Input/Output in C++


Input/Output in C++ Interview with follow-up questions

1. What is the role of cin and cout in C++?

cin and cout are the standard input and output stream objects defined in `. They are instances ofstd::istreamandstd::ostream` respectively, and are part of C++'s stream I/O system.

cout — standard output

Uses the insertion operator << to write formatted data to the console (stdout):

#include 
int main() {
    int x = 42;
    std::cout << "The answer is " << x << '\n';
}
  • std::endl flushes the buffer and writes a newline. Prefer '\n' when you don't need the flush — it is significantly faster in tight loops.
  • std::cout is buffered; output may not appear until the buffer is flushed.

cin — standard input

Uses the extraction operator >> to read formatted data from the console (stdin):

int age;
std::cin >> age;
  • >> skips leading whitespace and stops at the next whitespace character — it does not read whole lines.
  • To read a full line including spaces, use std::getline(std::cin, str).
  • Always check the stream state after reading: if (!(std::cin >> age)) { /* handle error */ }.

C++20 addition — std::print / std::println

C++23 introduces std::print and std::println in `as type-safe,std::format-based replacements forprintf`-style output:

#include 
std::println("The answer is {}", 42);   // C++23

Common interview points:

  • cin/cout are tied by default: reading from cin flushes cout first (to ensure prompts appear before input is read).
  • std::ios_base::sync_with_stdio(false) and std::cin.tie(nullptr) together can give significant performance gains in competitive-programming style I/O, at the cost of losing synchronisation with C-style printf/scanf.
  • cout is a global object — it is not thread-safe by default. In C++20, std::osyncstream wraps an output stream to make concurrent writes safe.
↑ Back to top

Follow-up 1

How would you use cin and cout to take input and display output?

To take input using cin, you can use the >> operator. For example:

cin >> variable; // Reads input from the user and stores it in the variable

To display output using cout, you can use the << operator. For example:

cout &lt;&lt; "Hello, World!"; // Displays "Hello, World!" on the console

You can also chain multiple inputs or outputs together using the >> and << operators. For example:

cin &gt;&gt; variable1 &gt;&gt; variable2; // Reads two inputs from the user and stores them in variable1 and variable2 respectively
cout &lt;&lt; "The sum is: " &lt;&lt; sum; // Displays the sum on the console

Follow-up 2

What are the differences between cin and scanf, cout and printf?

The main differences between cin and scanf, cout and printf are:

  1. Syntax: cin and cout are part of the C++ standard library and use the >> and << operators for input and output respectively. scanf and printf are part of the C standard library and use format specifiers for input and output.

  2. Type Safety: cin and cout are type-safe, meaning they perform type checking at compile-time. scanf and printf are not type-safe, meaning they can lead to runtime errors if the format specifiers do not match the types of the variables.

  3. Error Handling: cin and cout have built-in error handling mechanisms. They set the failbit and badbit flags when an error occurs, which can be checked using the fail() and bad() member functions. scanf and printf do not have built-in error handling mechanisms.

  4. Performance: cin and cout are generally slower than scanf and printf due to the additional type checking and error handling overhead.

Follow-up 3

What are the manipulators in C++?

Manipulators in C++ are special functions that can be used with the output stream cout to modify the way data is displayed. They are used to control formatting options such as setting the width, precision, and alignment of the output. Some commonly used manipulators in C++ include:

  • setw(n): Sets the width of the next output field to n characters.
  • setprecision(n): Sets the precision (number of decimal places) of floating-point values to n.
  • setfill(c): Sets the fill character for the output fields to c.
  • left: Sets the alignment of the output fields to left-justified.
  • right: Sets the alignment of the output fields to right-justified.

Manipulators can be used by including the header file and using the manipulator functions with the cout stream. For example:

#include 
#include 

int main() {
    int num = 42;
    double pi = 3.14159;

    std::cout &lt;&lt; std::setw(10) &lt;&lt; num &lt;&lt; std::endl; // Output: "        42"
    std::cout &lt;&lt; std::setprecision(3) &lt;&lt; pi &lt;&lt; std::endl; // Output: "3.14"
    std::cout &lt;&lt; std::setfill('*') &lt;&lt; std::setw(10) &lt;&lt; num &lt;&lt; std::endl; // Output: "********42"
    std::cout &lt;&lt; std::left &lt;&lt; std::setw(10) &lt;&lt; num &lt;&lt; std::endl; // Output: "42        "
    std::cout &lt;&lt; std::right &lt;&lt; std::setw(10) &lt;&lt; num &lt;&lt; std::endl; // Output: "        42"

    return 0;
}

2. What is the use of get() and getline() functions in C++?

Both functions are declared in (and for the std::string overload of getline) and address a gap that operator&gt;&gt; cannot fill: reading input that includes whitespace.

istream::get()

Reads a single character without skipping whitespace, or reads into a char buffer up to a delimiter.

char ch;
std::cin.get(ch);              // read one character, including spaces and newlines

char buf[80];
std::cin.get(buf, 80);         // read up to 79 chars, stop before newline, leave newline in stream
std::cin.get(buf, 80, '\t');   // custom delimiter

Key behaviour: get(buf, n) leaves the delimiter in the stream. A subsequent get or &gt;&gt; will see it immediately.

std::getline()

Reads an entire line from a stream into a std::string, consuming and discarding the newline.

#include 
std::string line;
std::getline(std::cin, line);      // reads until newline, discards newline
std::getline(std::cin, line, ','); // custom delimiter

This is the idiomatic way to read a full line in modern C++.

Critical gotcha: mixing &gt;&gt; and getline

operator&gt;&gt; leaves the newline in the stream. A getline called immediately after will read an empty line:

int n;
std::cin &gt;&gt; n;
std::cin.ignore(std::numeric_limits::max(), '\n'); // discard leftover newline
std::string name;
std::getline(std::cin, name);  // now reads correctly

Always call std::cin.ignore(...) to consume the trailing newline before switching to getline.

Choosing between them:

Situation Use
Read one character including whitespace get(ch)
Read a full line into a std::string std::getline(cin, str)
Read fixed-width input into a char buffer get(buf, n)
General token reading (skips whitespace) operator&gt;&gt;
↑ Back to top

Follow-up 1

What is the difference between get() and getline()?

The main difference between get() and getline() functions in C++ is how they handle input.

The get() function reads a single character at a time and stops reading when it encounters a newline character. It does not discard the newline character and leaves it in the input stream. This can cause issues when using get() in combination with other input functions.

The getline() function, on the other hand, reads a line of text until it encounters a newline character or reaches the specified maximum number of characters. It automatically discards the newline character and stores only the text in the string variable. This makes it more convenient for reading lines of text from the input stream.

Follow-up 2

Can you provide an example of how to use get() and getline()?

Sure! Here's an example that demonstrates the usage of get() and getline() functions in C++:

#include 
#include 

int main() {
    char ch;
    std::string line;

    // Using get()
    std::cout &lt;&lt; "Enter a character: ";
    std::cin.get(ch);
    std::cout &lt;&lt; "You entered: " &lt;&lt; ch &lt;&lt; std::endl;

    // Using getline()
    std::cout &lt;&lt; "Enter a line of text: ";
    std::getline(std::cin, line);
    std::cout &lt;&lt; "You entered: " &lt;&lt; line &lt;&lt; std::endl;

    return 0;
}

In this example, get() is used to read a single character from the user, while getline() is used to read a line of text. The entered character and line of text are then displayed on the console.

Follow-up 3

In what scenarios would you prefer getline() over get()?

You would prefer to use getline() over get() in the following scenarios:

  1. When you want to read a line of text that may contain spaces. get() stops reading when it encounters a whitespace character, while getline() reads the entire line including spaces.

  2. When you want to read a line of text that may exceed a certain length. get() requires you to specify the maximum number of characters to read, while getline() automatically adjusts to the length of the input line.

  3. When you want to read multiple lines of text. get() can only read a single character at a time, while getline() can read an entire line of text at once.

Overall, getline() provides more flexibility and convenience for reading lines of text from the input stream.

3. How can you redirect output from console to a file in C++?

There are two common approaches: redirecting at the OS shell level, or redirecting programmatically inside C++ code.

1. Shell-level redirection (most common in practice)

Run the compiled program and redirect its stdout at the command line:

./myprogram &gt; output.txt    # overwrite
./myprogram &gt;&gt; output.txt   # append

This requires no code changes and is the standard deployment approach.

2. Programmatic redirection using rdbuf()

Replace std::cout's internal stream buffer with an ofstream's buffer:

#include 
#include 

int main() {
    std::ofstream outFile("output.txt");
    if (!outFile) {
        std::cerr &lt;&lt; "Failed to open output file\n";
        return 1;
    }

    // Save original buffer and redirect cout
    std::streambuf* originalBuf = std::cout.rdbuf(outFile.rdbuf());

    std::cout &lt;&lt; "This goes to output.txt\n";

    // Restore original cout buffer before outFile is destroyed
    std::cout.rdbuf(originalBuf);

    std::cout &lt;&lt; "This goes to console again\n";
    return 0;
}

Important: restore std::cout's buffer before outFile goes out of scope. If outFile is destroyed while std::cout still points to its buffer, any subsequent output through std::cout is undefined behaviour.

3. Writing directly to a file stream (preferred for new code)

Rather than redirecting cout, simply use std::ofstream directly for file output:

#include 
#include    // C++23

int main() {
    std::ofstream log("output.txt");
    log &lt;&lt; "Writing directly to file\n";
    std::println(log, "C++23 formatted: {}", 42);  // std::println accepts any ostream
}

This is clearer, safer, and avoids the global-state mutation of redirecting std::cout.

Common interview follow-up: "How do you redirect both stdout and stderr to the same file?" — At the shell: ./prog &gt; out.txt 2&gt;&amp;1. In code: redirect both std::cout and std::cerr buffers to the same ofstream.

↑ Back to top

Follow-up 1

What is the syntax to redirect output to a file?

The syntax to redirect output to a file in C++ is using the stream redirection operator &gt; or &gt;&gt;. The &gt; operator is used to redirect and overwrite the contents of the file, while the &gt;&gt; operator is used to append the output to an existing file.

Here is an example:

#include 
#include 

int main() {
    std::ofstream outputFile("output.txt");
    std::streambuf* originalCoutBuffer = std::cout.rdbuf();
    std::cout.rdbuf(outputFile.rdbuf());

    // Output will be redirected to output.txt
    std::cout &lt;&lt; "Hello, World!";

    // Restore the original cout buffer
    std::cout.rdbuf(originalCoutBuffer);

    return 0;
}

Follow-up 2

What happens if the file already exists?

If the file already exists and you use the &gt; operator to redirect the output, the contents of the file will be overwritten with the new output. If you use the &gt;&gt; operator, the output will be appended to the existing contents of the file.

Here is an example:

#include 
#include 

int main() {
    std::ofstream outputFile("output.txt");
    std::streambuf* originalCoutBuffer = std::cout.rdbuf();
    std::cout.rdbuf(outputFile.rdbuf());

    // Output will be appended to output.txt
    std::cout &lt;&lt; "Hello, World!";

    // Restore the original cout buffer
    std::cout.rdbuf(originalCoutBuffer);

    return 0;
}

Follow-up 3

How can you append to an existing file instead of overwriting it?

To append to an existing file instead of overwriting it, you can use the &gt;&gt; operator for stream redirection. This will append the output to the existing contents of the file.

Here is an example:

#include 
#include 

int main() {
    std::ofstream outputFile("output.txt", std::ios::app);
    std::streambuf* originalCoutBuffer = std::cout.rdbuf();
    std::cout.rdbuf(outputFile.rdbuf());

    // Output will be appended to output.txt
    std::cout &lt;&lt; "Hello, World!";

    // Restore the original cout buffer
    std::cout.rdbuf(originalCoutBuffer);

    return 0;
}

4. What is the use of cerr and clog in C++?

cerr and clog are both output streams defined in `that write to the standard error device (stderr). They exist separately fromcout` (stdout) so that diagnostic output can be separated from normal program output — for example, piping stdout to a file while still seeing errors on the terminal.

std::cerr — unbuffered error output

  • Writes immediately to stderr without buffering.
  • Use for urgent error messages where you need the output to appear even if the program crashes immediately afterward.
if (!file.is_open()) {
    std::cerr &lt;&lt; "Error: could not open file\n";
    return 1;
}

std::clog — buffered log output

  • Writes to stderr but through a buffer, making it more efficient for high-volume logging.
  • The buffer is flushed when it fills up or when explicitly flushed with std::flush or std::endl.
  • Use for non-critical diagnostic messages and logging where a slight delay is acceptable.
std::clog &lt;&lt; "Processing record " &lt;&lt; id &lt;&lt; '\n';

Comparison table:

cerr clog
Destination stderr stderr
Buffered No Yes
Use case Fatal errors, crash-time output Logging, diagnostics
Performance Slower (flush per write) Faster for repeated writes

Modern practice:

In production code, cerr and clog are often supplemented or replaced by a structured logging library (spdlog, Abseil logging, etc.) that offers log levels, timestamps, and file rotation. However, understanding these standard streams is still expected in C++ interviews.

Common follow-up: "Why would stderr be separate from stdout?" — So that when you redirect ./prog &gt; data.txt, error messages still appear on the console. It also lets tools like make capture build output while showing errors to the user.

↑ Back to top

Follow-up 1

What is the difference between cerr and cout?

The main difference between cerr and cout is that cerr is used for writing error messages, while cout is used for general output. cerr is typically used when you want to display error messages or diagnostic information that should be immediately visible, even if the standard output (cout) is redirected or piped to another program. cerr is an unbuffered stream, which means that the output is immediately written to the standard error device. On the other hand, cout is a buffered stream, which means that the output is stored in a buffer and is written to the standard output device when the buffer is full or when the program terminates normally.

Follow-up 2

In what scenarios would you use cerr instead of cout?

cerr is typically used when you want to display error messages or diagnostic information that should be immediately visible, even if the standard output (cout) is redirected or piped to another program. Some scenarios where cerr is commonly used include:

  • Reporting critical errors or exceptions
  • Logging error messages or warnings
  • Displaying diagnostic information during debugging

By using cerr instead of cout, you ensure that the error messages are immediately visible to the user or developer, regardless of the program's output redirection or piping.

Follow-up 3

What is the difference between cerr and clog?

The main difference between cerr and clog is that cerr is an unbuffered stream, while clog is a buffered stream. This means that cerr immediately writes the output to the standard error device, while clog stores the output in a buffer and writes it to the standard error device when the buffer is full or when the program terminates normally. In terms of usage, cerr is typically used for critical error messages or immediate diagnostic information, while clog is used for general logging or informational messages that do not require immediate visibility.

5. What is the concept of streams in C++?

A stream in C++ is an abstraction representing a sequence of characters flowing to or from a source or destination (console, file, string, network socket, etc.). The stream model decouples the I/O operations in your code from the actual device, so the same &lt;&lt; and &gt;&gt; operators work identically whether you are writing to the screen, a file, or an in-memory buffer.

The stream class hierarchy (,, ``):

ios_base
  └── basic_ios
        ├── basic_istream  (std::istream)
        │     ├── std::cin
        │     └── std::ifstream
        ├── basic_ostream  (std::ostream)
        │     ├── std::cout / cerr / clog
        │     └── std::ofstream
        └── basic_iostream
              └── std::fstream / std::stringstream

Main stream categories:

Category Classes Purpose
Console I/O cin, cout, cerr, clog Read/write to terminal
File I/O ifstream, ofstream, fstream Read/write files
String I/O istringstream, ostringstream, stringstream Read/write in-memory strings

Stream state flags:

Streams maintain internal state bits you must check after operations:

  • good() — no errors
  • eof() — end of input reached
  • fail() — logical error (e.g., reading a non-integer into an int)
  • bad() — unrecoverable I/O error
int n;
if (!(std::cin &gt;&gt; n)) {
    std::cin.clear();                   // reset error flags
    std::cin.ignore(1000, '\n');        // discard bad input
}

Stream manipulators:

Streams are configured via manipulators from ``:

std::cout &lt;&lt; std::fixed &lt;&lt; std::setprecision(2) &lt;&lt; 3.14159;  // "3.14"
std::cout &lt;&lt; std::hex &lt;&lt; 255;                                  // "ff"
std::cout &lt;&lt; std::setw(10) &lt;&lt; std::left &lt;&lt; "hello";           // "hello     "

Modern alternative for output formatting — std::format (C++20):

Rather than manipulators, std::format provides Python-style, type-safe formatting without touching stream state:

#include 
std::cout &lt;&lt; std::format("{:.2f}\n", 3.14159);  // "3.14"

C++23 adds std::print/std::println which write a formatted string directly to a stream.

Key interview point: Because streams share a common base class (std::ostream), you can write functions that accept any output stream by reference — making code reusable across console, file, and string destinations:

void printReport(std::ostream&amp; out, const Data&amp; d) {
    out &lt;&lt; std::format("Name: {}, Value: {}\n", d.name, d.value);
}
// Call with cout, ofstream, or ostringstream interchangeably
↑ Back to top

Follow-up 1

What are the different types of streams in C++?

In C++, there are two types of streams: input streams and output streams.

  1. Input streams: These streams are used for reading data from a source. Examples of input streams include cin (standard input stream) and ifstream (file input stream).

  2. Output streams: These streams are used for writing data to a destination. Examples of output streams include cout (standard output stream) and ofstream (file output stream).

Follow-up 2

What is the difference between input stream and output stream?

The main difference between an input stream and an output stream is the direction of data flow.

  1. Input stream: An input stream is used for reading data from a source. It allows you to extract data from the stream using the extraction operator (&gt;&gt;). Examples of input streams include cin (standard input stream) and ifstream (file input stream).

  2. Output stream: An output stream is used for writing data to a destination. It allows you to insert data into the stream using the insertion operator (&lt;&lt;). Examples of output streams include cout (standard output stream) and ofstream (file output stream).

Follow-up 3

How does the stream concept help in handling input and output operations in C++?

The stream concept in C++ provides a convenient and uniform way to handle input and output operations. It abstracts the details of reading from or writing to different sources or destinations, such as the keyboard, files, or network connections. By using streams, you can perform input and output operations in a consistent manner, regardless of the specific source or destination.

For example, you can use the cin input stream to read data from the keyboard, and you can use the cout output stream to write data to the console. Similarly, you can use the ifstream input stream to read data from a file, and you can use the ofstream output stream to write data to a file.

Streams also provide various member functions and operators that allow you to perform common input and output operations, such as reading or writing formatted data, manipulating the stream state, and controlling the buffering of data.

Live mock interview

Mock interview: Input/Output in C++

Intermediate ~5 min Your own free AI key

Your voice and your AI key never touch our servers; the key stays in this browser and is sent only to Google. Only your round scores are saved to track progress.