我是一名计算机科学专业的学生,因此对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'都被捕获了:
谢谢Ben Voigt:)
尽管如此,这种解决方案依赖于格式,非常脆弱。如果任何行在'\ n'之前还有其他内容(如空格或制表符),则代码将错过换行符。因此,使用getline()和sstrings的另一个解决方案更加可靠。
答案 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
}