Как использовать file.eof () при чтении целых чисел из файла? - PullRequest
0 голосов
/ 16 января 2020

Я пишу программу, которая считывает данные из файла. Файл содержит строки целых чисел, такие как

5 6 2 8 6 7

2 5 3

4 0 9 1 3

Первое целое число каждой строки соответствует количеству чисел в этой строке. Моя цель - прочитать в каждой строке, сохранить числа в векторе и поработать с ними. Вот что я сделал:

int main(){

 vector<int> vec;
 int amount;
 int nums;
 ifstream file ("file.txt");


 while(!(file.eof())){
     file >> amount;
     cout << amount << endl;

     for (int i = 0; i < amount; i++){
         file >> nums;
         vec.push_back(nums);
     }

 printArray(vec);
 bubbleSort(vec);
 vec.clear();
 }

 return 0;
}

К сожалению, последняя строка всегда читается дважды. Я посмотрел онлайн и увидел, что функция eof () не должна использоваться для поддержки циклов. Что еще я мог бы использовать в этой ситуации?

Спасибо.

1 Ответ

1 голос
/ 16 января 2020

operator>> устанавливает флаг потока eofbit, если он пытается прочитать мимо EOF. Вы можете использовать это условие, чтобы разорвать ваши петли. Но вы должны фактически выполнить операцию чтения ДО того, как вы сможете оценить eof(). См. Почему iostream :: eof внутри условия al oop (т. Е. `While (! Stream.eof ())`) считается неправильным? для получения более подробной информации об этом.

Поскольку вы имеют дело с текстом на основе строки, вы можете использовать std::getline(), чтобы сначала прочитать каждую строку, а затем вы можете использовать std::istringstream для анализа каждой строки, например:

int main()
{
    vector<int> vec;
    ifstream file ("file.txt");
    string line;

    while (getline(file, line)) {
        istringstream iss(line);
        int amount, nums;

        iss >> amount;
        cout << amount << endl;

        for (int i = 0; (i < amount) && (iss >> nums); ++i){
            vec.push_back(nums);
        }

        printArray(vec);
        bubbleSort(vec);
        vec.clear();
    }

    return 0;
}

В качестве альтернативы, вы можете просто взять Преимущество того факта, что operator>> пропускает пробел, , включая разрывы строк, например:

int main()
{
    vector<int> vec;
    int amount, nums;
    ifstream file ("file.txt");

    while (file >> amount) {
        cout << amount << endl;

        for (int i = 0; (i < amount) && (file >> nums); ++i){
            vec.push_back(nums);
        }

        printArray(vec);
        bubbleSort(vec);
        vec.clear();
    }

    return 0;
}

Хотя этот подход будет несколько менее устойчивым к ошибкам во входных данных, по сравнению к подходу std:getline(). Если фактическое количество чисел в данной строке не соответствует указанному количеству в начале строки, при таком подходе чтение файла не будет синхронизировано c. Хуже того, если заданная строка содержит нецелочисленные значения, этот подход вообще не сможет читать любые последующие данные.

В подходе std:getline(), если данная строка искажена, код просто переместится перейдите к следующей строке и продолжайте, как ничего плохого не случилось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...