简体   繁体   中英

While Function and cin in C++

Its been a few days since I started reading Stroustrup's book Programming principles and practices. His grammar repetition detection code is the following,

string previous = " ";
string current;
while (cin >> current){
    if (previous == current)
        cout << "repeated word:" << current << "\n";
    previous = current;
}

Although he explained the while statement, I didn't quite understand how a whole sentence can be analyzed using the combination of while and cin. If it takes the sentence word by word, then what is it that exactly dictates that. For example, why doesn't it stop with the first word only.

I'm answering, because from your comments, your problem seems to be different from the issues the other answers address.

std::istream is a stream; the form of sequential input used in C++. (It can also be used for certain forms of non-sequential input, but that's an advanced feature, tricky to use, and it doesn't need to concern us here.) The important aspect of sequential input, or a stream, is that it extracts data from its source, and once the data is extracted, it is no longer there to be accessed. Logically, it can be thought of as a position marker into the data in the file; each time it extracts a character, the position marker advances, and it always extracts at the position marker. So when you write:

std::string dest;
std::cin >> dest;

the >> operator (which is nothing other than a function with a special name, as you'll see later in the book) first extracts characters until it finds one that isn't white space; then extracts characters until it finds one that is white space, putting each character it extracts into dest . It will also stop if there are no more characters to be extracted, a condition called end of file. If that happens before it has put any characters into dest , the input will fail; this failure will be memorized in the stream, and will be used when you use the stream in a context which requires a true or false: the stream is true unless it has failed.

But the important point to retain is that the stream never extracts the same character twice. If you want to see this better, the stream has some low level functions which allow you to extract the data, character by character. You might want to try:

char ch;
while ( std::cin.get( ch ) ) {
    std::cout << ch << std::endl;
}

std::istream::get is a very, very low level input, which always extracts exactly one character, without skipping white space, or anything. All the >> does is call this function until it has finished its task. It's a little bit more complicated; in particular, >> often cannot know whether it has finished until it has looked one character too far, so there are means to peek at the next character, without extracting it, and a means of pushing last character you've extracted back into the front of the stream, so you can read it again. And there are means of managing error status. (Say you do >> into an int , but the next characters to be read are "abc".) But for the moment, you don't have to worry about all that. For the moment, just remember that once a character has been read, it's gone, and can never be read again.

The answer is quite simple.

while (cin >> current)

reads the input until there's nothing left inside. The standard overloaded operator>> skips over whitespace and then reads everything until it encounters another whitespace character or reaches the end of the input. Since it's inside a while loop, it'll be called in every iteration of the loop. That's why the sentence is split in words.

Try to think as algorithm:

While the text isn t complete
    read a word
    if this word is like the previous one
        there s a repeated word
    store this word for next iteration

while (cin >> current) will send one word after another until cin is empty.

Simply, it'll read words until there are none left! Once the end of the input is reached, or a non-string is encountered (well, good luck with that), an error flag is set on the stream. cin >> current evaluates to cin , which in turn can convert to boolean false when an error flag is set. Since you're using cin >> current as a loop condition, this ends the loop.

cin is an instance of istream template class. operator >> acts on this istream instance to load input into data and returns a reference to this istream . Then it is tested by a call of cin::operator void*() which invokes fail() function to test if operation succeeded. This is why you can use this operation in while condition

while ( cin >> current)
{
   //...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM