Kodewick
Lesson 5 of 30Contents

Strings

Lesson 5 of 30 · Part 1 · Getting started · about 15 minutes

Names, addresses, product codes: text is everywhere in programs. C++ keeps a piece of text in a std::string (it needs #include <string>). Join two strings with +:

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string city = "Boston";6    std::string street = "Main Street";7    std::string address = street + ", " + city;8    std::cout << address << '\n';9    address += ", Apt 3";10    std::cout << address << '\n';11    return 0;12}
Output
Main Street, Boston
Main Street, Boston, Apt 3

+ joins pieces of text into a new string; += adds a piece to the end of the string you already have, just like += with numbers in lesson 4.

Length with size()

s.size() tells you how long a string is. The .size() after the variable is a member function, one that belongs to the string itself; you'll see many more written this way.

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string code = "AB-1024";6    std::string name = "café";7    std::cout << code.size() << '\n';8    std::cout << name.size() << '\n';9    return 0;10}
Output
7
5

AB-1024 has 7 characters, and shows 7. But café, with 4 letters, shows 5: size() counts bytes. Plain English letters, digits and symbols take 1 byte each, but é takes 2 here, and a Chinese character takes 3. That's why the examples below that pick characters by position stick to plain English letters and digits.

Characters by index

Each character in a string has a number, its index, starting from 0. s[0] is the first character and s[s.size() - 1] is the last. What you get is a char. A std::string can be changed: assign to s[i] and that character is replaced.

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string name = "jack";6    std::cout << name[0] << '\n';7    std::cout << name[name.size() - 1] << '\n';8    name[0] = 'J';9    std::cout << name << '\n';10    return 0;11}
Output
j
k
Jack

Press Step to watch name change from jack to Jack. Note the single quotes in 'J': name[0] is one character, so what goes in must be one character too.

Going out of range

"AB12" has only 4 characters, at indexes 0 to 3. Using s[10] to read a character that isn't there is undefined behavior: on an ordinary computer it might show some odd character, or something else might go wrong. Our engine stops at that line:

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string code = "AB12";6    std::cout << code[3] << '\n';7    std::cout << code[10] << '\n';8    return 0;9}
Output
2
index out of range

What happened: Stopped at line 7. This goes past the end of a vector, an array or a string. Real C++ would read or overwrite whatever is next in memory.

code[3] is the last character, 2, which is fine; code[10] is out of range. (C++ does let you read code[4]: it's an invisible empty character at the end of the string, of no use to you.) Before you use an index, ask yourself whether it's less than size().

substr and find

s.substr(start, n) takes n characters starting at index start and makes a new string of them; leave out n and it takes everything to the end. s.find("x") gives the index where x first appears. Together they can split an email address in two:

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string email = "[email protected]";6    auto at = email.find("@");7    std::cout << at << '\n';8    std::cout << email.substr(0, at) << '\n';9    std::cout << email.substr(at + 1) << '\n';10    return 0;11}
Output
3
ana
example.com

The @ is at index 3. substr(0, 3) is the first 3 characters, ana, and substr(4) runs from index 4 to the end. The type that find gives back has a long name, so this is a good place for auto.

When there is nothing to find, find gives back a special value, std::string::npos ("no position"):

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string email = "ana.example.com";6    auto at = email.find("@");7    std::cout << (at == std::string::npos) << '\n';8    return 0;9}
Output
1

It shows 1, meaning "true": not found. The == needs parentheses around it, or << would go first. Once you know if (lesson 6), you can do one thing when it's found and another when it isn't.

Comparing strings

== checks whether two strings are exactly the same; < and > compare them in dictionary order, character by character from the start:

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string a = "apple";6    std::string b = "banana";7    std::cout << (a == "apple") << '\n';8    std::cout << (a < b) << '\n';9    std::cout << ("Zoo" < a) << '\n';10    return 0;11}
Output
1
1
1

All three lines show 1. The last one may surprise you: characters are compared by their codes, and every capital letter comes before every small letter, so Zoo is less than apple.

Guess first

What does this program show?

1#include <iostream>2#include <string>3 4int main() {5    std::string a = "12";6    std::string b = "3";7    std::cout << a + b << '\n';8    return 0;9}

Numbers to strings and back

To put a number into a string, turn it into a string first with std::to_string. The other way round, std::stoi turns a string of digits into an int (the i is for int):

main.cpp
1#include <iostream>2#include <string>3 4int main() {5    int count = 3;6    std::string msg = "Your cart has " + std::to_string(count) + " items";7    std::cout << msg << '\n';8    std::string text = "42";9    int n = std::stoi(text);10    std::cout << n + 8 << '\n';11    return 0;12}
Output
Your cart has 3 items
50

text + "8" would be "428"; std::stoi(text) + 8 is 50. Numbers you get from input or from a file often arrive as strings, so convert them before doing math.

Practice

Write the code, then press Check. A hint costs nothing; the answer is there when you need it.

Exercise 1

Build a full name

Join first and last with + to show Hello, Ada Lovelace!.

It should print
Hello, Ada Lovelace!
exercise1.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string first = "Ada";6    std::string last = "Lovelace";7 8    return 0;9}
Output
Press Run or Ctrl+Enter
Exercise 2

The user name in an email

Use find and substr to take the part before the @, and show User: sam.lee.

It should print
User: sam.lee
exercise2.cpp
1#include <iostream>2#include <string>3 4int main() {5    std::string email = "[email protected]";6 7    return 0;8}
Output
Press Run or Ctrl+Enter
Exercise 3

Fix it: text plus a number

This program doesn't compile. Fix it so it shows Total: 5 items.

It should print
Total: 5 items
exercise3.cpp
1#include <iostream>2#include <string>3 4int main() {5    int count = 5;6    std::string msg = "Total: " + count + " items";7    std::cout << msg << '\n';8    return 0;9}
Output
Press Run or Ctrl+Enter

What you learned

  • A std::string holds text; + joins strings and += adds to the end.
  • s.size() counts bytes: 1 for each plain English character, more for others such as é or Chinese characters.
  • s[i] gives the character at index i, counting from 0; strings can be changed: s[0] = 'J';.
  • An index out of range (not less than size()) is undefined behavior, and the engine stops.
  • s.substr(start, n) takes a piece; s.find("x") finds a position, and gives std::string::npos when it can't.
  • == and < compare strings character by character, by code; capital letters come before small ones.
  • std::to_string(n) turns a number into a string, and std::stoi(s) turns a string into an int.