C ++ things: streaming and IO

  1. The concept
  
  of flow "flow" is "flow", which is the process of the flow of material from one place to another, such as the flow of water that we can perceive. C ++ streaming refers to the process of inputting information from external input devices (such as keyboards and disks) to the internal computer (that is, memory) and outputting from memory to external output devices (such as monitors and disks). This input and output process is visually compared to For "flow".
  
  In order to realize the internal and external flow of information, the C ++ system defines an I / O class library, each of which is called a corresponding stream or stream class to complete a certain function. Objects defined according to a stream class are often called streams.
  
  Usually the standard input or standard output device display is called the standard stream; the input and output of the file on the external storage disk is called the file stream; the string storage space specified in the memory is called the string stream.
  
  So what is the content of the stream usually?
  
  The basic unit in the stream is bytes, so it is also called byte stream. The byte stream can be ASCII characters, binary data, graphic images, audio and video and other information. Files and strings can also be viewed as ordered byte streams, also known as file streams and string streams.
  
  2.
  
  The IO class library of IO class C ++ is part of STL. A huge class library is defined in STL, and their inheritance relationship is as follows:
  
  bubuko.com, cloth button
  
  The classes that manage standard input / output streams are: istream (input), ostream (output), and iostream (input and output), where istream and ostream directly inherit from ios, and iostream inherits istream and otream multiple times. Cin is an istream object for input located in STL, and cout, cerr, and clog are three ostream objects for output. The cout object is also called standard output, which is used for normal output, cerr is used to output warning and error information, because it is called standard error, and clog is used to output general information when the program is running. The difference between cerr and clog is that cerr directly outputs related information to the display without going through the buffer, and clog puts the information in the buffer first, and outputs to the display when the buffer is full or when it encounters endl.
  
  The classes for managing file streams are: ifstream (file input), ofstream (file output), and fstream (file input / output). Among them, ifstream is a class inherited from istream, ofstream is a class inherited from ostream, and fstream is a class inherited from iostream.
  
  The classes for managing string streams are: istringstream (string input), ostringstream (string output), and stringstream (string input / output). Among them, istringstream is a class inherited from istream, ostringstream is a class inherited from ostream, and stringstream is a class inherited from iostream.
  
  3. The << and >> operators
  
  3.1 The usage of <<
  
  in the istream input stream class defines a set of common member functions overloaded to the right shift operator >>, the specific declaration format of the function is:
  
  istream & operator >> ( istream & is, char & c);
  
  istream & operator >> (istream & is, signed char & c);
  
  istream & operator >> (istream & is, unsigned char & c);
  
  istream & operator >> (istream & is, char * s);
  
  istream & operator >> (istream & is, signed char * s);
  
  istream & operator >> (istream & is, unsigned char * s);
  
  Because the right shift operator overloads the operation used to input data to the variable, it is also known as the extraction operator, which extracts the data from the stream and assigns it to the variable.
  
  When the system performs the cin >> variable operation, it will call the corresponding extraction operator overload function according to the type of the actual parameter x, transfer the variable reference to the corresponding formal parameter, and then read a value from the keyboard input and assign it to the variable And return to the cin stream so that you can continue to use the extraction operator to enter data for the next variable.
  
  When inputting data from the keyboard, only after inputting the data and pressing the Enter key, the system will store the line of data into the keyboard buffer for the cin stream to read sequentially to the variable. In addition, each data input from the keyboard must be separated by a space or a carriage return, because cin reads data for a variable with a space or a carriage return as its end mark.
  
  When cin >> When str_ptr in the str_ptr operation is a character pointer type, it is required to read a string from the input of the keyboard and assign it to the storage space pointed to by str_ptr, if str_ptr does not previously point to a storage space that allows writing information , The input operation cannot be completed. In addition, the character string input from the keyboard must not have double quote delimiters on both sides, if it is treated as double quote characters only. The same is true for the characters entered, without single quote delimiters.
  
  3.2 Usage
  
  of Ostream output stream class defines a group of public member functions that overload the left shift operator <<, and the specific declaration format of the function is:
  
  istream & operator >> (bool & val);
  
  istream & operator >> ( short & val);
  
  istream & operator >> (unsigned short & val);
  
  istream & operator >> (int & val);
  
  istream & operator >> (unsigned int & val);
  
  istream & operator >> (long & val);
  
  istream & operator >> (unsigned long & val );
  
  istream & operator >> (long long & val);
  
  istream & operator >> (unsigned long long & val);
  
  istream & operator >> (float & val);
  
  istream & operator >> (double & val);
  
  istream & operator >> (long double & val) ;
  
  istream& operator>> (void*& val);
  
  In addition to all the built-in types given by the right-shift operator overload function declared in the istream stream class, a void * type is added to output any pointer (but not a character pointer because it will be treated as a string, ie The value of a string stored in the storage space pointed to by the output.
  
  Because the left shift operator overload is used to output the value of the expression to the stream, it is also called the insertion operator. For example, when the output stream is cout, the expression value is inserted into the display, that is, output to the display.
  
  When the system executes cout << variable operation, first call the corresponding insert operator overload function according to the type of x value, and transfer the value of the variable to the corresponding formal parameter by value, and then execute the function body to change the value of the variable (that is, the shape Parameter value) is output to the display screen, displayed from the current screen cursor position, and then returned to the cout stream, so as to continue to use the insertion operator to output the value of the next expression.
  
  4. IO condition status
  
  4.1 The status of the query stream
  
  may cause errors in IO operations. Some errors are recoverable, while others occur deep in the system, which is beyond the scope of application correction.
  
  The IO class defines some functions and flags that can help us access and manipulate the conditional state of the stream.
  
  First, the type of the variable that represents the current state of a stream is strm :: iostate, where strm is a stream type, which can be iostream, fstream, and so on. For example, we define a standard IO stream state:
  
  iostream :: iostate strm_state = iostream :: goodbit;
  
  IO inventory defines four iostate type contexpr values, which represent specific bit patterns. These values ​​are used to represent specific types of IO conditions and can be used with bit operations to detect or set multiple flag bits at once.
  
  1) strm :: badbit is used to specify that the stream has crashed. It represents system-level errors, such as unrecoverable read and write errors. Normally, once the badbit is set, the stream can no longer be used.
  
  2) strm :: failbit is used to indicate that an IO operation has failed.
  
  3) strm :: eofbit is used to indicate that the stream reaches the end of the file.
  
  After a recoverable error occurs, the failbit is set, and a character error is read if the value is expected to be read. This problem can usually be fixed, and the stream can continue to be used. If the end of the file is reached, both eofbit and failbit will be set.
  
  4) strm :: goodbit is used to indicate that the stream is not in an error state. This value is guaranteed to be zero.
  
  The value of goodbit is 0, indicating that no error has occurred in the stream. If any of badbit, failbit, and eofbit are set, the condition for detecting the flow status will fail.
  
  The standard library also defines a set of functions to query the status of these flags. If s is a stream, then:
  
  s.eof () // If the eofbit of stream s is set, return true
  
  s.fail () // if If the failbit or badbit of stream s is set, return true
  
  s.bad () // If the badbit of stream s is set, then return true
  
  s.good () // If the stream s is in a valid state, then return true
  
  in the actual When we judge whether the state of the stream is valid in the loop, we directly use the stream object itself, such as: while (cin >> variable) {cout << variable}, which is converted to while ((cin >> variable) in practice. good ()) {cout << variable}.
  
  4.2 Management Condition State The
  
  IO class library provides three functions to manage and set the state of the stream:
  
  s.clear (); // Reset all conditional statuses in stream s, set the stream status to valid, and call good will return true
  
  s.clear (flags); // According to the flags flag, stream s The corresponding condition state in
  
  s.setstate (flags); // According to the given flags flag, set the corresponding condition state in stream s.
  
  s.rdstate (); // returns an iostate value, corresponding to the current state of the stream.
  
  We can use the above member functions like this.
  
  iostream :: iostate old_state = cin.rdstate (); // remember the current state of cin
  
  cin.clear (); // valid with cin
  
  process_input (cin); // use cin
  
  cin.setstate (old_state); // will Set cin to the original state
  
  cin.clear (cin.rdstate () & ~ cin.failbit & ~ cin.badbit); // Reset failbit and badbit, keep eofbit unchanged.
  
  5. IO buffer
  
  5.1 Input buffer
  
  Let's look at a simple input and output program:
  
  int main ()
  
  {
  
  char ch;
  
  while (cin >> ch && ch! = '#')
  
  {
  
  Cout << ch;
  
  }
  
  return 0;
  
  }
  
  The function of the program is to input characters in a loop, and then display the input characters, and end when encountering # or cin stream failure. According to the surface of the program, the desired effect is to enter one and display one, like this rroonnyy #, red represents the displayed result. In practice, our output and output are like this:
  
  ronny # abc [Enter]
  
  ronny
  
  input character immediately echoes a form of unbuffered or direct input, which means that the character you typed becomes available immediately for the program you are waiting for . In contrast, delayed echo is an example of buffered input. In this case, the character blocks you type are collected and stored in a temporary storage area called a buffer. Press the Enter key to make the character segment you input have effect on the program.
  
  Buffered input is commonly used in text programs. When you make a mistake, you can use your keyboard to correct the error. When the Enter key is finally pressed, you can send the correct input.
  
  In some interactive games, unbuffered input is required. For example, when you press a key in a game, you must execute a command.
  
  There are two types of buffering:
  
  1) Full buffering: the buffer is cleared when it is full (the content is sent to its destination). This type of buffering usually appears in file input.
  
  2) Line buffer: The buffer is cleared when a newline character is encountered. The keyboard input is a standard line buffer, so pressing the enter key will clear the buffer.
  
  5.2 Output buffer The
  
  above is the input buffer, and the output in C ++ is also buffered.
  
  Each output stream manages a buffer to store data read and written by the program. For example, if you execute the following code
  
  os << ”please enter a value:”;
  
  The text string may be printed immediately, but it may also be stored in the buffer by the operating system and then printed. With the buffering mechanism, the operating system can combine multiple output operations of the program into a single system-level write operation. Since the write operation of the device may be time-consuming, allowing the operating system to combine multiple output operations into a single device write operation can bring a great performance improvement.
  
  There are many reasons for the buffer refresh (that is, the data is actually written to the output device or file):
  
  <1> The program ends normally, and the buffer refresh is executed as part of the return operation of the main function.
  
  <2> When the buffer is full, the buffer needs to be refreshed, and then new data can continue to be written to the buffer.
  
  <3> We can use the endl operator to explicitly refresh the buffer.
  
  <4> After each output, we can use the unitbuf operator to set the internal state of the stream to clear the buffer. By default, unitbuf is set for cerr, so the content written to cerr is refreshed immediately.
  
  <5> An output stream is related to another stream. In this case, when reading and writing the associated stream, the buffer of the associated stream is flushed, and both cin and cerr are associated with cout. Therefore, reading cin or writing cerr will cause the buffer of cout to be refreshed.
  
  In addition to endl can complete line breaks and refresh the buffer, there are two similar operators in the IO library: flush and ends. flush flushes the buffer, but does not output any extra characters; ends inserts a null character into the buffer, and then flushes the buffer.
  
  cout << "hi!" << endl; // output hi and a newline character, then refresh the buffer
  
  cout << "hi!" << flush; // output hi, then refresh the buffer, without appending any extra characters
  
  cout << "hi!
  
  If we want to refresh the buffer after each output operation, we can use the unitbuf manipulator. It tells the stream to perform a flush operation after each subsequent write operation. The nounitbuf operator resets the stream to restore the normal system-managed buffer refresh mechanism.
  
  cout << unitbuf; // The buffer is refreshed immediately after all output operations
  
  // Any output is refreshed immediately, no buffer
  
  cout << nounitbuf; // Return to the normal buffer mode
  
  Note: If the program terminates abnormally, the output buffer Will not be refreshed. When a program crashes, the data it outputs is likely to stay in the output buffer and wait for printing.
  
  We can associate an istream to another ostream, or we can associate an ostream to another ostream.
  
  cin.tie (& cout); // The standard library has associated cin and cout together
  
  // s.tie If s is associated with an output stream, it returns a pointer to the stream, if the object is not associated with the stream, it returns empty Pointer
  
  ostream * old_tie = cin.tie (nullptr); // no longer associate cin with other streams, and old_tie points to cout
  
  cin.tie (& cerr); // reading cin will refresh cerr instead of cout
  
  cin.tie (old_tie ); // Rebuild the normal association between cin and cout
  
  6. Use file stream
  
  6.1 When
  
  creating a file stream object using the file stream object , we can provide the file name or not, and then use the open member function to open the file.
  
  string infile = "../ input.txt";
  
  string outfile = "../output.txt";
  
  ifstream in (infile); // open the file when defined
  
  ofstream out;
  
  out.open (outfile); // open the file with open
  
  If the call to open fails, failbit will be set , So it is usually a good habit to check when calling open.
  
  If you use a read file stream ifstream to open a file that does not exist, it will cause the read to fail, and if you use a write file stream ofstream to open a file, if the file does not exist, it will create the file.
  
  Once a file stream has been opened, it remains associated with the corresponding file. In fact, calling open on an already opened file stream will fail, and will cause failbit to be set. Subsequent attempts to use the file stream will fail. In order to associate the file stream with another file, you must first close the associated file. Close the associated file of a stream can be completed with the close member function.
  
  6.2 File mode
  
  Each stream has an associated file mode, which is used to indicate how to use the file. The file modes and their meanings are listed below:
  
  in
  
  Open in read mode
  
  out Open
  
  in write mode
  
  app
  
  Each write operation is located to end of file
  
  ate
  
  locate the file immediately after the end of the file open
  
  trunc
  
  truncate the file
  
  binary
  
  binary manner IO
  
  You can specify the file mode when initializing a stream with a file name or when opening a file with open, but pay attention to the following restrictions:
  
  <1> You can only set the out mode for ofstream or fstream objects.
  
  <2> Only in mode can be set for ifstream or fstream objects.
  
  <3> The trunc mode can only be set when out is set.
  
  <4> As long as trunc is not set, you can set the app mode. In app mode, even if the out mode is not explicitly specified, the file is always opened as an output.
  
  <5> By default, even if we do not specify trunc, files opened in out mode will be truncated. In order to retain the contents of the file opened in out mode, we must also specify the app mode, which will only append the data to the end of the file; or specify the in mode at the same time, that is, open the file and read and write at the same time.
  
  <6> The ate and binary modes can be used for any type of file stream object, and can be combined with any other file mode.
  
  Opening a file in out mode discards the existing data, so the way to prevent an ofstream from emptying the contents of a given file is to also specify app mode.
  
  // In these few statements, file1 is truncated
  
  ofstream out ("file1"); // implicitly open the file in output mode and truncate the file
  
  ofstream out2 ("file1", ofstream :: out); // implied Truncate the file
  
  ofstream out3 ("file1", ofstream :: out | ofstream :: trunc); // Explicitly truncate the file
  
  // In order to preserve the content of the file, we must explicitly specify the app
  
  ofstream app ("file2", ofstream :: app); // implicitly as the output mode
  
  ofstream app ("file2", ofstream :: app | ofstream :: out);
  
  7,
  
  three character stream sstream header files are defined Types to support memory IO, these types can write data to string, read data from string, just like string is an IO stream.
  
  7.1 Using istringstream
  
  Many times we need to process the text line by line, and we need to analyze the words in the line separately. At this time, it is convenient to use istringstream.
  
  For example, our program needs to read one line of text at a time, and then take out the words and save them in a vector.
  
  string line, word;
  
  while (getline (cin, line))
  
  {
  
  vector <string> wordList;
  
  istringstream lineText (line);
  
  while (lineText >> word)
  
  {
  
  wordList.push_back (word);
  
  }
  
  }
  
  7.2 Use ostringstream
  
  when we step by step When constructing the output, I hope that ostringstream is very useful when printing it together. It can help us complete the function like itoa, ftoa to digital string conversion.
  
  int num1 = 42;
  
  double pi = 3.1415926;
  
  string str = "some numbers";
  
  ostringstream formatted;
  
  formatted << str << pi << num1;
  
  cout << formatted.str () << endl;
  
  where str member function is stringstream has several unique operations one.
  
  string s;
  
  stringstream strm (s); // Save a copy of s, this constructor is explicit.
  
  strm.str (); // Returns a copy of the string object saved by strm.
  
  strm.str (s); // Copy s to strm and return void.
  
  8. Formatted input and output
  
  8.1 The
  
  standard library of manipulators defines a set of manipulators used to modify the state of the stream. A manipulator is a function or an object that affects the state of the stream and can be used as an input or output operator. The operation object, such as endl, which we are familiar with, is an operator.
  
  Manipulators are used for two types of output control: the output form of the control value and the number and position of the padding. Most manipulators that change the format state are set / reset in pairs: a manipulator is used to set the format state to One new value, and the other is used to restore it to the normal default format.
  
  8.2 Controlling the format of Boolean values
  
  Boolalpha can be set to output true of bool type variables as true or false as false. You can set noboolalpha to restore the internal state to the default format.
  
  // modify boolalpha flag
  
  #include <iostream> // std :: cout, std :: boolalpha, std :: noboolalpha
  
  int main () {
  
  bool b = true;
  
  std :: cout << std :: boolalpha << b < <'\ n';
  
  std :: cout << std :: noboolalpha << b << '\ n';
  
  return 0;
  
  }
  
  8.3 The decimal value of the specified integer value
  
  is output in decimal format by default. We can set different Format manipulator to change the base of the output integer value.
  
  oct: display
  
  hex in octal
  
  : display dec in hexadecimal : display in decimal
  
  In addition, you can use the showbase manipulator to explicitly format the prefix, with leading 0 in octal and leading 0x in hexadecimal. The manipulator noshowbase restores the state of cout so that the integer value is no longer displayed. Sometimes we need to output hexadecimal as uppercase such as 0X FF, you can use the operator uppercase and nouppercase to control the case of the stream output.
  
  cout << uppercase << showbase << hex << 20 << 1024
  
  << nouppercase << noshowbase << dec << endl;
  
  8.
  
  The printing precision is changed by the precision member or using the setprecision manipulator. Where precision is an overloaded function, a version accepts int parameters, sets the precision to this value, and returns the old precision value. The other version does not accept parameters and returns the current precision value. The setprecision manipulator accepts a parameter that is used to set the precision.
  
  Scientific is used to specify scientific notation, fixed is specified as fixed-point decimal, and hexfloat is specified as a hexadecimal floating point number. defaultfloat restores the stream to its default state.
  
  Setting showpoint can be used to force the printing of decimals.
  
  8.5 Output padding
  
  setw: Specify the minimum space of the next number or character string
  
  left: Indicates left-justified output.
  
  right: indicates right-aligned output, right-aligned is the default format.
  
  internal: Controls the position of the negative symbol. It aligns the symbol to the left, aligns the value to the right, and fills all intermediate spaces with spaces.
  
  setfill: Allows you to specify a character to replace the default space to fill the output.
  
  int i = -16;
  
  double d = 3.14159;
  
  cout << "i:" << setw (12) << i << '\ n'
  
  << "d:" << setw (12) << d << '\ n';
  
  cout << left
  
  << "i:" << setw (12) << i << '\ n'
  
  << "d:
  

  
  << "i:" << setw (12) << i << '\ n'
  
  << "d:" << setw (12) << d << '\ n';
  
  cout << internal
  
  << " i: "<< setw (12) << i << '\ n'
  
  <<" d: "<< setw (12) << d << '\ n';
  
  cout << setfill ('#')
  
  < <"i:" << setw (12) << i << '\ n'
  
  << "d:" << setw (12) << d << '\ n'
  
  << setfill ('');
  
  bubuko .com, cloth button
  
  9, random access
  
  to streams Different stream types generally support random access to data in related streams. The stream can be repositioned to skip around, reading the last line first, then the first line, and so on. The standard library provides a pair of functions to seek a given position and tell the current position in the relevant stream.
  
  9.
  

  

  

  

  
  Logically, the g version can only be used on istream or ifstream or istringstream, and the p version can only be used on the ostream type or its derived class ofstream or ostringstream. The iostream object, fstream or stringstream object can both read and write the related stream, and can use any of the two versions. 9.
  
  9.2 There is only one mark
  
  Although the standard library distinguishes between input and input and has two versions, it only maintains one mark in the file-there is no distinguishable read mark and write mark.
  
  Just when trying to call tellp on the ifstream object, the compiler will give an error message. vice versa.
  
  When using the fstream and stringstream types that are both readable and writable, there is only one buffer for storing data and a marker that represents the current position in the buffer. The standard library maps both the g version and the p version to this marker.
  
  9.3 Ordinary iostream objects generally do not allow random access.
  
  9.4 Reposition mark
  
  seekg (new_position); seekp (new_position);
  
  seekg
  
  (offset, dir);
  
  seekp (offset, dir); the
  
  first version switches the current position to a given location, the second version accepts an offset And an indicator of where to calculate the offset.
  
  9.5 Access
  
  to a value returned by the tell function, use the pos_type member of the appropriate class to save.
  
  10. An example
  
  Assuming a given file to read, we will write a new line at the end of the file, and the line change includes the relative position of the beginning of each line (the program does not have to write the offset of the first line, because it is always 0). For example, given the following file,

Guess you like

Origin www.cnblogs.com/zhenhua1618/p/12729831.html