What you'll learn
Useful programs exchange data with people, files, and other programs. C++ streams provide a typed interface for that exchange, while std::string gives text safe value semantics and automatic storage management.
By the end, you'll be able to:
- Route results and diagnostics through the correct standard stream
- Create, combine, inspect, and compare
std::stringvalues - Choose between token extraction and complete-line input
- Recover a failed input stream and parse structured text exactly
The standard streams
Streams model a sequence of characters plus state describing whether operations succeeded. The operating environment connects the standard C++ stream objects to three standard channels.
#include <iostream>
int main() {
std::cout << "Result: " << 42 << '\n';
std::clog << "Calculation completed\n";
bool valid{false};
if (!valid) {
std::cerr << "Error: value is invalid\n";
return 1;
}
}Key idea
std::cout and diagnostics on std::cerr orstd::clog. Shell users can then redirect data and errors independently.Output & formatting
The insertion operator << writes values from left to right. Manipulators from<iomanip> configure how later values are represented.
#include <iomanip>
#include <iostream>
int main() {
double price{19.5};
std::cout << std::fixed << std::setprecision(2);
std::cout << "Price: $" << price << '\n';
std::cout << std::left << std::setw(12) << "C++ course"
<< std::right << std::setw(6) << 30 << '\n';
std::cout << std::boolalpha << (price < 20.0) << '\n';
}| Manipulator | Effect |
|---|---|
std::fixed | Use fixed-point floating notation |
std::setprecision(n) | Set fractional digits with fixed; significant digits otherwise |
std::setw(n) | Set the minimum width of the next field only |
std::left / std::right | Choose field alignment |
std::boolalpha | Write true/false instead of 1/0 |
Tip
'\n' for an ordinary newline. std::endl also flushes the stream, which is useful only when an immediate flush is actually required.Working with std::string
std::string owns a growable sequence of characters. It copies and moves like a value, tracks its size, and manages its own storage—making it the normal choice for owned text in C++.
#include <iostream>
#include <string>
int main() {
std::string first{"Ada"};
std::string last{"Lovelace"};
std::string full{first + " " + last};
std::cout << full << '\n';
std::cout << "characters: " << full.size() << '\n';
std::cout << "first: " << full.front() << '\n';
if (full.starts_with("Ada")) {
std::cout << "Expected prefix\n";
}
}Watch out
text[index] does not check bounds. Use text.at(index)when a checked access is valuable, or prove index < text.size() first.Token input
Extraction with >> skips leading whitespace and reads one formatted token. For strings, it stops at whitespace; for numbers, it attempts a numeric conversion.
#include <iostream>
#include <string>
int main() {
std::string name;
int age{};
std::cout << "First name and age: ";
if (std::cin >> name >> age) {
std::cout << name << " is " << age << '\n';
} else {
std::cerr << "Expected a word followed by an integer\n";
return 1;
}
}Note
Ada 28. It does not fit a full name such as Ada Lovelace, because the first extraction stops at the space.Complete-line input
std::getline reads through the delimiter—newline by default—and stores the text without that delimiter. When switching from >>, consume leading whitespace deliberately with std::ws.
#include <iostream>
#include <string>
int main() {
int quantity{};
std::string description;
std::cout << "Quantity: ";
if (!(std::cin >> quantity)) return 1;
std::cout << "Description: ";
std::getline(std::cin >> std::ws, description);
std::cout << quantity << " × " << description << '\n';
}Watch out
getline(std::cin, description) immediately after numeric extraction may consume the leftover newline and return an empty string. std::getline(std::cin >> std::ws, description) solves that case, but it also discards intentional leading whitespace.Stream state & validation
A failed formatted extraction sets a failure state and leaves the offending characters in the stream. Recovery requires both clearing the state and discarding the invalid line before trying again.
#include <iostream>
#include <limits>
int read_age() {
while (true) {
std::cout << "Age (0-130): ";
int age{};
if (std::cin >> age && age >= 0 && age <= 130) {
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return age;
}
std::cout << "Please enter a whole number from 0 to 130.\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
int main() {
std::cout << "Accepted: " << read_age() << '\n';
}- Attempt the extraction
- Validate domain rules, not only syntax
- On failure, call
clear()to reset stream state - Call
ignore(..., '\n')to discard the bad line - Explain the expected input and retry
Parsing text
Reading a complete line first separates input acquisition from interpretation. A string stream can then parse the in-memory text without corrupting the state of std::cin.
#include <iostream>
#include <sstream>
#include <string>
bool parse_point(const std::string& text, int& x, int& y) {
std::istringstream input{text};
char comma{};
if (!(input >> x >> comma >> y) || comma != ',') return false;
input >> std::ws;
return input.eof(); // reject trailing non-whitespace text
}
int main() {
int x{};
int y{};
if (parse_point("12, -4", x, y)) {
std::cout << x << ' ' << y << '\n';
}
}Key idea
12,4junk. After parsing the expected fields, consume whitespace and verify end-of-input when the whole line must match the grammar.Type-safe formatting
C++20's std::format separates a format template from its typed arguments. It supports alignment, width, precision, numeric bases, and other presentation rules without permanently changing stream state.
#include <format>
#include <iostream>
int main() {
std::string language{"C++"};
int modules{30};
double progress{0.2};
std::cout << std::format(
"{} course: {} modules, {:.0%} drafted\n",
language, modules, progress);
}Note
<format>. Use stream formatting when your supported library lacks it, and document the minimum toolchain for projects that require it.Recap & quick check
Key takeaways
- cin reads standard input; cout carries results; cerr and clog carry diagnostics.
- std::string owns text, tracks its size, and behaves like a value.
- Formatted extraction reads tokens; getline reads complete lines.
- Recovering failed input requires clearing stream state and discarding invalid characters.
- Parse the complete expected grammar rather than accepting a valid prefix.
Quick check
1. Which stream should carry an error diagnostic?
2. Why can getline return an empty line after operator>>?
3. What two actions recover from invalid formatted input?
4. What does std::string::size report?
Your programs can now communicate reliably. Next: Module 4 — Decisions & Control Flow, where values begin directing program behavior.