简体   繁体   English

C++中的While函数和cin

[英]While Function and cin in C++

Its been a few days since I started reading Stroustrup's book Programming principles and practices.自从我开始阅读 Stroustrup 的书《编程原则和实践》以来已经有几天了。 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.虽然他解释了while语句,但我还是不太明白用while和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; std::istream是一个流; the form of sequential input used in C++. 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 .然后提取字符,直到找到一个空白字符,然后将提取的每个字符放入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;如果在将任何字符放入dest之前发生这种情况,则输入将失败; 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. std::istream::get是一种非常非常低级的输入,它总是只提取一个字符,而不会跳过空格或任何东西。 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. (假设您将>>转换为int ,但要读取的下一个字符是“abc”。)但目前,您不必担心所有这些。 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.标准重载operator>>跳过空格然后读取所有内容,直到遇到另一个空格字符或到达输入的末尾。 Since it's inside a while loop, it'll be called in every iteration of the loop.由于它在while循环内,它将在循环的每次迭代中被调用。 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. while (cin >> current)会一个接一个地发送,直到 cin 为空。

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. cin >> current的计算结果为cin ,这反过来又可以转化为布尔false当错误标志。 Since you're using cin >> current as a loop condition, this ends the loop.由于您使用的cin >> current作为循环条件,这结束循环。

cin is an instance of istream template class. cinistream模板类的一个实例。 operator >> acts on this istream instance to load input into data and returns a reference to this istream . operator >>作用于此 istream 实例以将输入加载到数据中并返回对此istream的引用。 Then it is tested by a call of cin::operator void*() which invokes fail() function to test if operation succeeded.然后通过调用cin::operator void*()来测试它,该调用调用fail()函数来测试操作是否成功。 This is why you can use this operation in while condition这就是为什么你可以在 while 条件下使用这个操作

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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