因为eof,用C ++读取文件两次?

时间:2011-04-16 04:45:45

标签: c++ readfile eof

我从文件中读取数字,应用3个函数并打印到另一个文件:

int main(int argc, char** argv) {
    std::ifstream fin;
    fin.open("input.txt");

    std::ofstream fout;
    fout.open("output.txt", std::ios::app);

    char arr[50];
    int a,b;
    int N;//number to factor

    while (!fin.eof()){
        //Print backward
        fin >> arr;
        PrintBackward( arr );
        fout << endl;

        //Greatest common divisor
        ((fin >> a) >> b);
        fout << gcd( a, b );
        fout << endl;

        //Find prime factor
        fin >> N;
        PrimeFactor(N);
        fout << endl;     
    }

    fin.close();
    fout.close();

    return 0;
}

运行后,结果重复:

olleh
3
2 3 7 
olleh
3
2 3 7

我读了一篇类似的文章,但它是关于读入1变量的,所以它似乎不可行。

如果我在break循环结束时设置while,那很好。有没有办法不使用break

2 个答案:

答案 0 :(得分:3)

while (!whatever.eof())基本上总是错误的,永远不会正确检测到文件的结尾。在你的情况下,最简单的方法是将读取合并在一起,然后进行所有处理,如下所示:

while (fin >> arr >> a >> b >> N) {
    PrintBackwards(arr);
    fout << "\n";

    fout << gcd(a, b) << "\n";

    fout << PrimeFactor(N) << "\n";
}

关键部分是检查阅读结果,而不是彼此分开检查和阅读。

还有一些建议:我使用std::string代替数组。我还将字符串从打印中分离出来,因此您可以使用以下内容:

fout << reverse(arr)   << "\n" 
     << gcd(a, b)      << "\n" 
     << PrimeFactor(N) << "\n";

强调操作之间的共性往往是一件好事。

编辑:只是为了好玩,我会指出你可以做的另一种方法,如果你想要的话。由于您基本上是将这四个项目作为一个组进行阅读和处理,因此可以使该分组更加明确:

struct item { 
     std::string arr;
     int a, b, N;

     friend std::istream &operator>>(std::istream &is, item &i) { 
         return is >> arr >> a >> b >> N;
     }
};

struct process {
    std::string operator()(item const &i) { 
        std::ostringstream buffer;

        buffer << reverse(arr) << "\n" << gcd(a, b) << "\n" << PrimeFactor(N);
        return buffer.str();
    }
}

有了这个,您可以让标准库处理读写的所有细节,检查文件结尾等等:

std::transform(std::istream_iterator<item>(fin), 
               std::istream_iterator<item>(),
               std::ostream_iterator<std::string>(std::cout, "\n"),
               process());

答案 1 :(得分:0)

我的猜测是你过早检查eof - 它只在你尝试阅读时设置,并且因为你在文件末尾而读取失败。尝试在fin >> arr之后添加此内容:

if (fin.eof()) break;

实际上你应该在每次IO操作后检查错误 - 不是这样做是编码粗糙而且不稳健。