C++ Strings, Input, and Output
Work with std::string, formatted output, token and line input, and stream-state validation without leaving unread data to break the next operation.
Before this lesson
Build and inspect std::string values
Choose between extraction and getline
Detect and recover from invalid stream input
The short answer
Use std::string for owned text, std::getline for full lines, and stream state to detect failed extraction. Decide whether an input is token-based or line-based and handle the boundary consistently.
Std string owns text
std::string manages a resizable sequence of characters and owns its storage. It can be copied, compared, appended, indexed, and queried with size. Unlike a raw character array, it handles allocation and cleanup automatically.
Indexing still requires a valid position. text[index] does not check bounds; text.at(index) checks and reports an error. Prefer range-based loops when the task needs every character rather than a position.
#include <iostream>
#include <string>
int main()
{
std::string first{"Build"};
std::string name{first + "Quill"};
std::cout << name << " has " << name.size() << " characters\n";
std::cout << "First character: " << name.at(0) << '\n';
}Output is a stream of values
std::cout accepts values through repeated insertion operators. Each value keeps its type until formatting converts it to characters. Include labels and units so output remains understandable without reading the source.
The iomanip header provides controls such as std::fixed, std::setprecision, and field widths. Formatting state can persist on a stream, so set it close to the report it governs rather than assuming defaults.
Token input and line input differ
std::cin >> value performs formatted extraction: it skips leading whitespace and reads one value of the destination type. std::getline(std::cin, text) reads through the delimiter and is appropriate for names or sentences containing spaces.
Mixing the two styles requires a boundary decision. One approach is to read full lines consistently and parse them with a string stream. Another is to discard the remaining newline deliberately before switching to getline. Do not scatter unexplained ignore calls until the sample appears to work.
| Input need | Approach | Risk to handle |
|---|---|---|
| One integer token | std::cin >> count | Failed conversion |
| One word | std::cin >> word | Stops at whitespace |
| Full line | std::getline | May receive a pending newline |
| Parse a line | std::istringstream | Extra tokens and failed fields |
Stream state is part of validation
Extraction returns the stream, whose Boolean state reports success. if (std::cin >> count) combines the read and check. On failure, the destination is not a trustworthy new value and the stream remains failed until its state is cleared.
For a one-attempt command-line tool, an error message and nonzero return may be best. For an interactive retry loop, clear the error and discard the invalid line before asking again. Range validation is separate: successfully reading -4 as an integer does not make it a valid quantity.
Quick knowledge check
Answer before you reveal.
01Why does operator>> stop before a space for a string?
Formatted extraction reads one whitespace-delimited token by default.
02What should happen after numeric extraction fails?
Do not use the destination as valid input. Take an error path or clear the stream state and discard the bad data before retrying.
Exercise
Practice challenge
Read a full product name and an integer quantity, reject a failed quantity extraction, and print a labeled order summary.
Requirements
- Product names may contain spaces
- Non-numeric quantity input produces an error path
- The program does not calculate with an invalid quantity
Optional extension: Format a price with exactly two decimal places using iomanip.
Open in C++ compilerLesson checkpoint
One small step locks it in
Mark this lesson complete, then keep the momentum going.
Clear up the details
Frequently asked questions
Why can getline return an empty line after operator>>?
Formatted extraction can leave the trailing newline unread, so the next getline consumes it unless the boundary is handled.
Is std::endl required for a new line?
No. It writes a newline and flushes the stream. Use '\n' unless an immediate flush is actually required.
Should errors go to cout?
std::cerr is the conventional diagnostic stream, allowing ordinary output and errors to be redirected separately.