![](/img/trans.png)
[英]difference betwen file.get(char c) and file.get(char *c, int length)
[英]file.get() returning random numbers after a loop C++
我正在開發一個程序,該程序將文本文件中的一系列整數讀取到二維數組中。
該文件包含 40 行,每行 81 個數字,它們之間沒有空格。
問題是當我在循環完成后計算數組時,它在預期的 output 之前在array[0][0]
和array[0][1]
中輸出 2 個隨機數。我認為這與換行符/回車符。 循環的第一次迭代運行完美。 這是代碼:
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int array[9][9];
//Open file:
fstream ifile;
ifile.open("numbers.txt", ios::in);
if (ifile.fail())
{
cout << "Could not open numbers.txt" << endl;
return -1;
}
while (!ifile.eof())
{
for(int i=0; i<9; i++)
{
for(int j=0; j<9; j++)
{
int n = ifile.get();
if(isdigit(n))
{
array[i][j] = n - '0';
}
cout<<"array ["<<i<<"]["<<j<<"] is "<<array[i][j]<<endl;
}
} cout<<"This is a test"<<endl;
}
return 0;
}
我根本不明白外循環的目的。 首先, file
永遠不會等於eof()
,或者......什么是eof()
,無論如何? 其次,如果您實際上已經編寫while (.file.eof() )
,這可以解釋某些元素被覆蓋的事實。 在最后一個數字之后可能會有一些尾隨字符(至少是一個新行),因此您將再次重新進入循環。
即使您讀取的字符不是數字,您也會增加索引。 如果數據是 9 行 9 位數字,那么在完成內部兩次迭代后,網格中將有 9 個單元grid
尚未初始化,並且還有 9 個字符尚未從文件中讀取。 所以你將再次進入外循環,讀取這些字符。 其中一些將是數字,因此您最終會覆蓋您已經寫入的grid
中的單元格——這可能是您觀察到的效果。 此外,一旦到達文件末尾, file.get()
將開始返回EOF
通常為 -1。 這無疑就是為什么您對'\n'
和'\r'
的測試不起作用的原因。
這些只是格式正確的文件的問題。 對於格式正確的文件,只需使用file >> n
和char n;
幾乎可以工作; operator>>
跳過空格。 但是你仍然會第二次進入最外層的循環,因為file.eof()
在輸入失敗之前是不可靠的。 你說“我必須使用這個”,但除非你改變它,否則你的代碼無法工作。
就個人而言,我喜歡強大的解決方案,並進行大量錯誤檢查。 我會使用std::getline()
,並且我會驗證每一行是否正好包含 9 位數字。 就像是:
std::string line;
int i = 0;
while ( i < 9 && std::getline( file, line ) ) {
if ( line.size() != 9 ) {
throw FormatError( "wrong line length" );
}
for ( int j = 0; j != 9; ++ j ) {
if ( ! isdigit( static_cast<unsigned char>( line[j] ) ) ) {
throw FormatError( "illegal character" );
}
grid[i][j] = line[i] - '0';
}
}
if ( i != 9 || std::getline( file, line ) ) {
throw FormatError( "wrong line count" );
}
使用file.get()
並一次讀取一個字符並不會太難,但是您仍然希望在每次讀取后檢查EOF
:
for ( int i = 0; i != 9; ++ i ) {
for ( int j = 0; j != 9; ++ j ) {
int ch = file.get();
if ( ch == EOF ) {
throw FormatError( j == 0
? "line too short"
: "too few lines" );
}
if ( !isdigit( ch ) ) {
throw FormatError( "illegal character" );
}
grid[i][j] = ch - '0';
}
int ch = file.get();
if ( ch != '\n' ) {
throw FormatError( ch == EOF ? "too few lines" : "line too long" );
}
}
if ( file.get() != EOF ) {
throw FormatError( "too many lines" );
}
出現隨機數是因為無論您是否寫入grid[i][j]
,您都會遞增j
。
嘗試用以下內容替換您的內部循環:
for(int j=0; j<9; )
{
int n = file.get();
if(!file) break;
if(isdigit(n))
{
array[i][j] = n - '0';
cout<<"array ["<<i<<"]["<<j<<"] is "<<array[i][j]<<endl;
j++;
}
cout<<"grid ["<<i<<"]["<<j<<"] is "<<grid[i][j]<<endl;
}
當您到達文件末尾時不會設置eof
,它會在讀取失敗后設置。 最后一次讀取的數據當然是無效的,因為它失敗了。 您當前的代碼使用了無效數據...
除此之外, file != eof()
是各種錯誤。 它甚至不應該編譯,因為沒有::eof()
function,而iostream::eof()
需要一個 object。file file != EOF
可能會編譯,但隨后file
將被轉換為 bool 並提升為 int(要么0
或1
),它永遠不會等於EOF
( -1
)。 您的意思是.file.eof()
,但由於上述原因,這也是錯誤的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.