C++ strings and string streams

Use std::string, parse text with getline and istringstream, and convert between text and numbers.

C++
#include <iostream>
#include <sstream>
#include <string>

int main() {
  std::string text = "Programonic is fun";
  std::cout << text.size() << " " << text.substr(0, 7) << " " << text.find("is") << "\n";

  std::istringstream input("alpha 3\nbeta 5\ngamma x\n");
  std::string line;
  int total = 0;
  while (std::getline(input, line)) {
    std::istringstream fields(line);
    std::string name;
    int value;
    if (fields >> name >> value) {
      std::cout << name << "=" << value << "\n";
      total += value;
    } else {
      std::cout << "bad line: " << line << "\n";
    }
  }
  std::cout << "total " << total << "\n";
  std::cout << std::to_string(42) + "!" << " " << std::stoi("123") + 1 << "\n";
}
Output
18 Program 12
alpha=3
beta=5
bad line: gamma x
total 8
42! 124

Explanation

std::string manages its own memory and grows as needed. size gives the length, substr extracts part of the text, and find returns the position of a match or std::string::npos if there is none. Unlike a C string, it needs no terminating zero handling and is safe to copy and concatenate.

A string stream reads and writes text the way cin and cout do. std::istringstream wraps a string so that getline can split it into lines and the extraction operator >> can read a word and a number from each. If an extraction fails, the stream is put into a failed state, which makes it easy to detect bad lines. std::to_string and std::stoi convert between numbers and text.

Explore the dry run
Guided walkthroughReady
1#include <iostream>
2#include <sstream>
3#include <string>
4
5int main() {
6 std::string text = "Programonic is fun";
7 std::cout << text.size() << " " << text.substr(0, 7) << " " << text.find("is") << "\n";
8
9 std::istringstream input("alpha 3\nbeta 5\ngamma x\n");
10 std::string line;
11 int total = 0;
12 while (std::getline(input, line)) {
13 std::istringstream fields(line);
14 std::string name;
15 int value;
16 if (fields >> name >> value) {
17 std::cout << name << "=" << value << "\n";
18 total += value;
19 } else {
20 std::cout << "bad line: " << line << "\n";
21 }
22 }
23 std::cout << "total " << total << "\n";
24 std::cout << std::to_string(42) + "!" << " " << std::stoi("123") + 1 << "\n";
25}

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
18 characters; substr(0, 7) takes 7 characters from the start; the word is begins at index 12.—
18 Program 12
A string stream that behaves like an input file with three lines.—
18 Program 12
Read one line at a time until the stream is exhausted.—
18 Program 12
Reading a word and an int succeeds for the first two lines. For gamma x the int extraction fails.—
18 Program 12
Two good lines are printed and summed.—
18 Program 12
alpha=3
beta=5
The third line is reported instead of being silently misread.—
18 Program 12
alpha=3
beta=5
bad line: gamma x
3 + 5.—
18 Program 12
alpha=3
beta=5
bad line: gamma x
total 8
to_string builds text from a number; stoi parses text into a number.—
18 Program 12
alpha=3
beta=5
bad line: gamma x
total 8
42! 124

Cost and common mistakes

Parsing is O(n) for n characters.

  • find returns std::string::npos, a huge unsigned value, when nothing matches. Compare against npos, not against -1 in a signed variable.
  • std::stoi throws std::invalid_argument for text such as abc and std::out_of_range for huge values. Catch them for untrusted input.
  • operator>> skips leading white space and stops at the next white space, so it is not suitable for reading a whole line with spaces. Use getline for that.

Try it yourself

What does text.substr(8) return?

Reveal answer and reasoning

The rest of the string from index 8: "nic is fun".

Further reading