Lesson 38 min read

Input & Output with Streams

Streams are like conveyor belts β€” data flows in one direction, and you just place items on or pick them off

The Conveyor Belt Model

Forget printf and scanf for a moment. C++ introduces streams β€” a beautiful abstraction for I/O. Picture a conveyor belt in a factory:

  • cout β€” the output belt. You place items on it with <<, and they roll out to the screen.
  • cin β€” the input belt. Items arrive from the keyboard, and you pick them off with >>.
  • cerr β€” the emergency belt. Error messages go here β€” it's unbuffered, so they show up immediately.

The beauty of streams is type safety. Unlike printf("%d", x) where a wrong format specifier causes bugs, cout << x always knows the type of x and prints it correctly.

Basic Output with cout

#include <iostream>
using namespace std;
int main() {
string name = "Diana";
int age = 28;
double height = 5.7;
// Chain multiple items with <<
cout << "Name: " << name << endl;
cout << "Age: " << age << ", Height: " << height << endl;
// endl vs '\n'
cout << "This uses endl" << endl; // flushes the buffer
cout << "This uses \\n\n"; // just a newline, no flush β€” slightly faster
// Error output
cerr << "This is an error message!" << endl;
return 0;
}
Output
Name: Diana
Age: 28, Height: 5.7
This uses endl
This uses \n
This is an error message!

Reading Input with cin

cin >> reads one "token" at a time β€” it stops at whitespace (spaces, tabs, newlines). This is fine for single words or numbers, but falls apart when you need a full line with spaces.

That's where getline(cin, str) comes in. It reads everything until the newline, including spaces.

cin >> vs getline

#include <iostream>
#include <string>
using namespace std;
int main() {
// cin >> reads one token (stops at whitespace)
int age;
cout << "Enter your age: ";
cin >> age;
cout << "You entered: " << age << endl;
// Problem: cin >> with strings stops at the first space
string word;
cout << "Enter a word: ";
cin >> word;
cout << "Got: " << word << endl; // only gets first word!
cin.ignore(); // ⚠️ clear the leftover newline!
// getline reads the entire line (including spaces)
string fullName;
cout << "Enter your full name: ";
getline(cin, fullName);
cout << "Hello, " << fullName << "!" << endl;
return 0;
}
Output
Enter your age: 25
You entered: 25
Enter a word: hello
Got: hello
Enter your full name: John Doe
Hello, John Doe!
Note: cin >> stops at whitespace. Use getline(cin, str) for full lines. But mixing cin >> and getline causes a sneaky newline bug β€” after cin >>, a leftover '\n' sits in the buffer, and getline reads it as an empty line. Fix: call cin.ignore() between them to discard that lurking newline.

Formatted Output with iomanip

Need to line up columns in a table? Control decimal places? Pad numbers with zeros? The <iomanip> header has you covered. It provides manipulators β€” special objects you insert into the stream to change how the next item is formatted.

  • setw(n) β€” set the minimum width of the next output field
  • setprecision(n) β€” control how many digits appear
  • fixed β€” use fixed-point notation (not scientific)
  • left / right β€” alignment within the field width
  • setfill(c) β€” fill extra space with character c instead of spaces

Formatting with iomanip

#include <iostream>
#include <iomanip>
using namespace std;
int main() {
// Controlling decimal places
double pi = 3.141592653589793;
cout << "Default: " << pi << endl;
cout << "fixed(2): " << fixed << setprecision(2) << pi << endl;
cout << "fixed(6): " << fixed << setprecision(6) << pi << endl;
// Reset to default
cout << defaultfloat;
// Table alignment with setw
cout << "\n--- Price List ---" << endl;
cout << left << setw(15) << "Item" << right << setw(8) << "Price" << endl;
cout << left << setw(15) << "Coffee" << right << setw(8) << fixed << setprecision(2) << 4.50 << endl;
cout << left << setw(15) << "Sandwich" << right << setw(8) << 8.99 << endl;
cout << left << setw(15) << "Cake" << right << setw(8) << 12.00 << endl;
// Padding with setfill
cout << "\nOrder #" << setfill('0') << setw(5) << 42 << endl;
return 0;
}
Output
Default:    3.14159
fixed(2):   3.14
fixed(6):   3.141593

--- Price List ---
Item                Price
Coffee               4.50
Sandwich             8.99
Cake                12.00

Order #00042

String Streams β€” Streams Without I/O

Sometimes you want to build a formatted string without printing it. stringstream from <sstream> is a stream that reads from and writes to a string in memory. Think of it as a conveyor belt that loops back on itself β€” you put things on, then take the assembled result off as a single string.

This is incredibly handy for parsing strings or building complex output.

String Streams

#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
// Building a string with ostringstream
ostringstream oss;
oss << "Score: " << 42 << "/" << 50 << " (" << 84.0 << "%)";
string report = oss.str();
cout << report << endl;
// Parsing a string with istringstream
string data = "Alice 95 Bob 87 Carol 92";
istringstream iss(data);
string name;
int score;
while (iss >> name >> score) {
cout << name << " scored " << score << endl;
}
return 0;
}
Output
Score: 42/50 (84%)
Alice scored 95
Bob scored 87
Carol scored 92

Reading Until EOF

A common pattern is reading input until there's nothing left β€” useful for competitive programming or processing piped files. You can loop on cin >> variable since it returns a reference that converts to false when the stream is exhausted.

Reading Until End of Input

#include <iostream>
#include <string>
using namespace std;
int main() {
// Reading numbers until EOF (Ctrl+D on Mac/Linux, Ctrl+Z on Windows)
int num;
int sum = 0;
int count = 0;
cout << "Enter numbers (Ctrl+D to stop):" << endl;
while (cin >> num) {
sum += num;
count++;
}
if (count > 0) {
cout << "Sum: " << sum << endl;
cout << "Average: " << (double)sum / count << endl;
}
return 0;
}
Output
Enter numbers (Ctrl+D to stop):
10 20 30 40
Sum: 100
Average: 25
Challenge

Quick check

What happens if you use cin >> name to read "John Doe"?
← Operators & ExpressionsConditionals β†’