该文件设置正确,但eof()和peek()意外地从新流返回错误的值

时间:2017-11-07 11:26:04

标签: c++ fstream iostream

我想生成一个随机数组。

void Random_nums(int n, string fileName) {

    ofstream fsave(fileName);
    int ranArray[n];

    srand( (unsigned int)time(NULL) );
    for(int i=0; i<n; i++)
    {
        ranArray[i]=rand()%2001 - 1000;
        fsave << ranArray[i] << '\n'; //save them into ranArray
    }

    fsave.close();
}

我想将它们保存到一个单独的文件中。

之后我想读取刚刚保存的数据并在新函数中实现它们。

void FunctionWantToUse(string inputFile, string outputFile) {

    //reading data
    ifstream fin(inputFile);
    cout << fin.is_open();//which is 1

    //how many numbers are there in this file
    int n = 0;
    n = distance(istream_iterator<int>(fin), istream_iterator<int>());

    //restore the array
    int array[n];

    //test
    cout << fin.peek() << ' ' << EOF;//they are both -1!

    //another test
    cout << fin.peek() << '\n'; //which return -1
    cout << fin.eof() << '\n'; //which return 1

    //since peek() and EOF both return -1, I can't get into this loop. 
    while (fin.peek() != EOF) {
        if ((fin >> array[i]).good()) {
            cout << array[i];
        }
    }

完全不知道为什么fin.peek()和fin.eof()的值分别变为-1和1。

当我运行这两个功能时,控制台告诉我这个。

-1 -1-1
1

Process finished with exit code 0

我还提供了一些其他测试,例如,当我生成随机数时,将fsave.eof()置于循环中,并打印出所有0。

有人可以告诉我这里发生了什么吗?我现在完全没有任何线索。

1 个答案:

答案 0 :(得分:3)

使用std::distance(istream_iterator<int>(fin), istream_iterator<int>()),您将浏览该文件,直至其无法阅读并int。发生这种情况要么是因为有一些输入无法解析为int(在跳过前导空格之后)或文件结尾。在任何情况下,当对distance()的调用返回时,流将设置为std::ios_base::failbit,如果错误是由于文件末尾也到达std::ios_base::failbit

明显的解决方法是确定距离,而是直接将整数读取到合适的表示中。例如:

std::vector<int> array{std::istream_iterator<int>(fin),
                       std::istream_iterator<int>()};

如果你真的想要使用循环,你应该测试流是否在之后从流中读取失败状态,例如:

for (int tmp; fin >> tmp; ) {
    // use tmp
}

如果您确实需要先确定元素数量,那么您需要

  1. clear()设置std::ios_base::failbit后的流状态。如果没有这一点,大多数流操作将被忽略。
  2. seekg()回到流的开头。
  3. 但请注意,调整std::vector<int>几次调整几乎肯定比读取文件并解析其内容两次更有效。

    BTW,你对数组的使用有两个问题:

    1. 可变大小的数组是标准C ++的一部分,尽管有些编译器确实支持它们作为扩展。
    2. 如果文件大小合理,您将获得堆栈溢出。
    3. 最好不要使用std::vector<int>