Ruby/Łańcuchy znakowe

Łańcuchy znakowe

edytuj

Ruby radzi sobie z łańcuchami znakowymi tak dobrze jak z danymi numerycznymi. Łańcuch może być ograniczony znakami podwójnego cudzysłowu ("...") lub pojedynczego (apostrof) ('...').

irb(main):001:0> "abc"
=> "abc"
irb(main):002:0> 'abc'
=> "abc"

Używanie podwójnych lub pojedynczych cudzysłowów czasami może mieć różne efekty. Łańcuch ujęty w podwójny cudzysłów pozwala stosować znaki formatujące za pomocą odwróconego ukośnika oraz obliczać zagnieżdżone wyrażenia używając #{}. Łańcuch ujęty w apostrofy nie pozwala na taką interpretację; to co widzisz - to dostajesz. Przykłady:

irb(main):001:0> puts "a\nb\nc"
a
b
c
=> nil
irb(main):002:0> puts 'a\nb\nc'
a\nb\nc
=> nil
irb(main):003:0> "\n"
=> "\n"
irb(main):004:0> '\n'
=> "\\n"
irb(main):005:0> "\001"
=> "\001"
irb(main):006:0> '\001'
=> "\\001"
irb(main):007:0> "abcd #{5*3} efg"
=> "abcd 15 efg"
irb(main):008:0> var = " abc "
=> " abc "
irb(main):009:0> "1234#{var}5678"
=> "1234 abc 5678"

Manipulowanie łańcuchami w Rubim jest sprytniejsze i bardziej intuicyjne niż w C. Dla przykładu, możesz łączyć ze sobą łańcuch używając +, a powtarzać łańcuch wiele razy za pomocą *:

irb(main):001:0> "foo" + "bar"
=> "foobar"
irb(main):002:0> "foo" * 2
=> "foofoo"

Konkatenacja łańcuchów w C jest bardziej kłopotliwa z powodu konieczności bezpośredniego zarządzania pamięcią:

char *s = malloc(strlen(s1)+strlen(s2)+1);
strcpy(s, s1);
strcat(s, s2);
/* ... */
free(s);

W Rubim natomiast, nie musimy w ogóle zastanawiać się nad miejscem zajmowanym w pamięci przez łańcuch. Jesteśmy wolni od jakiegokolwiek zarządzania pamięcią.

Oto kilka rzeczy, które możesz zrobić z łańcuchami.

Konkatenacja:

slowo = "fo" + "o" 
puts slowo #=> "foo"

Powtórzenie:

slowo = slowo * 2 
puts slowo #=> "foofoo"

Ekstrahowanie znaków (zauważ, że znaki w Rubim są liczbami całkowitymi):

puts slowo[0]     #=> 102
# 102 jest kodem ASCII znaku `f'

puts slowo[-1]    #=> 111
# 111 jest kodem ASCII znaku `o'

(Wartości ujemne oznaczają liczbę znaków od końca łańcucha.)

Ekstrahowanie podłańcuchów:

warzywo = "pietruszka"
puts warzywo[0,1]    #=> "p"
puts warzywo[-2,2]   #=> "ka"
puts warzywo[0..3]   #=> "piet"
puts warzywo[-5..-2] #=> "uszk"

Sprawdzanie równości:

puts "foo" == "foo" #=> true
puts "foo" == "bar" #=> false

Zróbmy użytek z kilku tych cech. Oto zgadywanka "co to za słowo", ale być może słowo "zgadywanka" to zbyt dużo dla tego kodu. ;-)

# zapisz to jako zgadnij.rb
slowa = ['fiolek', 'roza', 'bez']
sekret = slowa[rand(3)]

print "zgadniesz? "
while odp = STDIN.gets
  odp.chop!
  if odp == sekret
    puts "Wygrales!"
    break
  else
    puts "Przykro mi, przegrales."
  end
  print "zgadniesz? "
end
puts "Chodzilo o " + sekret + "."

Na razie nie przejmuj się za bardzo szczegółami powyższego kodu. Oto jak wygląda uruchomiona łamigłówka.

% ruby zgadnij.rb
zgadniesz? fiolek
Przykro mi, przegrales.
zgadniesz? bez
Przykro mi, przegrales.
zgadniesz? ^D
Chodzilo o roza.

(Mogło nam pójść nieco lepiej biorąc pod uwagę, że szansa na trafienie wynosi 1/3.)