Горячий конвертировать 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 тоже может быть в порядке. Но не оба. Можете ли вы придумать эти два варианта?


Ваша программа работает сейчас. В заключение: "уберись!" Удалите ненужные вещи, убедитесь, что код правильно вставлен и отформатирован, и добавьте цикл для печати массива, чтобы вы могли проверить и убедиться, что он работает правильно.

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

Другие вопросы по тегам