我正在研究一个从文本文件到2D数组中读取一系列整数的程序。
该文件包含40行81个数字,它们之间没有空格。
问题在于,当我在循环结束后输出数组时,它会在预期输出之前在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;
}
答案 0 :(得分:2)
我根本不了解外循环的目的。首先,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()
直到将是不可靠的
输入失败。你说“我必须使用它”,但你的代码不能
除非你改变它,否则必须工作。
就个人而言,我赞成使用大量错误检查的强大解决方案。 ID
使用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" );
}
答案 1 :(得分:1)
随机数会显示,因为无论您是否写入j
,都会增加grid[i][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;
}
答案 2 :(得分:1)
eof
,它在读取失败后设置。而上次读取的数据当然是无效的,因为它失败了。您当前的代码使用无效数据...
除此之外,file != eof()
是各种错误的。它甚至不应该编译,因为没有::eof()
函数,iostream::eof()
需要一个对象。 file != EOF
可能会编译,但file
会转换为bool并提升为int(0
或1
),它永远不会等于EOF
(-1
)。你的意思是!file.eof()
,但由于上面给出的原因,这也是错误的。