The comments of this Code refer to the experiences of many netizens and some of my own experiences for later reference.
The Getline member function of the C ++ standard library basic_istream class has two versions.
basic_istream<Elem, Tr>& getline( char_type *_Str, streamsize _Count);basic_istream<Elem, Tr>& getline( char_type *_Str, streamsize _Count, char_type _Delim);
The first parameter is the first address of the character array provided by the user. The second parameter is the array length, and the third parameter is the string separator.
One implementation of the member functions in the first version is
typedef basic_istream<_Elem, _Traits> _Myt;typedef basic_ios<_Elem, _Traits> _Myios;_Myt& getline(_Elem *_Str, streamsize _typedef basic_istream<_Elem, _Traits> _Myt;Count){// get up to _Count characters into NTCS, discard newline return (getline(_Str, _Count, _Myios::widen('\n')));}
It can be seen that it finally calls the second version of Getline, but sets the separator as a common carriage return. So next we will focus on the implementation of the second member function.
_ MYT & Getline (_ ELEM * _ STR, streamsize _ count, _ ELEM _ delim) {// get up to _ count characters into NTCs, discard _ delim _ debug_pointer (_ Str); // judge the validity of the incoming pointer ios_base: iostate _ state = ios_base: goodbit; _ chcount = 0; // The number of characters read from the input stream const sentry _ OK (* This, true);/* Note: The above sentence is critical, and it is related to whether the following if statement is executed, that is, whether to read the input stream. In terms of syntax, sentry is a class, and _ OK is a const object of the sentry class. When constructing this object, you need to input two parameters. The first one is the reference of the stream object, the second parameter indicates the processing method of white space characters (such as spaces and tabs). If it is set to true, it means that the white space characters are not ignored, that is, one character is extracted from the input stream. */If (_ OK & 0 <_ count) /*************************************** * ************************************ inside the sentry class A type conversion operator is overloaded, it converts an instance of the sentry class into a bool expression. * This expression returns the value of the Private member _ OK of the sentry class. Bool sentry: Operator bool () const * {// test if _ ipfx succeeded * return (_ OK ); *} * _ OK the value of this Member is set by the sentry class constructor * during initialization. The setting process is troublesome. I will not repeat it here (in fact, I didn't quite understand it ). * But it is certain that when the input stream is in normal state, the value of this member is also true. * otherwise, the value is false. ** _ Count is the second parameter passed in by the caller. Here, it is used as the initial value of the cyclic counter. In the future, the value of * _ count is reduced by one for each read character. **************************************** **************************************/{ // State okay, use facet to extract int_type _ metadelim = _ traits: to_int_type (_ delim); int_type _ meta = _ myios: rdbuf ()-> sgetc (); // read a character from the input stream for (; _ meta = _ myios: rdbuf ()-> snextc () // snextc () read the next character if (_ traits: eq_int_type (_ traits: EOF (), _ Meta) from the input stream) {// end of file, quit _ state | = ios_base:: eofbit; break;} // note: At the end of the file, Getline ends else if (_ meta = _ metadelim) {// got a delimiter, discard it and quit ++ _ chcount; // read characters + 1 _ myios: rdbuf ()-> sbumpc ();/* Note: The Terminator is read out of the preceding sentence. If no Terminator is specified, that is, read '\ n. However, the carriage return is not copied to the buffer, so that the next read operation will start with the first character after the carriage return, */break;}/* Note: An Terminator is encountered, getline ends. Pay attention to the order here. It first checks whether an Terminator is encountered and then determines whether a specified number is read. */Else if (-- _ count <= 0) {// buffer full, quit _ state | = ios_base: failbit; break;} // note: the specified number is read, the execution here implies that the last digit of the specified number is still not the Terminator. // Therefore, this part sets the input stream status to an error. // This directly causes the subsequent Getline (or get) and> operators and other read operations to fail to be correctly executed.) else {// got a character, add it to string ++ _ chcount; // read characters plus 1 * _ STR ++ = _ traits: to_char_type (_ Meta);} // note: this branch copies a single character to the buffer} * _ STR = _ ELEM (); // * Add terminating null character/* Note: the above sentence adds the terminator '\ 0' to the string because _ ELEM () constructs a character object with an ascii code of 0 */_ myios :: setstate (_ chcount = 0? _ State | ios_base: failbit: _ state);/* Note: If no characters are read, keep the input stream status before the Getline operation, otherwise, set the input stream to the corresponding status based on the execution of this Getline operation. */Return (* This); // return the input stream object itself}