Горячий конвертировать TXT файл в массив структурных ошибок сегментации?
Попытка извлечь данные из текстового файла и поместить эти данные в массив.
Файл содержит определенное количество строк, каждая из которых имеет одинаковое расположение:
Number FamilyName FirstName GPA
Необходимый массив является массивом структуры.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 25
typedef struct ppl {
int login;
char *p_name;
char *p_surname;
}person;
int main(void)
{
char *line = NULL;
person *data=malloc(MAX*sizeof(person));
float *gpa=malloc(MAX*sizeof(float));
size_t length=0;
FILE* txtfile;
if ((txtfile=fopen("file.txt","r"))==NULL) return -1;
int i=0; // the counter for the for loop
int buf_ID; // buffer variable for the sscanf test
char buf_name[256]; // same
char buf_surname[256]; // same
float buf_grade; // same
while ((read = getline(&line, &length,txtfile)) != -1 && i<MAX)
{
if(sscanf(line,"%d %s %s%*s %f", &buf_ID, buf_name, buf_surname, &buf_grade)==4)
{
data[i].login=buf_ID;
data[i].p_name= malloc(strlen(buf_name)+1);
strcpy(data[i].p_name, buf_name);
data[i].p_surname= malloc(strlen(buf_surname)+1);
strcpy(data[i].p_surname, buf_surname);
gpa[i]=buf_grade;
i++;
}
}
int j;
printf("ID | Name | Surname | GPA\n");
for(j=0;j<i;j++)
{
printf("%d | %s | %s | %f\n", data[j].login, data[j].p_name, data[j].p_surname, gpa[j]);
}
fclose(txtfile);
return 0;
}
(Часто редактируемый код - я заполняю бесполезным текстом, потому что иначе публикация не публикуется)
1 ответ
Я вижу, что вы сейчас распределили память для вашего массива. Хорошо.
Теперь о char *
буферы buf_name
и т.д. Может быть лучше сделать статическое распределение здесь, например
char buf_name[256];
Вы собираетесь повторно использовать этот буфер, поэтому статическое распределение в порядке.
Следующий шаг:
Найдите функцию getline: http://man7.org/linux/man-pages/man3/getline.3.html и проверьте правильность всех параметров.
Теперь возьмите ваш отладчик и перейдите к sscanf
, Перешагните через него и проверьте, правильно ли прочитаны переменные sscanf
(использование отладчика является важной частью обучения C).
Следующая вещь - спросить себя, есть ли у вашей группы людей вся необходимая память. Если нет, как вы собираетесь распределять эту память?
Вы выделили множество людей, использующих malloc. У каждого человека есть некоторые данные, связанные с ним. Данные состоят из примитивных типов и составных типов. Примитивный тип - это int, float, double и char. Составной тип состоит из ряда из них. Строка является составным типом, потому что она состоит из более чем одного символа.
Таким образом, ваши персоны в массиве имеют строковые данные, связанные с ними, как указатели, но указатели не имеют связанной с ними памяти. Вам необходимо выделить память для хранения строковых данных. Ваши данные->p_name=malloc(MAX*100);`неверен.
С каждым человеком, которого вы читаете, вы должны выделить строковую память для хранения строковых данных, которые sscanf
положить в буферы фиксированного размера:
data[i].p_name= malloc(strlen(buf_name)+1);
strcpy(data[i].p_name, buf_name);
и то же самое для других строковых данных. (Вы делаете это в цикле, конечно!)
Примечание: для примитивного типа данные распределяются компилятором; для составного типа вы должны выделить память.
Nb: строка в C заканчивается нулевым символом. Для этого требуется больше памяти, чем длина строки.
Что это за секунда
sscanf
делать там в вашей петле???
Наконец, скопируйте идентификатор:
data[i].login= buf_id;
Обратите внимание, что вы не храните оценку в человеке и gpa
не выделена память (так что вы можете снова получить ошибку сегмента).
Ваша программа будет работать без ошибки сегмента. Но ваши циклы неверны:
У вас есть цикл for, который повторяется ровно 25 раз; внутри цикла у вас есть цикл while, который читает данные и помещает их в людей. Но индекс лиц обновляется только в цикле for, а не в цикле while. После прочтения последней строки данных цикл while останавливается и начинается следующая итерация цикла for. Однако данных больше нет.
Таким образом, вам нужен другой тип цикла, который повторяется не более 25 раз (так как у вас не больше людей, чем этот) и на остановках больше нет данных.
Цикл for может быть хорошо; цикл while тоже может быть в порядке. Но не оба. Можете ли вы придумать эти два варианта?
Ваша программа работает сейчас. В заключение: "уберись!" Удалите ненужные вещи, убедитесь, что код правильно вставлен и отформатирован, и добавьте цикл для печати массива, чтобы вы могли проверить и убедиться, что он работает правильно.
Я надеюсь, что вы получили удовольствие от разработки этой программы.