Прочитать файл дважды в C ++ из-за eof? - PullRequest
0 голосов
/ 16 апреля 2011

Я читаю числа из файла, применяю 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 ]

3 голосов
/ 16 апреля 2011

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

Таким образом, вы можете позволить стандартной библиотеке обрабатывать все деталичтение и запись, проверка конца файла и т. д .: * 10101

std::transform(std::istream_iterator<item>(fin), 
               std::istream_iterator<item>(),
               std::ostream_iterator<std::string>(std::cout, "\n"),
               process());
0 голосов
/ 16 апреля 2011

Я предполагаю, что вы проверяете eof слишком рано - это устанавливается только тогда, когда вы пытаетесь прочитать, и чтение не удается, потому что вы находитесь в конце файла. Попробуйте добавить это после fin >> arr:

if (fin.eof()) break;

На самом деле вы должны проверять ошибки после каждой операции ввода-вывода - не делать этого - неаккуратное кодирование и оно не будет устойчивым.

...