[英]How exactly does the extract>> operator works in C++
我是一名計算機科學專業的學生,因此對C ++語言沒有太多經驗(考慮到這是我使用這種語言的第一個學期)或編碼。
我被賦予了一個從文本文件中讀取整數的賦值,其形式為:
19 3 -2 9 14 4
5 -9 -10 3
.
.
.
這讓我更好地了解了I / O操作符,因為我需要使用此流做某些事情(呃)。
我到處尋找,無法找到關於extract >>運算符如何在內部工作的簡單解釋。 讓我澄清一下我的問題:
我知道提取器>>運算符會提取一個連續元素,直到它到達空格,制表符或換行符。 我試圖弄清楚的是,指針(?)或讀取位置(?)在提取元素之后會在哪里。 它會被刪除的元素的最后一個字符,還是被刪除,因此消失了? 它會出現在空格/制表符/'\\ n'字符本身嗎? 也許是下一個要素提取的開始?
我希望我很清楚。 我缺乏所有適當的術語來更清楚地描述我的問題。
這就是為什么我需要知道這個:(如果有人想知道......)其中一個要求是分別對每行中的所有整數求和。 我創建了一個循環來逐個提取所有整數,直到它到達文件的末尾。 但是,我很快就了解到extract >>運算符忽略了空格/制表符/換行符。 我想要嘗試的是提取>>一個元素,然后使用inputFile.get()來獲取空格/制表符/換行符。 然后,如果它是換行符,那就做我要做的事情。 這僅在流指針處於良好位置以便在最后一次提取>>之后提取空格/制表符/換行符時才有效。
在我之前的問題中 ,我嘗試使用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的另一種解決方案更加可靠。
提取后,流指針將被放置在導致提取終止的空白處(或其他非法字符,在這種情況下,還將設置failbit)。
這並不重要,因為你不負責跳過那個空格。 下一次提取將忽略空格,直到找到有效數據。
綜上所述:
還有noskipws
修飾符,可用於更改默認行為。
operator>>
將文件中的當前位置保留為提取的最后一個字符之外的一個字符(可能位於文件末尾)。 這不一定有助於你的問題; 一行中的最后一個值后面可以有空格或制表符。 您可以跳過向前閱讀每個字符並檢查它是否是'\\n'
以外的空白區域,但更習慣的方法是讀取面向行的輸入是使用std::getline
讀取該行,然后初始化std::istringstream
從行中提取整數:
std::string line;
while ( std::getline( source, line ) ) {
std::istringstream values( line );
// ...
}
這還可以確保在行中出現格式錯誤時,主輸入的錯誤狀態不受影響,您可以繼續下一行。
根據cppreference.com ,標准operator>>
將工作委托給std::num_get::get
。 這需要一個輸入迭代器。 輸入迭代器的一個屬性是,您可以多次取消引用它而不會推進它。 因此,當檢測到非數字字符時,迭代器將指向該字符。
一般來說, istream
的行為不是istream
。 有多個標志可以改變任何istream
行為方式,你可以在這里閱讀。 一般來說,你不應該關心內部指針的位置; 這就是你首先使用流的原因。 否則,您只需將整個文件轉儲為字符串或等效文件,然后手動檢查它。
無論如何,回到你的問題,一種可能的方法是使用istream
提供的getline
方法來提取字符串。 從字符串,您可以手動讀取它,或將其轉換成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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.