Lab #3: Strings
Date: September 2, 2008

Ruby is a programmer-friendly language. As you would expect from that philosophy, strings in ruby are much-easier to use than strings in languages like C++ or Java.

  1. Single-quoted Strings

    Single quotes are the simplest way to create strings in Ruby. The only complication is how to add single quotes into such a string literal. We'll show an example of how not to do so below, followed by how to do so using a backslash escape. Only a small number of escape sequences exist in order to allow the presence of single quotes and newlines in such strings. Note that irb shows the value of the string you created using double-quoted string notation. String objects can be created in multiple ways, but no matter what type of quotes you use, the result is a String object, which irb always shows in the same way.

    $ irb
    irb(main):001:0> string = 'Hello Ruby'
    => "Hello Ruby"
    irb(main):002:0> string = 'Hello Ruby's Friend'
    irb(main):003:0' '
    SyntaxError: compile error
    (irb):2: syntax error, unexpected tIDENTIFIER, expecting $end
    string = 'Hello Ruby's Friend'
                          ^
            from (irb):2
            from :0
    irb(main):004:0> string = 'Hello Ruby\'s Friend'
    => "Hello Ruby's Friend"
    irb(main):005:0> string = 'A long string\
    irb(main):006:0' separated on two lines.'
    => "A long string\\\nseparated on two lines."
    irb(main):007:0> string.class
    => String
    
  2. Double-quoted Strings

    Double-quotes provide a more powerful way to create strings, allowing not only for a wider variety of escape sequences to encode newlines, tabs, and non-ASCII characters, but also providing the feature of string interpolation.

    $ irb
    irb(main):009:0> string = "Hello Ruby"
    => "Hello Ruby"
    irb(main):009:0> string.class
    => String
    irb(main):011:0> string = "Hello Ruby's Friend"
    => "Hello Ruby's Friend"
    irb(main):012:0> string = "He said, "Hello Ruby.""
    SyntaxError: compile error
    (irb):12: syntax error, unexpected tCONSTANT, expecting $end
    string = "He said, "Hello Ruby.""
                             ^
            from (irb):12
            from :0
    irb(main):013:0> string = "He said, \"Hello Ruby.\""
    => "He said, \"Hello Ruby.\""
    irb(main):019:0> string = "A long string\
    irb(main):020:0" separated on two lines."
    => "A long stringseparated on two lines."
    irb(main):021:0> puts string
    A long stringseparated on two lines.
    => nil
    irb(main):022:0> string = "A long string
    irb(main):023:0" separated on two lines."
    => "A long string\nseparated on two lines."
    irb(main):024:0> puts string
    A long string
    separated on two lines.
    => nil
    irb(main):025:0> puts "\tIndented text."
            Indented text.
    => nil
    irb(main):026:0> puts "Multiple lines printed\nFrom a one line string.\n"
    Multiple lines printed
    From a one line string.
    => nil
    irb(main):027:0> "1 + 1 == #{1 + 1}"
    => "1 + 1 == 2"
    irb(main):028:0> "360 degrees == #{2 * 3.1415926} radians"
    => "360 degrees == 6.2831852 radians"
    irb(main):031:0> animals = "Cats"
    => "Cats"
    irb(main):033:0> "#{animals} chase dogs."
    => "Cats chase dogs."
    irb(main):034:0> animals2 = "geckos"
    => "geckos"
    irb(main):035:0> "#{string} chase #{animals2}."
    => "Cats chase geckos."
    
  3. Choose your own quotes.

    Ruby allows you to choose your own string delimiters using the %q and %Q operators, which act like single-quotes and double-quotes respectively. This feature makes it convenient to deal with strings which would otherwise require many characters to be escaped. Strings containing larger numbers of escapes are difficult to read and can be difficult to write correctly too.

    $ irb
    irb(main):001:0> %q!A string with ' and " characters but no escapes!
    => "A string with ' and \" characters but no escapes"
    irb(main):003:0> %q!However \! must be escaped when using \! as a quote.!
    => "However ! must be escaped when using ! as a quote."
    irb(main):004:0> %q(You can use matched parentheses or ], }, > delimiters)
    => "You can use matched parentheses or ], }, > delimiters"
    irb(main):005:0> %q[String interpolation doesn't work here, see: #{1+1}]
    => "String interpolation doesn't work here, see: \#{1+1}"
    irb(main):006:0> %Q[String interpolation does work here, see: #{1+1}]
    => "String interpolation does work here, see: 2"
    irb(main):007:0> %q{Escapes don't work here: \n, \t, \f}
    => "Escapes don't work here: \\n, \\t, \\f"
    irb(main):008:0> %Q{Escapes work here: \n, \t, \f}
    => "Escapes work here: \n, \t, \f"
    irb(main):009:0> puts %Q{Escapes work here: \n, \t, \f}
    Escapes work here: 
    ,       , 
    
    => nil
    
  4. Here documents

    Ruby supports here documents like the shell does. Here documents are a convenient way to create long strings.

    irb(main):010:0> doc = <<END
    irb(main):011:0" This is a here document.
    irb(main):012:0" It stretches until we see the word E N D.
    irb(main):013:0" \tYou can indent and use other escapes.
    irb(main):014:0" You can even do interpolation: #{2 ** 24}
    irb(main):015:0" END
    => "This is a here document.\nIt stretches until we see the word E N D.\n\tYou can indent and use other escapes.\nYou can even do interpolation: 16777216\n"
    irb(main):016:0> puts doc
    This is a here document.
    It stretches until we see the word E N D.
            You can indent and use other escapes.
    You can even do interpolation: 16777216
    => nil
    irb(main):017:0> singlequotedoc = <<'END'
    irb(main):018:0' This is a here document.
    irb(main):019:0' It also stretches until we see the word E N D.
    irb(main):020:0' \tYou can't indent and use double-quote escapes.
    irb(main):021:0' You can't even do interpolation: #{2 ** 24}
    irb(main):022:0' END
    => "This is a here document.\nIt also stretches until we see the word E N D.\n\\tYou can't indent and use double-quote escapes.\nYou can't even do interpolation: \#{2 ** 24}\n"
    irb(main):023:0> puts singlequotedoc
    This is a here document.
    It also stretches until we see the word E N D.
    \tYou can't indent and use double-quote escapes.
    You can't even do interpolation: #{2 ** 24}
    => nil
    
  5. Characters

    As in most languages, strings are different from characters in Ruby. Characters are not the same as one-character long strings. If you give a string a single index, you're extracting a single character from the string. Note that the first character of the string is index 0, as it is in most languages. If we call the class method on a character, we'll find that characters are just numbers.

    $ irb
    irb(main):001:0> foo = "abcdefghijklmnopqrstuvwxyz"
    => "abcdefghijklmnopqrstuvwxyz"
    irb(main):002:0> foo[0]
    => 97
    irb(main):003:0> foo[0].class
    => Fixnum
    irb(main):004:0> 1.class
    => Fixnum
    

    Ruby characters are ASCII encoded by default. If you check an ASCII table, you'll find the numeric values of the characters there are identical to the ones given to you by ruby.

    $ irb
    irb(main):001:0> foo = "abcdefghijklmnopqrstuvwxyz"
    => "abcdefghijklmnopqrstuvwxyz"
    irb(main):002:0> foo[0]
    => 97
    irb(main):003:0> foo[1]
    => 98
    irb(main):004:0> foo[2]
    => 99
    irb(main):005:0> bar = "ABC"
    => "ABC"
    irb(main):006:0> bar[0]
    => 65
    irb(main):007:0> bar[1]
    => 66
    irb(main):008:0> bar[2]
    => 67
    

    If you want to turn a number into a corresponding one-character long ASCII string, use the chr method. Note that you specify a character using the ? character as shown below instead of looking up the ASCII numerical value. You can also use boolean comparisons on characters and strings in the same way you can use them with numbers.

    irb(main):009:0> 65.chr
    => "A"
    irb(main):010:0> bar[0].chr
    => "A"
    irb(main):011:0> ?B
    => 66
    irb(main):013:0> "A" < "B"
    => true
    irb(main):014:0> "C" < "B"
    => false
    
  6. Slicing Strings

    Using two numbers in brackets, slicing extracts a substring that starts with the first number (remember that the first character is indicated by zero, not one) and ends with the character before the last number. That means to extract the first character of the string, you need to use the slice [0,1].

    $ irb
    irb(main):001:0> foo = "a string"
    => "a string"
    irb(main):002:0> foo[0,1]
    => "a"
    irb(main):003:0> foo[0,3]
    => "a s"
    

    Note that you can write to string slices as well as read from them. You can even insert large substrings into a slice as we do below with "the."

    irb(main):004:0> foo[0,1] = "b"
    => "b"
    irb(main):005:0> foo
    => "b string"
    irb(main):006:0> foo[0,1] = "the"
    => "the"
    irb(main):007:0> foo
    => "the string"
    

    You can also use negative indices, which count from the end of the string. To get the last character of the string, we use the indices [-1,1].

    irb(main):008:0> foo[-1,1]
    => "g"
    

    Everything in ruby is an object, which means that slicing is the same as calling a method on a string. That method has the name [] and can be called with the dot syntax and arguments in parentheses like any other method as we see below.

    irb(main):009:0> foo.[](0,1)
    => "t"
    
  7. String Operators

    Strings provide operators other than the square bracket operator used for indexing. Ruby supports string concatenation as most languages do, and it also supports string multiplication. Most objects in Ruby support a method to_s which converts the object to a string. We use this method below to convert numbers to strings.

    
    
  8. String Conversion with to_s

    You cannot concatenate a number with a string. However, you can convert a number to a string, then concatentate the resulting string with the original string. Most objects in Ruby support a method to_s which converts the object to a string. We use this method below to convert numbers to strings. However, it's usually easier to use string interpolation instead of concatenation in this case.

    irb(main):004:0> 'One == ' + 1
    TypeError: can't convert Fixnum into String
            from (irb):4:in `+'
            from (irb):4
            from :0
    irb(main):005:0> 'One == ' + 1.to_s
    => "One == 1"
    irb(main):006:0> '1 + 1 == ' + (1+1).to_s
    => "1 + 1 == 2"
    irb(main):007:0> "1 + 1 == #{1+1}"
    => "1 + 1 == 2"
    
     

    ©2008 James Walden, Ph.D.