C++ strings and string streams
Use std::string, parse text with getline and istringstream, and convert between text and numbers.
#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";
}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
#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";}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
| Step / line | What happens | State after step | Output 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".