Неправильно выводятся числа из файла в массив
Мне нужно вывести числа записанные в файле input_data.txt в массив, но вместо ожидаемого массива в виде
11 5 7
3 4 6
18 15 9
получаю вот это:
main.cpp:
#include <fstream>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cmath>
using namespace std;
int main() {
ifstream input_data;
input_data.open("input_data.txt");
if (!input_data.is_open()) {
cout << "Error while opening file";
system("pause");
return 0;
}
// int SIZE = input_data.gcount();
int count = 0;
while (!input_data.eof()) {
char ch;
while (input_data >> ch)
count++;
}
int SIZE = sqrt(count);
double** arr = new double* [SIZE];
for (int i = 0; i < SIZE; i++)
arr[i] = new double[SIZE];
for (int i = 0; i < SIZE; i++)
for (int j = 0; j < SIZE; j++)
input_data >> arr[i][j];
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++)
cout << arr[i][j] << " ";
cout << "\n";
}
double max;
max = (arr[0][0] > arr[1][0]) ? arr[0][0] : arr[1][0];
max = (arr[0][0] > arr[2][0]) ? arr[0][0] : arr[2][0];
max = (arr[1][0] > arr[2][0]) ? arr[1][0] : arr[2][0];
ofstream output_data;
output_data.open("output_data.txt");
if (!output_data.is_open()) {
cout << "Error while opening file";
system("pause");
return 0;
}
else {
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
output_data << setprecision(3) << fixed << arr[i][j] / max << " ";
}
output_data << endl;
}
}
for (int i = 0; i < SIZE; i++)
delete[] arr[i];
delete[] arr;
input_data.close();
output_data.close();
return 0;
}```
Ответы (2 шт):
Посмотрите на вот этот Ваш код:
while (!input_data.eof()) {
char ch;
while (input_data >> ch)
count++;
}
Вы дочитали файл до конца. Ему система выставила флаг, что он уже прочитан. А Вы после этого пытаетесь из него выжать (прочитать) что-то еще. Что же Вы сможете прочитать? - разве что ошибки оператора ввода.
Как исправить? Во-первых, нужно "перемотать" файл на начало с помощью команды типа input_data.seekg(0). Во-вторых, вам нужно сбросить флаг достижения конца файла: input_data.clear(). И только после этого можно пытаться читать файл заново. (как вариант - можно закрыть и потом снова открыть файл, но "это грубо и не по-европейски" (c))
Все это было бы хорошо, но даже тогда, Вы получите снова ошибку из-за того, что Вы неверно определяете необходимый размер массивов SIZE. Вы его пытаетесь вычислить через размер файла? А кто сказал, что все числа будут одноразрядные? И как тут учесть пробелы - они же тоже занимают место в файле? В приведенном цикле Вам нужно бы считывать не в переменную типа char, а считать, сколько раз удастся прочитать данные того типа, из которого у Вас состоит массив (double).
В первую очередь вам необходимо ознакомиться с тем, как вообще работают потоки ввода/вывода в c++. Общая их характеристика - флаги состояния. Можно почитать общую документацию по basic_ifstream здесь. В случае, если чтение из файла может продолжаться, по умолчанию стоит флаг goodbit. Если встречается какая-то ошибка, из-за которой невозможен дальнейший ввод/вывод, либо требуется вмешательство пользователя, то выставляются флаги ошибки eof, badbit и другие в зависимости от типа ошибки.
В вашем случае в вот этом отрезке кода вы считываете весь файл посимвольно, вплоть до конца файла:
while (!input_data.eof()) {
char ch;
while (input_data >> ch)
count++;
}
Вполне логично предположить, что когда встречается конец файла, выставляется флаг eof, что делает дальнейший ввод/вывод невозможным (и это причина по которой input_data.eof() возвращает true). Далее вы пытаетесь заполнить массив, пытаясь снова вывести что-то из файла, но выводить уже нечего - конец файла достигнут.
Для решения проблемы нужно сделать две вещи:
- Сбросить флаги ошибок
- Вернуть курсор в начало файла, либо пересоздать соединение с ним (первый вариант предпочтительнее по очевидным причинам)
Сброс eof флага осуществляется при помощи функции basic_ifstream::clear(). Почитать конкретно о функции можно тут.
Смена же позиции курсора достигается функцией basic_ifstream::seekg. В вашем случае нужно прописать input_data.seekg(0).
Кроме того, я настоятельно рекомендую заменить динамический массив на, например, std::string или std::vector заполнять его внутри while, примерно так:
// Код на идеальность не претендует
// Работоспособность не проверял
std::string data;
while (!input_data.eof()) {
char ch;
while (input_data >> ch)
count++;
data.push_back(ch);
}
