Как считать динамический массив из файла с
Перейти к содержимому

Как считать динамический массив из файла с

  • автор:

Чтение чисел из текстового файла в динамический массив

При попытке считывания цифр из файла и их записи в одномерный массив, считывание прекращалось при появлении первого же пробела.

#include #include using namespace:: std; int main()< int input_float_vector_size=0; float* input_float_vector = new float[input_float_vector_size]; // динамический вектор, для записи полученных из файла чисел в массив ifstream file; file.open("INPUT.txt"); if(!file.is_open())< cout else< while(file>>input_float_vector[input_float_vector_size]) < cout > delete [] input_float_vector; file.close(); 

return 0; > Этот вопрос наверняка давно имеет ответ. Однако найденные советы не помогали. Вскоре эмпирически выяснилось, что проблема решается способом открытия самого файла. При открытии с помощью конструктора ifstream file(«INPUT.txt»), а не традиционно file.open(«INPUT.txt») все работает прекрасно! Объясните причину.

Отслеживать
219k 15 15 золотых знаков 120 120 серебряных знаков 230 230 бронзовых знаков
задан 6 янв 2020 в 6:54
299 2 2 серебряных знака 18 18 бронзовых знаков

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Ваша, гм. вобщем, неприятности тут:

int input_float_vector_size=0; float* input_float_vector = new float[input_float_vector_size]; // динамический вектор, для записи полученных из файла чисел в массив 

Выделен массив нулевой длины. Который, как бы вы ни надеялись, что, увеличивая некую переменную, он будет расти — так поверьте, это то же самое, что написать на бумажке «дай мне 100 рублей» и получив их, рассчитывать, что если вы теперь на бумажке зачеркнете 100 и напишете 10000 — то у вас от этого в кошельке что-то прибавится.

Вы пишете неизвестно куда, имея классическое «неопределенное поведение», так что то, что вам кажется что программа заработала — так это не так.

vector input; . float i; while(file >> i) input.push_back(i); 

Можно вообще через copy , но это пока для вас рановато, разберитесь с этим.

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

Как считать динамический массив из файла с

Кроме отдельных динамических объектов в языке C++ мы можем использовать динамические массивы. Для выделения памяти под динамический массив также используется оператор new , после которого в квадратных скобках указывается, сколько массив будет содержать объектов:

int *numbers ; // динамический массив из 4 чисел // или так // int *numbers = new int[4];

Причем в этом случае оператор new также возвращает указатель на объект типа int — первый элемент в созданном массиве.

В данном случае определяется массив из четырех элементов типа int, но каждый из них имеет неопределенное значение. Однако мы также можем инициализировать массив значениями:

int *numbers1 >; // массив состоит из чисел 0, 0, 0, 0 int *numbers2 >; // массив состоит из чисел 1, 2, 3, 4 int *numbers3 >; // массив состоит из чисел 1, 2, 0, 0 // аналогичные определения массивов // int *numbers1 = new int[4]<>; // массив состоит из чисел 0, 0, 0, 0 // int *numbers1 = new int[4](); // массив состоит из чисел 0, 0, 0, 0 // int *numbers2 = new int[4]< 1, 2, 3, 4 >; // массив состоит из чисел 1, 2, 3, 4 // int *numbers3 = new int[4]< 1, 2 >; // массив состоит из чисел 1, 2, 0, 0

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

Стоит отметить, что в стандарт С++20 добавлена возможность выведения размера массива, поэтому, если применяется стандарт С++20, то можно не указывать длину массива:

int *numbers >; // массив состоит из чисел 1, 2, 3, 4

После создания динамического массива мы сможем с ним работать по полученному указателю, получать и изменять его элементы:

int *numbers >; // получение элементов через синтаксис массивов std::cout 

Причем для доступа к элементам динамического массива можно использовать как синтаксис массивов ( numbers[0] ), так и операцию разыменования ( *numbers )

Соответственно для перебора такого массива можно использовать различные способы:

unsigned n< 5 >; // размер массива int* p < new int[n] < 1, 2, 3, 4, 5 >>; // используем индексы for (unsigned i<>; i < n; i++) < std::cout std::cout ; i < n; i++) < std::cout std::cout ; q != p + n; q++) < std::cout std::cout 

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

Для удаления динамического массива и освобождения его памяти применяется специальная форма оператора delete :

delete [] указатель_на_динамический_массив;

#include int main() < unsigned n< 5 >; // размер массива int* p < new int[n] < 1, 2, 3, 4, 5 >>; // используем индексы for (unsigned i<>; i < n; i++) < std::cout std::cout

Чтобы после освобождения памяти указатель не хранил старый адрес, также рекомендуется обнулить его:

delete [] p; p = nullptr; // обнуляем указатель

Многомерные массивы

Также мы можем создавать многомерные динамические массивы. Рассмотрим на примере двухмерных массивов. Что такое по сути двухмерный массив? Это набор массив массивов. Соответственно, чтобы создать динамический двухмерный массив, нам надо создать общий динамический массив указателей, а затем его элементы - вложенные динамические массивы. В общем случае это выглядит так:

#include int main() < unsigned rows = 3; // количество строк unsigned columns = 2; // количество столбцов int** numbers>; // выделяем память под двухмерный массив // выделяем память для вложенных массивов for (unsigned i<>; i < rows; i++) < numbers[i] = new int[columns]<>; > // удаление массивов for (unsigned i<>; i < rows; i++) < delete[] numbers[i]; >delete[] numbers; >

Вначале выделяем память для массива указателей (условно таблицы):

int** numbers>;

Затем в цикле выделяем память для каждого отдельного массива (условно строки таблицы):

numbers[i] = new int[columns]<>;

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

Пример с вводом и выводом данных двухмерного динамического массива:

#include int main() < unsigned rows = 3; // количество строк unsigned columns = 2; // количество столбцов int** numbers>; // выделяем память под двухмерный массив for (unsigned i<>; i < rows; i++) < numbers[i] = new int[columns]<>; > // вводим данные для таблицы rows x columns for (unsigned i<>; i < rows; i++) < std::cout ; j < columns; j++) < std::cout > numbers[i][j]; > > // вывод данных for (unsigned i<>; i < rows; i++) < // выводим данные столбцов i-й строки for (unsigned j<>; j < columns; j++) < std::cout std::cout for (unsigned i<>; i < rows; i++) < delete[] numbers[i]; >delete[] numbers; >

Пример работы программы:

Enter data for 1 row 1 column: 2 2 column: 3 Enter data for 2 row 1 column: 4 2 column: 5 Enter data for 3 row 1 column: 6 2 column: 7 2 3 4 5 6 7

Указатель на массив

От типа int** , который представляет указатель на указатель (pointer-to-pointer) следует отличать ситуацию "указатель на массив" (pointer to array). Например:

#include int main() < unsigned n; // количество строк int (*a)[2] = new int[n][2]; int k<>; // устанавливаем значения for (unsigned i<>; i < n; i++) < // устанавливаем данные для столбцов i-й строки for (unsigned j<>; j < 2; j++) < a[i][j] = ++k; >> // вывод данных for (unsigned i<>; i < n; i++) < // выводим данные столбцов i-й строки for (unsigned j<>; j < 2; j++) < std::cout std::cout // удаляем данные delete[] a; a = nullptr; >

Здесь запись int (*a)[2] представляет указатель на массив из двух элементов типа int. Фактически мы можем работать с этим объектом как с двухмерным массивом (таблицей), только количество столбцов в данном случае фиксировано - 2. И память для такого массива выделяется один раз:

int (*a)[2] = new int[n][2];

То есть в данном случае мы имеем дело с таблице из n строк и 2 столцов. Используя два индекса (для строки и столца), можно обращаться к определенному элементу, установить или получить его значение. Консольный вывод данной программы:

1 2 3 4 5 6

Как считать динамический двумерный массив из файла СИ?

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

#include #include int main(int argc, char *argv[]) < if (argc == 1) < printf("No file names"); return 0; >int size; FILE *OpenFile; OpenFile = fopen(argv[1], "r"); if (!OpenFile) < printf("Failed to open the file"); return 0; >else < size = CountFile(OpenFile) >int СountFile(FILE *OpenFile) < int temp, counter = 0; while (fscanf(OpenFile, "%d", &temp) != EOF) < counter++; >return counter; >
  • Вопрос задан более трёх лет назад
  • 284 просмотра

1 комментарий

Простой 1 комментарий

Как считать динамический массив из файла с

Здравствуйте, я написал программу по работе с динамическим массивом. Программа выполняет следующие действия:
1. Открывает входящий файл.
2. Считает количество строчек в нём -> count.
3. Создает динамический массив, состоящий из count элементов.
4. Считывает данные из входящего файла и заполняет ими этот массив.
5. Печатает массив на экран.

#include "stdafx.h" #include "stdio.h" #include "iostream.h" int count=0; //Глобальный счётчик элементов во входящем файле void counter (FILE *f1) //Программа-счётчик количества элементов (строчек) в файле с исходными данными < cout cout int *fill_array (FILE *f1) //Программа заполнения динамического массива с чтением файла < cout int i; for(i=0;i cout void print_array (int* row) //Печатаем содержимое динамического массива < cout > int main(int argc, char* argv[]) < cout printf("\nFiles are being opened"); if((f1=fopen(argv[1], "r")) == NULL) //Открываем входящий поток - файл с исходным временным рядом < perror(argv[1]); return 1; >if((f2=fopen(argv[2], "w+")) == NULL) //Открываем выходящий поток для записи результатов < perror(argv[2]); return 1; >counter(f1); //Запустили счётчик записей, результат - в count int *row; //Инициализация динамического массива для дальнейшей работы row=fill_array (f1);//Динамический массив заполняется специальной функцией, открывающей файл с исходными данными print_array (row);//И выводится на экран return 0; >

Проблема в 5 пункте - она печатает не то, что было в исходном файле. Появляются какие-то одинаковые цифры. Может, она неправильно заполняет динамический массив данными из файла? Или неправильно его выводит на экран?

На вход подается текстовый файл:

10
13
23
4
76
12
-9
4
0
73
12

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *