由于eof,在c++中对一个文件读两次



我从一个文件中读取数字,应用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

我读过一篇类似的文章,但它是关于读取到一个变量,所以似乎不可行。

如果我在while循环的末尾设置一个break,它是好的。有没有办法不使用break ?

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());

我猜您检查eof太早了—它只在您尝试读取并且读取失败时设置,因为您在文件的末尾。试着在fin >> arr:

后面添加这个
if (fin.eof()) break;

实际上,您应该在每次IO操作后检查错误-不这样做是草率的编码,并且不会健壮

相关内容

最新更新