C malloc () со структурой совета - PullRequest
0 голосов
/ 04 февраля 2012

У меня две структуры, и у меня есть массив из 30 указателей StudentType. У меня проблема с malloc(). Когда я его компилирую, все в порядке. Но когда я пытаюсь его отладить, в Dev c ++ отображается «Ошибка сегментации».

В Eclipse он показывает что-нибудь на консоли. Я думаю, что мои ошибки заключаются в следующих строках кода:

students[0]=(StudentType *)malloc(sizeof(StudentType)*NumOfStudents);
(*students[NumOfStudents]).firstName=(char*)malloc(sizeof(char[30]));
(*students[NumOfStudents]).lastName=(char*)malloc(sizeof(char[30]));

Это часть моего кода.

#include <stdio.h>
#include <stdlib.h>

typedef struct{
    float firstAssignment;
    float secondAssignment;
    float midterm;
    float final;
    float finalMark;
}StudentRecordType;

typedef struct{
    char *firstName;
    char *lastName;
    int idNumber;
    StudentRecordType marks;
}StudentType;
StudentType *students[30];
char firstName[30];
char lastName[30];

int ReadFromFile();
int PrintAll();
int NumOfStudents;
int i;

int main(void)
{
    ReadFromFile();
}

int ReadFromFile()
{
    FILE *fp;
    fp=fopen("project2-askhsh2.dat","r");
    if(fp==NULL)
    {
        printf("Error opening file.\n");
    }
    else
    {
        printf("Successful open of project2-askhsh2.dat\n");
    }
    fscanf(fp,"%d",&NumOfStudents);
    printf("%d\n",NumOfStudents);
    students[0]=(StudentType *)malloc(sizeof(StudentType)*NumOfStudents);
    (*students[NumOfStudents]).firstName=(char*)malloc(sizeof(char[30]));
    (*students[NumOfStudents]).lastName=(char*)malloc(sizeof(char[30]));

    for(i=0;i<NumOfStudents;i++)
    {
        (*students[i]).idNumber=i;
        fscanf(fp,"%s %s", (*students[i]).firstName,(*students[i]).lastName);
        fscanf(fp,"%f %f %f %f",(*students[i]).marks.firstAssignment,(*students[i]).marks.secondAssignment,(*students[i]).marks.midterm,(*students[i]).marks.final);
        printf("%s",(*students[i]).firstName);//, students[i].lastName);
    }

}

Ответы [ 4 ]

3 голосов
/ 04 февраля 2012

(*students[NumOfStudents]).firstName=(char)malloc(sizeof(char[30]));

Во-первых, актеры просто ошибочны. Приведение к char теряет информацию.
Во-вторых, в C не приводите возвращаемое значение из malloc(). В лучшем случае это избыточно и может скрывать ошибку, которую компилятор мог бы обнаружить без преобразования.

Если вы все равно собираетесь разыграть, приведите к char*.

2 голосов
/ 04 февраля 2012

Похоже, что при использовании указателя students у вас есть дополнительный уровень указателей, который вам не нужен, чтобы вызывать некоторую путаницу. Вы также получаете доступ за концом выделенного массива.

Так что вместо

StudentType *students[30];

Что дает вам массив из 30 указателей на StudentType. Я думаю, вы, вероятно, просто хотели:

StudentType *students;

Это простой указатель на StudentType, который можно использовать как основу для динамически размещаемого массива. Затем, когда вы делаете распределение, вы делаете это:

students = malloc(sizeof(*students) * NumOfStudents);

И вам придется инициализировать каждый из этих StudentTypes, прежде чем использовать их.

for(i=0;i<NumOfStudents;i++)
{
    students[i].firstname = malloc(30);
    students[i].lastname = malloc(30);
}

Обратите внимание, что каждый StudentType теперь доступен напрямую как элемент из массива студентов как student[i], а не как *students[i], который у вас был неправильный. Вы можете расширить это до остальной части вашего кода. Помните, что вы можете получить доступ только из индекса 0 к NumOfStudents-1, поэтому не используйте студентов [NumOfStudents].

Другая проблема, с которой вы столкнетесь, заключается в том, что когда вы используете fscanf (), вам нужно передать адрес переменной, чтобы сохранить результат при использовании оператора амперсанда. В настоящее время вы только передаете значение, например, вы должны использовать &students[i].marks.firstAssignment вместо (*students[i]).marks.firstAssignment, при условии, что вы также исправите ошибки указателя.

1 голос
/ 04 февраля 2012

Эти два оператора неверны:

(*students[NumOfStudents]).firstName=(char*)malloc(sizeof(char[30]));
(*students[NumOfStudents]).lastName=(char*)malloc(sizeof(char[30]));

C-массивы индексируются нулем, и поэтому вы пытаетесь разыменовать единицу после размера массива.Предполагая, что вы хотите установить имя и фамилию последнего элемента students[], вам нужно разыменовать индекс NumOfStudents - 1.

. Вам не нужно приводить результат malloc() кchar * (при условии, что вы пишете приложение на C).

sizeof(char) равно 1, поэтому вам просто нужно написать malloc(30).

0 голосов
/ 04 февраля 2012
(*students[NumOfStudents]).firstName=(char*)malloc(sizeof(char[30]));

Я думаю, вы имели в виду:

students[some_index]->firstName = malloc(30);

С some_index что-то ниже NumOfStudents.

Таким образом, ваш цикл становится:

for(i=0; i < NumOfStudents ; i++)
    {
        /* students[] is an array of pointers
        ** students[i] is a pointer
        */
        students[ i ] = malloc(sizeof *students[ i ]);
        students[ i ]->idNumber=i;

        students[ i ]->firstName = malloc(30);
        students[ i ]->lastName= malloc(30);

        fscanf(fp,"%s %s"
            , students[i]->firstName
            , students[i]->lastName
            );
        fscanf(fp,"%f %f %f %f"
            , &students[i]->marks.firstAssignment
            , &students[i]->marks.secondAssignment
            , &students[i]->marks.midterm
            , &students[i]->marks.final
            );
        printf("%s",students[i]->firstName);//, students[i].lastName);
    }

И используя глобальный индекс с именем "i" можно считать плохим стилем.

...