Горячий конвертировать TXT файл в массив структурных ошибок сегментации? - PullRequest
0 голосов
/ 13 октября 2018

Попытка извлечь данные из текстового файла и поместить эти данные в массив.

Файл содержит определенное количество строк, каждая из которых соответствует одинаковому расположению:

Number FamilyName FirstName GPA

Необходимый массив представляет собой массив struct.

#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 Ответ

0 голосов
/ 13 октября 2018

Я вижу, вы сейчас выделите память для вашего массива.Хорошо.

Теперь о 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 раз (поскольку у вас не больше людей), и этот цикл останавливается тамбольше нет данных.

A для цикла может быть в порядке;цикл while тоже может быть в порядке.Но не оба.Можете ли вы придумать эти два варианта?


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

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

...