Я пытаюсь создать эту небольшую базу данных студентов, используя связанные списки в C. По какой-то причине я получаю ошибку сегментации при втором запуске этой функции. У меня есть переключатель внутри цикла while, где я могу запускать различные функции, вводя число с клавиатуры. Итак, когда я запускаю программу, нажмите 1, чтобы запустить эту функцию ниже, все работает нормально. Но когда я пытаюсь запустить его во второй раз, не прерывая программу между ними, происходит сбой, и отладчик сообщает мне, что произошла ошибка сегментации. Я не могу понять, почему.
Это функция в моем скрипте.
int add_student(void){
current_student = student_head;
current_study = study_head;
if (current_study == NULL || current_study == NULL)
return 1;
while(current_student->next_student != NULL){
current_student = current_student->next_student;
}
current_student->next_student = (student*)malloc(sizeof(student));
printf("Enter the persons personal number.");
scanf("%d", ¤t_student->next_student->pernum);
printf("Enter the persons name");
scanf("%s", current_student->next_student->name);
printf("Male or female? Write 1 for male and 0 for female.");
scanf("%d", ¤t_student->next_student->is_male);
if (current_student->next_student->is_male == 0)
num_of_female++;
else
num_of_male++;
printf("Enter the persons age");
scanf("%d", ¤t_student->next_student->age);
printf("Enter the persons email");
scanf("%s", current_student->next_student->email);
while(current_study->next_study != NULL){
current_study = current_study->next_study;
}
current_study->next_study = (study*)malloc(sizeof(study));
current_study->next_study->pernum = current_student->next_student->pernum;
printf("Does this student study math? Asnwer 1 for yes or 0 for no."); // Field of study.
scanf("%d", ¤t_study->next_study->math);
printf("Does this student study english? Asnwer 1 for yes or 0 for no.");
scanf("%d", ¤t_study->next_study->english);
printf("Does this student study chemistry? Asnwer 1 for yes or 0 for no.");
scanf("%d", ¤t_study->next_study->chemistry);
printf("Does this student study biology? Asnwer 1 for yes or 0 for no.");
scanf("%d", ¤t_study->next_study->biology);
printf("Does this student study history? Asnwer 1 for yes or 0 for no.");
scanf("%d", ¤t_study->next_study->history);
num_of_stud++;
}
Я просто хочу, чтобы функция могла работать неограниченное количество раз без сбоев.
Когда я запускаю функцию в первый раз, current_student имеет ожидаемый адрес памяти, а current_student->next_student имеет значение NULL, как и ожидалось. Второй раз текущий студент имеет тот же адрес, а current_student->next_student имеет адрес, так что пока все работает?
Current_student, student head, current_study и Study_head объявлены как глобальные указатели.
Обновлено: вот объявления структур и указатели на выделенную память. Они находятся вне main на верхнем уровне вне любой функции:
typedef struct student{
int pernum;
char name[100];
int is_male;
int age;
char email[100];
struct student *next_student;
}student;
typedef struct study{
int pernum;
int math;
int english;
int chemistry;
int biology;
int history;
struct study *next_study;
}study;
int num_of_stud = 0;
int num_of_female = 0;
int num_of_male = 0;
student *current_student;
study *current_study;
student *student_head = NULL;
study *study_head = NULL;
Вам не хватает кода. Мы не знаем, какого типа ваши переменные, такие как current_student
.
Первое, что нужно сделать, это выяснить, какая строка кода, в частности, вызывает сбой. С помощью этой информации вы будете знать, какой разыменование указателя является виновником и, следовательно, какая переменная установлена неправильно, и вы можете вернуться оттуда к основной причине ошибки.
Так как функция всегда возвращает 1, потому что study_head
равно NULL. (Не нужно тестировать дважды: if (current_study == NULL || current_study == NULL)
)
У вас как минимум 7 глобальных переменных слишком много.
Вы никогда не должны приводить возвращаемое значение malloc
в программе C. Это блокирует важные сообщения об ошибках.
Не видя содержимого вашей основной функции и того, как вызывалась функция add_student, я взял немного художественной лицензии на рефакторинг некоторых функций, чтобы они чувствовали, когда добавляется первая структура студента или структура обучения, и действовали соответственно. обеспечить правильную начальную точку и последующую цепочку связанных списков. Ниже приведена версия вашей функции с некоторыми изменениями для определения начальной точки студента/учебы, а также основная функция, которая позволяет вводить непрерывное количество записей студентов и учебы. Это немного длинно, но я не мог понять, как сжать это дальше.
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
int pernum;
char name[100];
int is_male;
int age;
char email[100];
struct student *next_student;
} student;
typedef struct study
{
int pernum;
int math;
int english;
int chemistry;
int biology;
int history;
struct study *next_study;
} study;
int num_of_stud = 0;
int num_of_female = 0;
int num_of_male = 0;
student *current_student = NULL;
study *current_study = NULL;
student *student_head = NULL;
study *study_head = NULL;
int add_student(void)
{
int resp = 0; /* Added to provide a user controlled end to student and study data entry */
if (current_student == NULL) /* If this is the initial student set up the initial structure allocation */
{
current_student = malloc(sizeof(student));
student_head = current_student;
}
else /* Else, chase down the linked list to the last current student */
{
while(current_student->next_student != NULL)
{
current_student = current_student->next_student;
}
}
current_student->next_student = malloc(sizeof(student));
printf("Enter the person's personal number: ");
scanf("%d", ¤t_student->next_student->pernum);
printf("Enter the persons name: ");
scanf("%s", current_student->next_student->name);
printf("Male or female? Write 1 for male and 0 for female: ");
scanf("%d", ¤t_student->next_student->is_male);
if (current_student->next_student->is_male == 0)
num_of_female++;
else
num_of_male++;
printf("Enter the persons age ");
scanf("%d", ¤t_student->next_student->age);
printf("Enter the persons email ");
scanf("%s", current_student->next_student->email);
current_student->next_student->next_student = NULL; /* Make sure the last student element has its pointer properly initialized */
if (current_study == NULL) /* If this is the initial study element set up the initial structure allocation */
{
current_study = malloc(sizeof(study));
study_head = current_study;
}
else /* Else, chase down the linked list to the last current study element */
{
while(current_study->next_study != NULL)
{
current_study = current_study->next_study;
}
}
current_study->next_study = malloc(sizeof(study));
current_study->next_study->pernum = current_student->next_student->pernum;
printf("Does this student study math? Asnwer 1 for yes or 0 for no: "); // Field of study.
scanf("%d", ¤t_study->next_study->math);
printf("Does this student study english? Asnwer 1 for yes or 0 for no: ");
scanf("%d", ¤t_study->next_study->english);
printf("Does this student study chemistry? Asnwer 1 for yes or 0 for no: ");
scanf("%d", ¤t_study->next_study->chemistry);
printf("Does this student study biology? Asnwer 1 for yes or 0 for no: ");
scanf("%d", ¤t_study->next_study->biology);
printf("Does this student study history? Asnwer 1 for yes or 0 for no: ");
scanf("%d", ¤t_study->next_study->history);
current_study->next_study->next_study = NULL; /* Make sure the last study element has its pointer properly initialized */
num_of_stud++;
printf("More students 0/1 "); /* Send a response back to the main function to determine if further entry will occur */
scanf("%d", &resp);
if (resp == 0)
{
return -1;
}
return 0;
}
int main()
{
while (1) /* A test harness to allow a variable number of students to be entered */
{
if (add_student() == -1)
{
break;
}
}
current_student = student_head->next_student; /* This bit added just to verify what was entered */
printf("Student list\n-----------------------------------------\n");
while (1)
{
printf("Number: %d Name: %s\n", current_student->pernum, current_student->name);
if (current_student->next_student == NULL)
{
break;
}
current_student = current_student->next_student;
}
current_student = student_head->next_student;
printf("\nStudy list\n-----------------------------------------\n");
while (1)
{
printf("Person number: %d Math: %d English: %d Chemistry: %d Biology: %d History: %d\n", current_study->pernum, current_study->math, current_study->english, current_study->chemistry, current_study->biology, current_study->history);
if (current_study->next_study == NULL)
{
break;
}
current_study = current_study->next_study;
}
return 0;
}
Некоторые моменты, на которые следует обратить внимание.
Ниже приведен пример вывода терминала для двух записей студента/учебы; однако можно было бы ввести больше студентов и связанных с ними учебных структур.
@Vera:~/C_Programs/Console/StudentBody/bin/Release$ ./StudentBody
Enter the person's personal number: 22
Enter the persons name: Craig
Male or female? Write 1 for male and 0 for female: 1
Enter the persons age 18
Enter the persons email [email protected]
Does this student study math? Asnwer 1 for yes or 0 for no: 1
Does this student study english? Asnwer 1 for yes or 0 for no: 0
Does this student study chemistry? Asnwer 1 for yes or 0 for no: 0
Does this student study biology? Asnwer 1 for yes or 0 for no: 0
Does this student study history? Asnwer 1 for yes or 0 for no: 0
More students 0/1 1
Enter the person's personal number: 33
Enter the persons name: Lily
Male or female? Write 1 for male and 0 for female: 0
Enter the persons age 19
Enter the persons email [email protected]
Does this student study math? Asnwer 1 for yes or 0 for no: 0
Does this student study english? Asnwer 1 for yes or 0 for no: 1
Does this student study chemistry? Asnwer 1 for yes or 0 for no: 0
Does this student study biology? Asnwer 1 for yes or 0 for no: 0
Does this student study history? Asnwer 1 for yes or 0 for no: 0
More students 0/1 0
Student list
-----------------------------------------
Number: 22 Name: Craig
Number: 33 Name: Lily
Study list
-----------------------------------------
Person number: 22 Math: 1 English: 0 Chemistry: 0 Biology: 0 History: 0
Person number: 33 Math: 0 English: 1 Chemistry: 0 Biology: 0 History: 0
Кроме того, вы можете изучить возможность передачи вашей структуры или адреса структуры в качестве параметров функции вместо использования глобальных переменных, как указано в комментариях. Но для того, чтобы предоставить своевременный ответ с кодом как есть, я оставил ваши переменные как глобальные переменные.
Попробуйте и посмотрите, соответствует ли это духу вашего проекта.
Отредактируйте свой пост, чтобы оставить немного меньше воображению. Каковы ваши
struct
определения? Отредактируйте, чтобы создать минимальный воспроизводимый пример