Last Updated:

Input and output in C++ with Examples

Input and output in C++

1. "Classic" I/O

Language C defines three standard I/O threads:

  1. stdin – standard input device (keyboard);
  2. stdout – standard output device (screen);
  3. stderr is a standard error message output device (also a screen).

Simplest I/O:

  • getch() – entering one character without displaying it on the screen;
  • getche() – entering one character and displaying it on the screen;
  • putchar(int c) – displays a single character on the screen.

All of these features require you to include a header file <conio.h>.

All other I/O functions are defined in the header file <stdio.h>.

1.1. Screen I/O

For input and output to the screen, the scanf and printf functions are used, respectively, the prototypes of which have the following form: int scanf (char *format, ...); int printf(char *format, ...);

The output is carried out by the printf function, which has the following syntax: printf(<line of the description of formats> [, <the output list>]);

The format description string consists of regular characters, special character sequence control, and format specifications.

Regular characters and control sequences are simply copied to the standard output stream in the order in which they appear.

Format specifications begin with the % character and end with a character that specifies the type of value to display. In addition, format specifications can contain symbols and numbers to control the appearance of the output value (see below for details). The output list consists of variables and/or constants whose values must be output. The number of format specifications must be equal to the number of output values that are specified in the output list. If this condition is not met, the execution of the function may lead to unpredictable results.

Input is performed by the scanf function, which has the following syntax: scanf(<formation description string> [, <the input list>]);

A format description string consists of a set of format specifications, the same as for the printf function. The input list consists of the addresses of the variables where the input values will be entered. The address of the variable is calculated using the unary operation &. The number of format specifications must be equal to the number of input values that are specified in the input list.

The scanf function returns the number of values that were successfully entered and converted. The printf function returns the number of characters written to the output stream.

Control sequences include the following sequences of characters:

SequenceAction
\aBeep
\bDelete the previous character
\nNew line
\rCarriage return
\tTabulation
\'Apostrophe
\"Quotation marks
\\Backslash
\oooASCII character in octal notation
\xoooASCII character in hexadecimal notation

The format specification, which consists of required and optional fields, is as follows:

%[flags] [width] [.precision] [{h | l | L | I64}] type

FlagsMeaningDefault
Left alignment.Right alignment.
+Add the + or – sign before the numbers.The sign is added only before the negative numbers.
0Add zeros before the output value. If flags are used at the same time, 0, 0 is ignored.Add spaces.
gapAdd a space before a positive number. If the space and + flags are used at the same time, the space is ignored.No space is added.
#Add characters 0, 0x, or 0X before a non-zero value if the # flag is used with o, x, or X formats, respectively.The characters 0, 0x, and 0X are not added.
When using the # flag with the e, E, and f formats, the output number will contain a decimal point anyway.A decimal point is added only if it is followed by numbers.
When used with the g and G formats of the # flag, the output number will contain a decimal point and tail zeros anyway.A decimal point is added only if it is followed by numbers. Tail zeros are not displayed.
Ignored when used with c, d, i, u, and s formats. 

The width field contains the minimum number of characters to display— a non-negative integer. If the output value contains fewer characters, it is expanded with spaces (if the 0 flag is not specified). If the width field contains an asterisk (*), the field value is an integer from the argument list that precedes the output value.

The precision field is also a non-negative integer. The action depends on the type of value being displayed.

TypeActionDefault
c, CAccuracy has no effect.A symbol is displayed.
d, i, u, o, x, XPrecision specifies the minimum number of characters that will be printed. If a number contains fewer characters, it is expanded by zeros.The accuracy is 1.
e, E, fPrecision specifies the number of characters after the decimal point. The number is rounded.The accuracy is 6. If the precision is 0 or omitted, the decimal point is not displayed.
g, GAccuracy specifies the maximum number of significant digits.6 significant digits are printed.
s, SPrecision specifies the maximum number of characters to display.All characters in the string are displayed.

If the precision field contains an asterisk (*), then the integer from the argument list preceding the output value is taken as the value of the field.

The optional prefixes hlL, and I64 specify the "size" of the argument— long or short, a single-byte character, or an extended character, depending on the type specification they are modifying.

The required type field specifies the type of the output value.

SymbolTypeOutput Format
cint or wint_tWhen used with a function, printf defines a single-byte character, when used with a function, wprintf defines an extended character.
Cint or wint_tWhen used with a function, printf defines an extended character, when used with a function, wprintf defines a single-byte character.
dintAn iconic decimal whole.
iintAn iconic decimal whole.
ointAn unsigned octal whole.
uintAn unsigned decimal whole.
xintAn unsigned hexadecimal integer using the characters "abcdef".
XintAn unsigned hexadecimal integer using "ABCDEF" characters.
edoubleA sign number in the form [ – ]d.dddd e [sign]ddd, where d is one decimal digit, dddd is one or more decimal digits, ddd is three decimal digits and the sign is + or –.
EdoubleIdentical to the e format, except that the symbol E rather than e introduces the exponent.
fdoubleA sign number in the form [ – ]dddd.dddd, where dddd is one or more decimal digits. The number of digits before the decimal point depends on the magnitude of the number, and the number of digits after the decimal point depends on the accuracy required.
gdoubleA signed number in the format f or e, depending on which format is more compact for the specified value and accuracy.
GdoubleIdentical to the format g, except that the symbol E, rather than e, introduces the exponent.
npointer to integerThe number of characters successfully recorded so far in the output stream. This value is stored in the integer variable whose address is specified as an argument.
ppointer to voidPrints the address specified by the argument.
sstringWhen used with a function, printf specifies a string of single-byte characters, when used with a function, wprintf specifies a string of extended characters. Characters are printed before the end-of-line sign is reached.
SstringWhen used with a function, printf specifies a string of extended characters, when used with a function, wprintf specifies a string of single-byte characters. Characters are printed before the end-of-line sign is reached.

int m, n, x; double y; char c = '&'; char str[] = "String"; 
scanf("%d%d", &m, &n);Entering decimal integers into variables and mn
printf("m = %5d\nn = %5d\n", m, n);Output variables and in decimal format, use at least 5 characters mn
scanf("%d", &x);Enter a decimal integer into a variable x
printf("%#010x\n", x);Output of a variable in hexadecimal, 10 characters are used, // zeros and 0x characters are added in frontx
scanf("%lf", &y);Enter a real number into a variable y
printf("y = %7.2lf\n", y);Output of the real variable, at least 7 characters are used, of which 2 are after the period
printf("c = %c\n", c);Single character output
printf("%.4s\n", str);Line output (no more than 4 characters)

1.2. Read from line/write to string

The sprintf and sscanf functions allow you to write variable values to a formatted string or read variables from a string: int sscanf (char *str, char *format, ...); int sprintf(char *str, char *format, ...);

These functions are similar in all respects to the printf and scanf functions, only the first parameter is the string where the data is written or from.

1.3. Working with Files

  • Declaring a File Variable
FILE *file;
  • Open a file
FILE *fopen(char *name, char *mode);
  • Verify that the end of the file has reached
int feof(FILE *file);
  • Close a file
int fclose(FILE *file);

FILE – a special structure declared in the file <stdio.h>, which is used when working with files. To work with a file, you need to declare the file *<name> variable.

The fopen function is used to open a file. The first parameter specifies the name of the file. The second parameter specifies the type of file access required. mode

ModeAction
"r"Opening for reading. If the file does not exist or cannot be found, the fopen function returns an error symptom.
"w"Open for recording. If the file exists, its contents are destroyed. If the file does not exist, it is created.
"a"Open to add. If the file does not exist, it is created.
"r+"Open for read and write. The file must exist.
"w+"Open an empty file for reading and writing. If the file exists, its contents are destroyed.
"a+"Open for reading and adding. If the file does not exist, it is created.

In addition, the characters t and b can be added to the parameter to specify the text and binary modes, respectively. The default is text mode. mode

In the event of an error, the fopen function returns null.

1.3.1. Text Mode

Text input/output converts between the external representation of the value and the internal (machine) representation of that value.

  • Enter a single character
int getc (FILE *file);
  • Single character output
int putc (int c, FILE *file);
  • Input
int fscanf (FILE *file, char *format, ...);
  • Inference
int fprintf(FILE *file, char *format, ...);
  • Enter a string
char* fgets (char *line, int maxline, FILE *file);
  • Line output
int fputs (char *line, FILE *file);

1.3.2. Binary Mode

In binary mode, no conversions are performed, the internal representation of the value is written to the file. To open a file in binary mode, you must add the character b to the fopen function parameter. mode

  • Input from a binary file
unsigned fread (void *buf, int bytes, int num, FILE *file);
  • Output to binary file
unsigned fwrite (void *buf, int bytes, int num, FILE *file);

The fread function reads from a file into a variable of elements, each with a byte size. The fwrite function writes to a file of variable elements, each with a byte size. Functions return the number of items read/written. filebuf numbytesfilebuf numbytes

In binary mode, direct access to the file is possible: int fseek(FILE *file, long nbytes, int origin)

This function moves the pointer in the file by a byte from the position specified by the . In this case, the parameter can take the following values: filenbytesoriginorigin

  • SEEK_SET 0 – start of the file;
  • SEEK_CUR 1 – the current position of the pointer;
  • SEEK_END 2 is the end of the file.

The long ftell(FILE *file) function returns the current position of the pointer in the . file

fseek(file, 0, SEEK_END); n = ftell(file);Determine file size

2. Streaming I/O

In the C++ language, another method of input/output was developed using the so-called input and output streams.

2.1. Using standard cin and cout streams

To use standard I/O streams, you must include the <iostream> header file. The >> operation is used for input, and the << operation is used for output. The compiler determines the type of input/output variable and formats it accordingly.

#include <iostream> using namespace std; 
cin >> x;Entering a value into a variable from a standard cin streamx
cout << x;Output the value of a variable to a standard cout streamx
cin >> x >> y;Entering two variables
cout << "x = " << x << "\ny = " << y << endl;the endl function translates a string

If an input or output error occurs, the thread state variable is set to the appropriate flag. You can check its value by using the fail function.

cin >> x; if (cin.fail()) cout << "An error occurred while typing\n";

2.2. Formatting

To control the format of the input/output value, so-called manipulators are used. These are functions that are inserted between input/output values and change the state of the stream.

To use manipulators, you must include the header file <iomanip>.

Multiple manipulators have a parameter that can be specified by a literal or variable. Changes made by all manipulators except setw remain in effect until canceled. The setw manipulator applies to only one input/output value.

ManipulatorDescriptionNote
boolalphaThe values of bool variables are displayed as true and false. 
decInteger values are inferred in the decimal numeral system.Default
fixedA fixed format is used for real numbers. 
hexInteger values are displayed in hexadecimal. 
internalThe sign is aligned to the left, and the number itself is aligned to the right. 
leftLeft alignment. 
noboolalphaThe values of bool variables are displayed as 1 and 0.Default
noshowbaseThe prefixes 0 and 0x denoting the number system are not displayed.Default
noshowpointOutput only the integer part of a real number (without a period) if the fractional part is 0.Default
noshowposThe sign before the positive numbers is not displayed.Default
noskipwsA space is seen as a sign of typing completion. 
nouppercaseHexadecimal digits and the exponent symbol in the scientific format of a real number are displayed in lowercase letters.Default
octInteger values are derived in the octal number system. 
rightRight alignment.Default
scientificFor real numbers, a scientific format is used. 
setfill(c)Specifies the character to fill in. By default, a space is used. 
setprecision(n)Specifies the precision for real numbers. By default, the accuracy is 6. If neither a fixed nor a scientific format of a real number is established, then the accuracy determines the number of digits to be derived (total, before the point and after the point). If a number is too large, it is automatically displayed in scientific format, and then the accuracy specifies the number of digits in the mantissa. If a fixed real number format is set, precision specifies the number of digits after the period. If a scientific format of a real number is established, the precision specifies the number of digits in the mantissa. 
setw(n)Sets the minimum number of characters used to output the value. If the value is represented by fewer characters, the remaining positions are filled with the character set by the setfill manipulator. The alignment is set by the leftright, and internal manipulators. To set the default behavior (as many characters as necessary), you must use the setw manipulator with the 0 option.Affects only one input/output value!
showbaseOutput prefixes 0 and 0x to indicate the number system. 
showpointThe output of both the integer and fractional parts of a real number, even if the fractional part is 0. 
showposDisplay a sign before a positive number. 
skipwsSpaces are treated as separators between values.Default
uppercaseHexadecimal digits and the exponent symbol in the scientific format of a real number are displayed in uppercase letters. 

 

int m, n, x; double y; cin >> m >> n; cout << "m = " << setw(5) << m << "\nn = " << setw(5) << n << endl; cin >> x; cout << setfill('0') << showbase << hex << setw(10) << internal << x << endl; cin >> y; cout << setfill(' ') << fixed << setw(7) << setprecision(2) << y << endl;

2.3. Thread Linking

Let's look at an example.
char c; cout << "Введите символ: "; cin >> c;

How do we ensure that the words Enter a character appear on the screen before the read operation is performed? The output to the standard stream is buffered so that if the cin and cout streams are independent, the output text will not appear on the screen until the output buffer is full. The solution to this problem is that threads are linked using the tie function. This function is used to establish and break the links between the input and output streams.


char c; cin.tie(&cout); cout << "Enter character: "; cin >> c;

An input thread can be associated with only one output thread at a time. Addressing s.tie(0) breaks the link between the flow and the stream to which it was associated. Like most functions with threads that set the value, the tie function returns the previous value, which means that it returns the previous related thread or 0. When called without arguments, the tie() function returns the current bound thread without modifying it. s

2.4. File Streams

For file/to file I/O, there are streams that can be associated with a file on disk. To use file streams, you must include a header file <fstream>. There are three types of file streams: fstreamifstream, and ofstream. The difference between the two is that the fstream stream is opened for input and output by default, the default ifstream stream is opened for input, and the default ofstream stream is opened for output. You can change the default behavior, as well as set other file opening modes, by using the following constants:

  • ios_base::app  – open a file to add;
  • ios_base::binary  – open a binary, not a text file;
  • ios_base::in  – open the file for reading;
  • ios_base::out  – open the file for recording;
  • ios_base::trunc  – delete the contents of the file when opened.

File opening modes are combined using a bitwise OR (|) operation.

To open a file, you can specify the file name directly in the stream designer or use the open function.

fstream fs("f1.txt");Open a file for reading and writing
ifstream ifs("f2.txt");Open a file for reading
ofstream ofs("f3.txt");Open a file for recording
fstream fs("f1.txt", ios_base::in | ios_base::out | ios_base::trunk);Open a file for reading and writing and deleting the contents of the file
ifstream ifs("f2.txt", ios_base::in | ios_base::binary);To open a binary file for reading
ofstream ofs;Create a stream that is not associated with the file
ofs.open("f3.txt");Open the file for recording

If you plan to use a read-only or write-only file, it is safer to use the appropriate file stream.

To check the opening of the file, use the is_open function.

Threads are automatically closed when the program is terminated. However, if necessary, you can close the thread with the close function and then reopen it by linking it to another file.

To work with text streams, << and >> operations are used. It is also possible to use manipulators to format input/output values.

int x; fstream f; 
f.open("in.txt", ios_base::in);Open the file for reading
if (!f.is_open())Check the opening of the file
{ cout << "Unable to open file 'in.txt'\n"; return; } 
f >> x;Reading a variable from a file x
if (f.fail())Check for read errors
{ cout << "Error reading from file 'in.txt'\n"; return; } 
f.close();Close the file
f.open("out.txt", ios_base::out);Open the file again, now for recording
if (!f.is_open())Check the opening of the file
{ cout << "Unable to open 'out.txt'\n file"; return; } 
f << hex << x << endl;Derive the value of a variable in a 16-digit system x
f.close();Close the file

To check if the end of the file is reached, use the eof function.

int n; ifstream f("in.txt"); 
if (!f.is_open()) 
{ cout << "Unable to open file 'in.txt'\n"; return; } 
while (!f.eof())Until the end of the file is reached
{ f >> n; cout << n << endl; } 

To provide direct access to the file, the seekg/seekp and tellg/tellp functions are used. The difference between functions is that functions with a name ending with the 'g' character are used to work with input streams, and functions with a name ending with a 'p' character are used to work with output streams.

The seekg/seekp functions move the internal file pointer to a specified position. Positions correspond to bytes, numbering starts with 0. There are two types of functions – with one parameter and with two parameters. A single integer parameter specifies the absolute position in the file. Two parameters specify the offset (integer) and the reference point. This parameter can have the following values:

  • ios_base::beg – the beginning of the file;
  • ios_base::cur – the current position of the pointer;
  • ios_base::end – the end of the file.

The tellg/tellp functions have no parameters. They return the current position of the pointer in the file.

The seekg/seekp and tellg/tellp functions work with both text and binary threads. In any case, it is desirable either to know the structure of the file, or to work with files in which all records have the same length. Otherwise, it is possible to move the pointer to a position that is not the beginning of the recording.

To work with binary files, the read and write functions are used. The parameters of the function are a pointer (of type char* for the read function and type const char* for the write function) that specifies the address of the beginning of the array for I/O, and an integer that specifies the number of bytes for I/O.

For an example of using stream input from a binary file, see the end of the lecture.

3. Examples

 

Example 1. Enter an array from a text file

 


// Input function for a one-dimensional array.
// If the input was made without errors, 1 is returned, otherwise 0.
// x - input array,
// n is a pointer to a variable containing the number of array elements,
// fname - filename for input.

int ArrayInput(double x[], int *n, char *fname)
 {int i;
   FILE *file;

   if ((file = fopen(fname, "r")) == NULL)
    { printf("Unable to open file '%s'\n", fname);
      return 0;
     }
   if (fscanf(file, "%d", n) < 1)
    { printf ("Error reading from file '%s'\n", fname);
      fclose(file);
      return 0;
     }
   if (*n < 0 || *n > NMAX)
    { printf("Number of mass e-mails must be between 1 and %d! (file '%s')\n", NMAX, fname);
      fclose(file);
      return 0;
      }
   for (i = 0; i < *n; i++)
    if (fscanf(file, "%lf", &x[i]) < 1)
     { printf ("Error reading from file '%s'\n", fname);
       fclose(file);
       return 0;
      }
   fclose(file);
   return 1;
  }

Example 2. Output an array to a binary file


// Output array to binary.
// If the output was completed without errors, 1 is returned, otherwise 0.
// x - output array,
// n is a variable containing the number of array elements,
// fname - the name of the output file.

int BinOutput(double x[], int n, char *fname)
  { FILE *file;

    if ((file = fopen(fname, "wb")) == NULL)
     { printf("Unable to open file '%s'\n", fname);
       return 0;
      }
    if (fwrite(x, n * sizeof(double), 1, file) < 1)
     { printf ("Error writing to file '%s'\n", fname);
       fclose(file);
       return 0;
       }
    fclose(file);
    return 1;
   }

Example 3. Enter an array from a binary file


// Input array from binary file.
// If the input was made without errors, 1 is returned, otherwise 0.
// x - input array,
// n is a pointer to a variable containing the number of array elements,
// fname - filename for input.

int BinInput(double x[], int *n, char *fname)
 { FILE *file;

   if ((file = fopen(fname, "rb")) == NULL)
    { printf("Unable to open file '%s'\n", fname);
      return 0;
     }
   for (*n = 0; ; (*n)++)
    if (fread(x + (*n), sizeof(double), 1, file) < 1)
     if (feof(file))
      break;
     else
      { printf ("Error reading from file '%s'\n", fname);
        fclose(file);
        return 0;
       }
   fclose(file);
   return 1;
  }


// Another way

int BinInput(double x[], int *n, char *fname)
 { FILE *file;

   if ((file = fopen(fname, "rb")) == NULL)
    { printf("Unable to open file '%s'\n", fname);
      return 0;
     }
   fseek(file, 0, SEEK_END);
   *n = ftell(file) / sizeof(double);
   fseek(file, 0, SEEK_SET);
   if (fread(x, sizeof(double), *n, file) < *n)
    { printf ("Error reading from file '%s'\n", fname);
      fclose(file);
      return 0;
     }
   fclose(file);
   return 1;
  }

Example 4. Streaming an array from a binary file

 

// Input array from binary file.
// If the input was made without errors, 1 is returned, otherwise 0.
// x - input array,
// n is a pointer to a variable containing the number of array elements,
// fname - filename for input.

int BinInput(double x[], int *n, char *fname)
  { ifstream f(fname, ios_base::in | ios_base::binary);

    if (!f.is_open())
     { cout << "Unable to open file '" << fname << "'\n";
       return 0;
      }
    f.seekg(0, ios_base::end);
    *n = f.tellg() / sizeof(double);
    f.seekg(0, ios_base::beg);
    f.read(reinterpret_cast<char *>(x), *n * sizeof(double));
    if (f.fail())
     { cout << "Error reading from file '" << fname << "'\n";
       return 0;
      }
    return 1;
   }