Ошибка компиляции C ++ на std :: basic_ifstream

Я должен написать программу, которая объединяет числа в двух файлах и записывает все числа в третий файл. Программа принимает входные данные из двух разных файлов и записывает свои выходные данные в третий файл. Каждый входной файл содержит список чисел типа int в отсортированном порядке от наименьшего к наибольшему. После запуска программы выходной файл будет содержать все числа из двух входных файлов в одном более длинном списке в отсортированном порядке от наименьшего к наибольшему. Я не уверен на 100%, что моя логика верна. Спасибо за помощь.

inputFile1:

1 2 3 4 5 6 7 8 9 10

inputFile2:

11 12 13 14 15 16 17 18 19 20

#include <iostream>
#include <conio.h>
#include <fstream>

using namespace std;

int main()
{
int num1, num2;

ifstream inputFile;
ifstream inputFile2;
inputFile.open ("input1.txt");
inputFile2.open("input2.txt");
ofstream outputFile;
outputFile.open("output.txt");

inputFile >> num1;
inputFile2 >> num2;
while(inputFile.eof() && inputFile2.eof())
{
    if (num1 < num2)
    {
        outputFile << num1;
        inputFile >> num1;
    }
    else
    {       
        outputFile << num2;
        inputFile2 >> num2;
    }
    
}

inputFile.close();
inputFile2.close();
outputFile.close();

return 0;
}

person user1742419    schedule 28.10.2012    source источник
comment
Чего вы ожидаете от inputFile2.open();? Также не используйте while (!eof), используйте while (in >> var).   -  person chris    schedule 28.10.2012
comment
Вы можете объяснить, что в ›› означает var? Я так и не узнал. Я предполагаю, что var - это просто переменная, которую я использую, но 'in'?   -  person user1742419    schedule 28.10.2012
comment
Это просто общее. in будет входным потоком, который в вашем случае может быть inputFile или inputFile2.   -  person chris    schedule 28.10.2012
comment
@ user1742419 Вас учили использовать while (!inputFile.eof())?   -  person john    schedule 28.10.2012
comment
Да, но похоже, что это табу, и я боюсь ответить утвердительно на ваш вопрос.   -  person user1742419    schedule 28.10.2012
comment
Кажется, это невероятно распространенная ошибка, и очень неприятно слышать, что вас научили ее использовать. Вы, конечно, не должны были знать лучше. Вы можете прочитать здесь, чтобы узнать, почему это неверно stackoverflow.com/questions/5605125/ В основном люди используют его так, как будто eof() может определить, находитесь ли вы в конце файла. но это совсем не то, что он делает. Он сообщает вам, не удалось ли последнее чтение из-за конца файла. Что совсем другое.   -  person john    schedule 28.10.2012


Ответы (3)


Если можно использовать стандартную библиотеку, можно использовать merge:

int main()
{
    ifstream inputFile("input1.txt");
    ifstream inputFile2("input2.txt");
    ofstream outputFile("output.txt");

    typedef istream_iterator<int> IT;
    typedef ostream_iterator<int> OT;
    std::merge(IT(inputFile), IT(), IT(inputFile2), IT(), OT(outputFile, " "));

    outputFile.flush();
}

Также обратите внимание, что конструктор i / ofstream может открывать файл во время инициализации.

person Yakov Galka    schedule 28.10.2012
comment
Это, безусловно, мое любимое показанное решение, однако я бы избавился от явных закрытий, которые в любом случае произойдут при уничтожении, RAII - сильная сторона C ++, давайте использовать его! - person 111111; 28.10.2012
comment
@ 111111: Избавиться от закрытия inputFiles можно, но избавиться от закрытия outputFile - Нет. Я бы на самом деле заменил его на флеш. В основном RAII имеет семантику отката, тогда как close () и flush () являются семантикой фиксации. (Я не говорю об атомарности здесь.) Сброс может вызвать ошибку, поэтому, если вы закрываете файл во время обычного потока, вы можете захотеть получить возможное исключение. - person Yakov Galka; 28.10.2012
comment
Я почти уверен, что он вспыхивает и при разрушении. при явном закрытии файловых потоков возникает проблема, заключающаяся в том, что именованные объекты имеют недопустимое состояние. - person 111111; 28.10.2012
comment
@ 111111: Да, сбрасывается, но вы не знаете, не сработает ли он. Что касается недействительного состояния, вот почему я сказал, что вместо этого я буду промывать. - person Yakov Galka; 28.10.2012
comment
но в представленном вами коде .flush () в любом случае просто возвращает поток, который вы не проверяете, так как это отличается от простого разрешения деструктору делать это? Если бы у вас было это в if() с каким-то кодом обработки, я бы согласился. Также вы знаете, что flush на самом деле не записывает данные на диск, а просто передает их ОС, что маловероятно. - person 111111; 28.10.2012
comment
@ 111111: код вообще не проверяет ошибки, потому что это не суть qstn / answer. Пока мы говорим о том, следует ли вызывать flush или нет в реальном коде, ответ - «да». 1) Не все потоки используют std :: filebuf, и даже реализация std :: filebuf может указывать на сбой, генерируя исключение, и в этом случае установка exceptions(badbit) даст вам желаемую обработку ошибок. 2) Реализация std::filebuf может фактически сбрасывать на диск, хотя не все из них делают это. 3) если сбросить сбой в приведенном выше коде в наборах badbit, которые вы можете проверить позже. - person Yakov Galka; 28.10.2012
comment
Единственная проблема, с которой я столкнулся, это то, что я понятия не имею, что происходит, лол. - person user1742419; 28.10.2012
comment
@ user1742419: ну, если это домашнее задание (а это выглядит так), то инструктор, вероятно, хотел, чтобы вы выполнили merge самостоятельно, и этот ответ вам не поможет. Если да, то вам следовало добавить тег «домашнее задание». - person Yakov Galka; 28.10.2012
comment
В прошлый раз, когда я добавил тег «домашнее задание», мне сказали, что в этом больше нет необходимости. Кроме того, я пока изучал только основы, так что я даже не изучил слияние, ха-ха. - person user1742419; 29.10.2012

inputFile2.open();

должно быть

inputFile2.close();
person codaddict    schedule 28.10.2012
comment
Или просто удалите явные закрытия вообще, они всего лишь источник ошибок. - person 111111; 28.10.2012

inputFile2.open(); - это явно опечатка для inputFile2.close();

Но боюсь, ваша логика совершенно неверна. Вы не поняли смысл упражнения. Вы должны открывать и входные файлы, и выходной файл одновременно, и вы не должны использовать массив для хранения и сортировки чисел. Если вы сделаете это правильно, вам не понадобится массив и вообще не нужно будет выполнять какую-либо сортировку. В этом суть упражнения.

И повторить то, что уже было сказано минимум миллион раз на этом форуме. Не используй

while (!inputFile.eof())

Это неверно. Использовать

while (inputFile >> num)

Это очень простой набросок того, как выполнить слияние. Есть много деталей, которые нужно заполнить.

inFile1 >> num1;
inFile2 >> num2;
while (something or other)
{
  if (num1 < num2)
  {
    outFile << num1;
    inFile1 >> num1;
  }
  else
  {
    outFile << num2;
    inFile2 >> num2;
  }
}

Здесь есть ирония: «что-то или другое», вероятно, действительно связано с использованием eof(). Это единственный случай, когда использование inFile.eof() - правильное решение.

Кстати, ваши входные данные не очень хороши. Каждый файл должен быть отсортирован по отдельности, но у вас не должно быть всех чисел в файле1 меньше, чем все числа в файле2. Это не обязательно.

person john    schedule 28.10.2012
comment
Разве это не было бы inputFile >> i? - person user1742419; 28.10.2012
comment
num и i - просто переменные, вы можете называть их как хотите. Я использовал num только для обозначения числа. - person john; 28.10.2012
comment
Что именно указывают переменные? Думаю, я мог неправильно использовать это место, поставив там «i». Имеет значение, какая переменная? - person user1742419; 28.10.2012
comment
Конечно, какая переменная вы используете, имеет значение для логики вашей программы, если вы введете неправильную переменную, ваша программа не будет работать. У вас проблемы с концепцией переменной? Это довольно фундаментально, и вам придется бороться в будущем, если у вас нет четкой концепции. - person john; 28.10.2012
comment
Я имею в виду, что я не знаю, какую переменную использовать вместо той переменной, которую вы сказали. Потому что технически у меня в этом цикле две переменные. У меня есть массив num, а затем переменная счетчика i. Я не знаю, что использовать и почему. - person user1742419; 28.10.2012
comment
Что ж, вам предстоит потренироваться в решении этого упражнения. Как я уже сказал, вам не нужно использовать массив для решения этой головоломки. Подумайте, как бы вы решили эту проблему, если бы делали это сами. Сканируете ли вы два списка чисел один за другим или оба одновременно? Помните, что два списка чисел уже отсортированы, это очень важно. Какая разница? По сути, суть этого упражнения в том, что вы можете решить его, не разбираясь самостоятельно. - person john; 28.10.2012
comment
О Боже. . Мне будет стыдно это сказать. Но я не понимал, что должен был создать два файла с номерами в порядке сортировки. Я создал файлы, но без порядка сортировки. ха-ха. Я перечитал это снова и знаю, как это исправить. Спасибо. - person user1742419; 28.10.2012
comment
Я думал о том, что вы сказали, и не думаю, что смогу правильно сравнить их без массива, потому что что, если десятое число, которое я ввожу из файла, меньше первого числа, которое я беру из файла? Я не могу сравнивать их, если не использую массив. . . - person user1742419; 28.10.2012
comment
Что ж, в этом вся хитрость. 1) Прочтите по одному числу из каждого файла. 2) Сравните их и запишите меньшее число в свой результат. 3) Прочтите еще одно число, но только из файла с меньшим номером. Повторите процедуру, начиная с шага 2. Продолжайте, пока у вас не кончится числа. Таким образом, вы всегда храните только два числа, по одному из каждого файла, поэтому вам нужны только две переменные int, вам не нужен массив. Это основная идея, но есть немного больше деталей, которые нужно исправить (например, что вы делаете, когда у вас больше нет чисел в одном файле). - person john; 28.10.2012
comment
Вроде, но вы выводите оба числа, как я уже сказал, выводите только меньшее число. Вы не знаете, нужно ли выводить большее число, потому что в другом файле может быть другое меньшее число (как вы сказали в своем предыдущем комментарии). Также это while(inputFile>>num1 && inputFile2>>num2). - person john; 28.10.2012
comment
Я только что заметил, что в выходной файл ничего не выводится. Не понимаю, почему бы и нет. . . - person user1742419; 28.10.2012
comment
Извините, мой последний комментарий сбил с толку. while(inputFile>>num1 && inputFile2>>num2) тоже неверно. Важная часть этого (которую, я думаю, вы еще не поняли) заключается в том, что каждый раз в цикле вы читаете и записываете только одно число. Даже если вы читаете из двух файлов одновременно, вы выбираете чтение из одного или другого в зависимости от того, какое число меньше. Это ясно? В любом случае, мне пора. - person john; 28.10.2012
comment
Я так не думаю. Я попробовал другой метод и до сих пор не думаю, что получу желаемый результат. Обновленный код еще раз выше. Я даже не понимаю, как сравнить его с последним числом в выходном файле. - person user1742419; 28.10.2012
comment
Я обновил свой код, приведенный выше, с помощью базового эскиза. Код неверен, но я оставлю вам его исправить. - person john; 28.10.2012
comment
Я обновил свой код до того, что сделал до сих пор, но не очень. Единственный вопрос, который у меня есть, - почему мой код вообще ничего не выводит. Никаких результатов не получаю. - person user1742419; 28.10.2012
comment
Я думаю, что логика в вашем цикле while неверна, должно быть while (!inputFile.eof() && !inputFile2.eof()). Т.е. продолжайте цикл, когда у вас все еще есть числа из обоих файлов. Еще одна вещь, вам нужно будет решить, что делать, когда вы дойдете до конца файла в одном файле, но не в другом. Я оставляю вас думать об этом, но вам придется добавить еще код, чтобы справиться с этой ситуацией. - person john; 29.10.2012
comment
Мой профессор обычно подробно говорит о том, что повышение эффективности программы было бы дополнительным преимуществом, но сейчас я просто хочу, чтобы она работала. И пока мой выходной файл вылетает, когда я пытаюсь открыть его после изменения кода на while (!inputFile.eof() && !inputFile2.eof()) - person user1742419; 29.10.2012