Перейти к содержимому

Как считать массив из файла c

  • автор:

Как считать массив из файла c

Регистрация: 16.12.2009

Сообщений: 3

Как считать массив из файла?

Обьясните пожалуйста на примере, как из текстового файла с числовыми данными, введенных например через пробел, считать данные и вести их на экран в виде двухмерного массива?(На языке СИ)

Последний раз редактировалось Ronin021992; 16.12.2009 в 19:30 .

Ronin021992
Посмотреть профиль
Найти ещё сообщения от Ronin021992

Форумчанин

Регистрация: 16.02.2009

Сообщений: 555

#include #include using namespace std; int main() < int const n=4; int i=0; int j=0; int a[n][n]; ifstream f("1.txt"); while(!f.eof()) < if(j==n) < i++; j=0; coutf>>a[i][j]; cout system("pause"); >

Как считать массив из файла?

Программа должна считывать массив из файла и искать в нём минимальный элемент, но что-то не получается нормально считать сам массив. В чем проблема?

#include "stdafx.h" #include #include "fstream" using namespace std; void main() < ifstream in("input.txt"); int array[5]; in >> array[5]; int min = array[0]; for (int i = 1; i < 5; i++) < if (array[i] < min) < min = array[i]; >> ofstream out("output.txt"); out

введите сюда описание изображения

Файл input.txt

Отслеживать

задан 15 окт 2017 в 6:58

119 1 1 золотой знак 3 3 серебряных знака 10 10 бронзовых знаков

Читать надо поэлементно в цикле, и разделители по умолчанию — символы пробельной группы (запятая в них не входит). Ну, и еще в коде выход за пределы массива. Индексы начинаются с 0, т.е. элемента array[5] не существует.

15 окт 2017 в 7:48

@alexolut , я, вроде как, array[5] и не использую, тк в цикле i строго меньше 5

Как считать массив из файла в си?

Nipheris

1. Ты читаешь всё подряд как числа, а в файле у тебя есть нецифровые символы
2. Ты прочитанное сразу печатаешь обратно в файл.

Если хочешь использовать fscanf, то можно, например, так:

char c; for (int i = 0; i < n; i++) < for (int j = 0; j < m; j++) < fscanf(f, "%d", &pole[i][j]); fscanf(f, "%c", &c); printf("%d ",pole[i][j]); >printf("\n"); >

Только сначала отформатировать файл, чтобы числа через запятую шли и без остального мусора.

Как реализовать считывание строк из файла в массив строк?

По ходу дела, я очень плохо понял тему указателей и работы с памятью, и теперь вот никак не могу сделать, казалось бы простейшую вещь.
Есть текстовый файл со словами, записанными по одному слову в строчку. Нужно считать каждую строку в массив arr[]. Пробовал и fscanf и fgetsе — не получается 🙁
Подскажите, что я не так делаю, и как правильно?

#include #define SIZE 45 int main() < char *text = "example"; FILE *fp = fopen(text, "r"); if (fp == NULL) < printf("Could not open %s.\n", text); return 1; >//char word[SIZE+1]; char *arr[26]; int k=0; while(!feof(fp)) < fscanf(fp,"%s",arr[k]); //fgets(word, SIZE, fp); //arr[k]=word; k++; >for(int i=0; i%s\n", i+1, arr[i]); > return 0; >
abc bcd cde def zet
  • Вопрос задан более трёх лет назад
  • 14438 просмотров

Комментировать
Решения вопроса 1
Developer, ex-admin

На сколько я понял вы пытаетесь прочитать строку из файла и сохранить ее как элемент массива arr.
Но делаете это не правильно.
Ваша ошибка в том, что fscanf/fgets не выделяет память для хранения строки, она использует тот буфер, который вы ей предоставите. Но вы ничего не предоставляете.
Вам нужно для каждого элемента arr выделить память под строку:
arr[i] = (char*)malloc(sizeof(char) * BUFLEN);
где BUFLEN — некоторая целочисленная константа, обозначающая максимальную длину строки.
Тогда чтение из файла, как реализовано у вас пройдет.
В конце память выделенную с помощью malloc нужно освободить с помощью вызова free для каждого элемента массива arr.
И не забывайте обрабатывать ошибки выделения памяти и возвраты файловых операций.
fscanf со спецификатором формата «%s» считывает не строку, а слово — в строке может быть много слов. Для чтения строки используйте fgets, либо читайте посимвольно fgetc.
Когда заработает, потренируйтесь на файле, содержащем строку из более чем BUFLEN символов и попытайтесь найти корректный выход из этой ситуации.

Ответ написан более трёх лет назад
Нравится 2 8 комментариев
romajke @romajke Автор вопроса

Спасибо за ответ!
Функция fscanf мне вполне подходит, т.к. в моих исходных данных все строки состоят из одного слова. С выделением памяти, я кажется разобрался. В цикле, перед тем как использовать fscanf я выделяю память для элемента массива.

while(!feof(fp)) < arr[k] = (char*)malloc(sizeof(char) * SIZE); fscanf(fp,"%s",arr[k]); k++; >fclose(fp);

Но с высвобождением — не уверен что делаю верно. Правильно ли высвобождается память в этом цикле?

for(int i=0; i

В итоге программа работает, но не совсем корректно. Я вывожу на экран не пустые ячейки массива с помощью цикла:

for(int i=0; i%s\n", i+1, arr[i]); >

И получаю результат:

1 ->abc 2 ->bcd 3 ->cde 4 ->def 5 ->zet 6 -> 7 -> 8 -> Segmentation fault

Откуда берутся лишние три строки, и ошибка сегментации?

romajke, Проверка
if (arr[i])
в вашем случае не срабатывает.
Потому что, чтоб в arr[i] были нули (т.е. условие ложно) их нужно туда присвоить, а у вас этого нет.
Перед чтением из файла, присвойте всем значениям arr нули.
Потом, когда будете выделять память для строк значащие элементы примут значения !=0, а пустые строки так и останутся нулями и условие отработает как надо.

romajke @romajke Автор вопроса

Все верно, это помогло. Спасибо!
Код работает корректно.
А что с памятью? Верно ли я ее высвобождаю циклом

for(int i=0; i

Или нужно как то по другому?

romajke, Раз уж вы выделяете память не для всех элементов массива, то и освобождать нужно только их: добавьте перед free условие:
if(arr[i])

romajke @romajke Автор вопроса

res2001, да. Это понятно, теперь код полностью корректно работает. Но не совсем понятна работа fscanf в данном контексте. Если я, например, не сразу считываю в элемент массива arr[], а предварительно записываю данные в созданную переменную типа char word[SIZE]:

char word[SIZE] while(!feof(fp))

то код уже работает не корректно.
Все элементы массива заполняются последней считанной строкой:

1 ->zet 2 ->zet 3 ->zet 4 ->zet 26 ->zet *** Error in `./tes': double free or corruption (out): 0x00007fffeebbd000 *** Aborted

Если я правильно понимаю, то элементы массива получают ссылку на word, и получают значение которое хранится по адресу переменной word. Но как это изменить - не пойму. Как передать в элемент массива именно значение word?

romajke @romajke Автор вопроса

Проблему решил, с помощью использования strcpy, но понимание не пришло 🙁
Буду очень благодарен, если объясните.

romajke, Операция
arr[k]=word;
Не приводит к копированию строки из одного буфера в другой - этим вы сохраняете адрес буфера word в массив. Поэтому у вас все элементы массива будут ссылаться на один и тот же буфер. Кроме того, что при этом вы получаете не правильный результат, у вас еще образуется утечка памяти, т.к. указатели, на выделенную с помощью malloc память, потеряны и во free вы передаете указатель на word, что при этом освобождается . не известно и поведение не предсказуемо.
Вы правильно решили проблему, явно копируя строку с помощью strcpy. Аналогично нужно делать и с любыми другими массивами только использовать функцию memcpy (с помощью memcpy можно копировать и строки то же, она в этом плане универсальнее чем strcpy).
Ну и на последок - в Си как таковых строк нет, строка - это массив байт, оканчивающийся байтом со значением 0 (нулевой байт то же является частью массива/строки), поэтому и думать нужно о них как о массивах. Различие в том, что под строкой вы понимаете какую-то самостоятельную единую сущность, а это не так - это набор сущностей (байт).

dio4

Вам не нужно сразу разбираться с памятью - зачем?

/* читаем из файла требуемое кол. строк ROWS или до конца файла EOF (что наступит раньше), формируем строку по конечному символу '\n', в файле, добавляем завершающий '\0' и полученную строку СИ записываем в двумерный массив по 1-й строке в каждый элемент массива. Затем массив выводим на консоль. Есть подсчет считанных строк. */ #include #include /* prototype exit() */ #include #define ROWS 7 #define COLS 20 void file_open(void); FILE * file_in; //FILE* file_out; char ch, arr_str[ROWS][COLS]; int j, i, count = 0; int main(int agrc, char * argv[]) < file_open(); //ch=getc(file_in); for(j = 0; j < ROWS; ++j)< for(i = 0; (ch=getc(file_in)) != '\n' && (ch != EOF); ++i) < arr_str[j][i] = ch; // заполнение строки >//конец внутреннего for if(ch == EOF) < puts("достигнут конец файла, выход."); //arr_str[j][i] = '\0'; fprintf(stdout, "count is: %i \n", count); break; >// конец if else < arr_str[j][i] = '\0'; ++count; >// конец else > // конец внешнего for fclose(file_in); //fclose(file_out); /* вывод массива на консоль */ fprintf(stdout, "Из файла считано %i строк, которые имеют вид:\n", count); puts(""); // пропуск строки for(j = 0; j < count; ++j)< fprintf(stdout, "%s\n", arr_str[j]); >puts(""); // пропуск строки puts("Программа завершена."); exit(EXIT_SUCCESS); > void file_open(void) < if( (file_in = fopen("file_in", "r")) == NULL)< fprintf(stdout, "%s\n", "не могу отрыть файл для чтения"); exit(EXIT_FAILURE); >/* if( (file_out = fopen("file_out", "w")) == NULL) < fprintf(stdout, "%s\n", "не могу отрыть файл для записи"); exit(EXIT_FAILURE); >*/ > /* Из файла считано 7 строк, которые имеют вид: I am a human 1 I am a 2 human`s 2 I am a 3 human 3 Nmjh## ___ 987 ht! 5555555555555555 66666666666666 77777777777777 Программа завершена. */

Ответы на вопрос 4

Используйте двумерный массив для строк:
char arr[26][SIZE];

И добавьте fclose(fp) после цикла while<. >.

Ответ написан более трёх лет назад
Нравится 1 3 комментария
romajke @romajke Автор вопроса
Все равно получается ошибка сегментации
romajke, а какая максимальная длинна строки в файле?
romajke @romajke Автор вопроса
Входные данные:

abc bcd cde def zet

sergio_nsk @sergio_nsk
fscanf замени на

size_t alloced = 0; getline(&arr[k], &alloced, fp);

getline с сравнением с -1 можно поместить в while.

Ответ написан более трёх лет назад
romajke @romajke Автор вопроса
getline это разве не C++?
sergio_nsk @sergio_nsk
getline - это не C++. Тебя разве забанили в Гугле?
romajke @romajke Автор вопроса
sergio_nsk @sergio_nsk
romajke, это расширение GNU.

dio4

team leader, system engineer, master of sports

/* читаем из файла требуемое кол. строк ROWS или до конца файла EOF * (что наступит раньше), формируем строку по конечному символу '\n' * в файле, затем добавляем завершающий '\0' и полученную строку СИ * записываем * в двумерный массив по 1-й строке в каждый элемент массива. * Затем массив выводим на консоль. Есть подсчет считанных строк. * См также ниже мой коммент */ /* file_in находится в каталоге программы и имеет вид: I am a human 1 I am a 2 human`s 2 I am a 3 human 3 Nmjh## ___ 987 ht! 5555555555555555 66666666666666 77777777777777 8888888888888888 */ #include #include /* prototype exit() */ #include #define ROWS 7 #define COLS 20 void file_open(void); FILE * file_in; char ch, arr_str[ROWS][COLS]; int j, i, count = 0; int main(int agrc, char * argv[]) < file_open(); for(j = 0; j < ROWS; ++j)< for(i = 0; (ch=getc(file_in)) != '\n' && (ch != EOF); ++i) < arr_str[j][i] = ch; // заполнение строки >//конец внутреннего for if(ch == EOF) < puts("достигнут конец файла, выход."); fprintf(stdout, "count is: %i \n", count); break; >// конец if else < arr_str[j][i] = '\0'; ++count; >// конец else > // конец внешнего for fclose(file_in); /* вывод массива на консоль */ fprintf(stdout, "Из файла считано %i строк, которые имеют вид:\n", count); puts(""); // пропуск строки for(j = 0; j < count; ++j)< fprintf(stdout, "%s\n", arr_str[j]); >puts(""); // пропуск строки puts("Программа завершена."); exit(EXIT_SUCCESS); > void file_open(void) < if( (file_in = fopen("file_in", "r")) == NULL)< fprintf(stdout, "%s\n", "не могу отрыть файл для чтения"); exit(EXIT_FAILURE); >> /* Вывод на консоль: Из файла считано 7 строк, которые имеют вид: I am a human 1 I am a 2 human`s 2 I am a 3 human 3 Nmjh## ___ 987 ht! 5555555555555555 66666666666666 77777777777777 Программа завершена. */

Ответ написан более трёх лет назад

dio4

посимвольная работа со строками имеет более жесткий контроль над процессом. Обратите внимание, что строк в файле больше, чем мы считали. Это задается #define ROWS 7 если задать к примеру 10, то получим:

достигнут конец файла, выход.
count is: 9
Из файла считано 9 строк, которые имеют вид:

I am a human 1
I am a 2 human`s 2
I am a 3 human 3
Nmjh## ___ 987 ht!
5555555555555555
66666666666666
77777777777777
8888888888888888

сообщение о конце файла (EOF тоже отлавливается). И в строке arr_str[j][i] = '\0'; формируется окончательно строка "си" завершающим символом '\0', что тоже важно. Можно использовать динамический массив или массив переменной длины(пропадает нужда следить и использовать free() , но придется точно знать количество строк в файле (высчитывать заранее). Также, при желании для уменьшения времени компиляции можно переписать программку в нотации указателей (компилятор все равно это будет делать сам) и вместо функций использовать указатели на них 🙂 .

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

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