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;
return0;
}
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;
return0;
}
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;
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;
}
return0;
}
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;
}
return0;
}
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"?