Как читать в файле, а затем поместить каждую структуру в файле в массив? - PullRequest
0 голосов
/ 10 мая 2019

Мне нужно прочитать файл, а затем присвоить каждому количеству символов размера структуры часть массива структуры.

Итак, первые тридцать символов будут первыми, вторые тридцать символов будут последними, а 9 символов после этого будут ssn.Это будет первый студент в массиве.Второй ученик начинается после 69-го персонажа, третий ученик начинается после 138-го персонажа и так далее.

В файле будет что-то вроде: john \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0smith \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0123456789jack \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0myers \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0987654321

Что будет конвертировать в:

allStudents [0] .first = john

allStudents [0] .last = smith

allStudents [0] .ssn = 123456789

allStudents [1] .first = jack

allStudents [1] .last = myers

allStudents [1] .ssn = 987654321

Вот текущая настройка:

struct student allStudents[1000];

struct student {
    char first[30];
    char last[30];
    char ssn[9];
};

void findStudents() {
    int i;
    FILE *fp;
    char *temp;
    int counter = 0;
    int counter2 = 0;
    fp = fopen("students.db","rt");

    while( ( temp[counter2] = fgetc(fp) ) != EOF )
    {
        for (i = 0 ; i < 30 ; i++) {
            strcat(allStudents[counter].first, temp);
            counter2++;
        }

        for (i = 0 ; i < 30 ; i++) {
            strcat(allStudents[counter].last, temp);
            counter2++;
        }

        for (i = 0 ; i < 9 ; i++) {
            strcat(allStudents[counter].ssn, temp);
            counter2++;
        }

        counter++;
    }

    fclose(fp);
}

1 Ответ

1 голос
/ 10 мая 2019

Как уже упоминалось в комментариях, существует множество проблем: от не выделения памяти для char *temp до использования массива char длиной 9 для хранения длинного числа из 9 символов, не оставляя места для завершающего символа.

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

Еще одна вещь, на которую я хотел бы обратить внимание, это ваш массив struct student allStudents[1000]. Вы немедленно выделяете 1000 * sizeof(struct) байт, даже если в вашей базе данных есть только 2 записи. Возможно, лучшим подходом будет использование связанного списка. Или просто наличие массива указателей структуры (struct student *allStudents[1000]), который изначально занимал бы намного меньше памяти, но вам пришлось бы выделять память для каждой новой структуры.

Я предполагаю, что вам не разрешено изменять файл students.db, но нам все еще нужно добавить этот завершающий символ, поэтому в файле будет 69 байт для отдельной записи и 70 байт в структуре. Если вам разрешено, я предлагаю вам изменить его.

struct student {
    // max allowed first and last name length should be 29 to ensure a space for terminating character
    char first[30];
    char last[30];
    char ssn[10];
}

struct student allStudents[1000];

void findStudents() {
    int counter = 0;

    // if you want to just read the file use "r" mode, if you're writing in it you can use "r+" or "w+", but there is no "rt" as far as I know
    FILE *fp = fopen("students.db", "r");

    // you should always check if file is opened
    if(fp == NULL) {
        printf("File not opened");
        return;
    }

    // allocate memory where you will store a single record read from a file
    // note -1 since your struct is now 70bytes large and a record in file is 69
    // and for that reason we are using calloc instead of malloc, since calloc fills allocated memory with zero
    char *temp = (char*) calloc(1, sizeof(struct student) - 1);

    // instead of using fgetc for reading a single character, it's better to use fread here
    // fread returns number of elements successfully read which should be 69 if everything is alright
    while( ( fread(temp, 1, sizeof(struct student) - 1, fp) ) == sizeof(struct student) - 1 ) {
        // copy the content we read into the structure
        // we copy only 69 bytes here, leaving the last byte of structure untouched
        // and it will be 0x00 (terminating character for your ssn)
        memcpy(&allStudents[counter], temp, sizeof(struct student) - 1);
        counter++;
    }

    // free the allocated memory and close the file since you won't be using them anymore
    free(temp);
    fclose(fp);
}

Я бы также предложил вам вернуть количество прочитанных записей из вашей базы данных student.db.

Я написал этот код в предположении, что вы не можете изменить файловую структуру student.db, но если вам разрешено, пожалуйста, рассмотрите упомянутые предложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...