提取物究竟是如何>>运算符在C ++中工作

时间:2014-10-03 15:31:41

标签: c++ operators extract iostream fstream

我是一名计算机科学专业的学生,​​因此对C ++语言没有多少经验(考虑到这是我使用这种语言的第一个学期),或者是编码。

我被赋予了一个从文本文件中读取整数的赋值,其形式为:

19 3 -2 9 14 4
5 -9 -10 3
.
.
.

这让我有了更好地理解I / O操作符的旅程,因为我需要使用此流做某些事情(呃)。

我到处寻找,无法找到关于提取物>>的简单解释运营商内部工作。让我澄清一下我的问题:

我知道提取器>>运算符将提取一个连续元素,直到它到达空格,制表符或换行符。我试图弄清楚的是,指针(?)或读取位置(?)在提取元素之后会在哪里。它会被删除的元素的最后一个字符,还是被删除,因此消失了?它会出现在空格/制表符/'\ n'字符本身吗?也许是下一个元素的开头提取?

我希望我足够清楚。我缺乏所有适当的术语来更清楚地描述我的问题。


这就是我需要知道的原因:(如果有人想知道......) 其中一个要求是分别对每行中的所有整数求和。 我创建了一个循环来逐个提取所有整数,直到它到达文件的末尾。但是,我很快就知道提取物>>运算符忽略空格/制表符/换行符。我想要尝试的是提取>>一个元素,然后使用inputFile.get()来获取空格/制表符/换行符。然后,如果它是换行符,那就做我要做的事情。 只有当流指针在最后一次提取>>之后提取空格/制表符/换行符时,这才有效。


In my previous question,我尝试使用getline()和sstring来解决它。


解决方案:

为了回答我的特定问题,关于运算符>>作品,我不得不接受Ben Voigt的答案是最好的答案。 我已经使用了这里建议的其他解决方案(每行使用一个sstring),它们确实有效! (你可以在我上一个问题的链接中看到它)然而,我使用Ben的答案实现了另一个解决方案,它也有效:

        .
        .
        .

if(readFile.is_open()) {
        while (readFile >> newInput) {
                char isNewLine = readFile.get();    //get() the next char after extraction

                if(isNewLine == '\n')               //This is just a test!
                        cout << isNewLine;          //If it's a newline, feed a newline.
                else
                        cout << "X" << isNewLine;   //Else, show X & feed a space or tab

                lineSum += newInput;
                allSum += newInput;
                intCounter++;
                minInt = min(minInt, newInput);
                maxInt = max(maxInt, newInput);

                if(isNewLine == '\n') {
                        lineCounter++;
                        statFile << "The sum of line " << lineCounter
                        << " is: " << lineSum << endl;
                            lineSum = 0;
                }
        }
        .
        .
        .

不考虑我的数值,表格是正确的!两个空格和'\ n'都被捕获了: test

谢谢Ben Voigt:)

尽管如此,这种解决方案依赖于格式,非常脆弱。如果任何行在'\ n'之前还有其他内容(如空格或制表符),则代码将错过换行符。因此,使用getline()和sstrings的另一个解决方案更加可靠。

4 个答案:

答案 0 :(得分:3)

提取后,流指针将被放置在导致提取终止的空白处(或其他非法字符,在这种情况下,也将设置failbit)。

但这并不重要,因为你不负责跳过这个空白。下一次提取将忽略空格,直到找到有效数据。

总结:

  • 忽略前导空格
  • 尾随空格留在流

还有noskipws修饰符可用于更改默认行为。

答案 1 :(得分:2)

operator>>将当前位置留在文件中 提取的最后一个字符之外的字符(可能是 文件结束)。这对你的问题不一定有帮助; 一行中的最后一个值后面可以有空格或制表符。您 可以跳过阅读每个字符并检查是否 它是'\n'以外的空白区域,但更为惯用 读取面向行的输入的方法是使用std::getline 读取该行,然后将std::istringstream初始化为 从行中提取整数:

std::string line;
while ( std::getline( source, line ) ) {
    std::istringstream values( line );
    //  ...
}

这也可以确保在行中出现格式错误时, 主输入的错误状态不受影响,您可以 继续下一行。

答案 2 :(得分:1)

根据cppreference.com,标准operator>>将工作委托给std::num_get::get。这需要一个输入迭代器。输入迭代器的一个属性是,您可以多次取消引用它而不会推进它。因此,当检测到非数字字符时,迭代器将指向该字符。

答案 3 :(得分:1)

一般来说,istream的行为并非一成不变。有多个标志可以更改istream的行为方式,您可以阅读here。一般来说,你不应该关心内部指针的位置;这就是你首先使用流的原因。否则,您只需将整个文件转储到字符串或等效文件中,然后手动检查它。

无论如何,回到你的问题,一种可能的方法是使用getline提供的istream方法来提取字符串。从字符串中,您可以手动读取它,或将其转换为stringstream并从那里提取令牌。

示例:

std::ifstream ifs("myFile");
std::string str;

while ( std::getline(ifs, str) ) {
    std::stringstream ss( str );
    double sum = 0.0, value;
    while ( ss >> value ) sum += value;
    // Process sum
}