Skip to main content

Section 9.6 Indexes in strings

Recall that we said that a string is an object that combines some methods (functions) like size() with data. Well, the data a string needs to store is a list of characters. The characters in a string are indexed, or numbered, starting from 0:
0 1 2 3 4 5 6 7 8 9 10
H e l l o W o r l d
Note that:
  • The first character, 'H', is at index 0. Index 1 refers to the second character. This may be a little confusing at first, but it is a common way of numbering things in programming. (A good way to remember this that also hints at the reason for the conventionโ€”the first character is 0 bytes from the start of the string.)
  • The string Hello World is 11 characters long. That is the answer size() would give you.
  • Because we start counting from 0, the last character is at index 10. The last character in a string is always at position size() - 1.
To access characters in a string, string objects provide a function char at(size_t index). Given a location in the string, it returns the char at that index:
Listing 9.6.1. This active code outputs various characters from the string myString.
Attempting to access a bad index like -1 or a number greater than or equal to the size results in a run time error:
Listing 9.6.2.
If we read carefully, we can see the error message tells us there was an out_of_range problem using the value 100 in a string with size() (which is 11). Notice however that it does not tell us the line number the error occurred on. If it was not obvious we would need to use a debugger or print statements to identify the location. Here, we can tell that the error happened before the line that prints "Well, that didn't work." as we do not see it in the output.

Warning 9.6.1.

A common source of error involving strings and other arrays is indexing out of bounds. This is usually the result of forgetting to subtract 1 from size. Asking for index 11 in this string would cause an error.
You can also use the at() function to change the value of a character in a string by assigning a new character to the location:
Listing 9.6.3.

Warning 9.6.2. The [ ] syntax and its dangers.

There is another way to work with the characters in strings. Instead of myString.at(index) we can say myString[index]. The โ€œbracket notationโ€ (the [ ]) works the same as .at(), except for one critical difference. When you use a bad index with the brackets, no error is generated. Instead, your code reads from or writes to whatever is in memory either before or after the stringโ€™s characters. This can cause your code to modify some other variable, or some other important part of the code of your program!
.at() is โ€œsafeโ€ because it prevents you from accidentally doing bad things without knowing about it. [ ] is dangerous because it does whatever you ask it to, even if that makes no sense.
Why is there an unsafe version? It can be slightly faster to not stop and check if the index makes sense before using it. But only VERY slightly faster. You would have to be doing many thousands of string operations before the speed difference became noticeable to a person. And compilers can often detect from what your other code is doing that the safety check isnโ€™t needed and skip it.
C++ has a reputation for being a โ€œdangerous languageโ€ because it doesnโ€™t always protect programmers from their own mistakes. One way to make the language safer is to avoid the โ€œdangerousโ€ way of doing things unless we have a very good reason not to. For this reason, we will only use .at() notation in this book.

Checkpoint 9.6.1.

What would replace the โ€œ?โ€ in order to access the letter โ€œbโ€ in the string below?
string bake = "bake a cake!";
char letter = bake.at(?);
  • Donโ€™t forget that computer scientists do not start counting at 1!
  • Yes, this would access the letter "b".
  • This would access the letter "k".

Checkpoint 9.6.2.

What value does lunch end up with?
string lunch = "hello";
lunch.at(0) = lunch.at(3);
  • lunch
  • When we cout a string we print its content not its name.
  • jello
  • Carefully check which string(s) we are indexing into.
  • lello
  • Correct! We copy the โ€™lโ€™ from position 3 of "hello" to position 0.
  • heljo
  • Consider which string(s) we are indexing into.
You have attempted of activities on this page.