#c #loops #struct
#c #циклы #структура
Вопрос:
Я пишу простую программу на c, чтобы лучше понимать язык, но у меня странная проблема. Как вы видите из приведенного ниже кода, у меня есть только один цикл, который завершается, когда я вставляю 255 в качестве значения. Проблема в том, что когда я выбираю первый (вариант вставки) и после того, как я вставляю имя, программа запускает что-то вроде цикла и постоянно выдает мне экран выбора…
#include<stdio.h>
#include<stdlib.h>
struct student{
char *name;
int id;
};
void insertStudent(void);
struct student * init(void);
int main(){
struct student *p;
int selectionCode=0;
while(selectionCode!=255){
printf("nInsert students:1");
printf("nDisplay students:2");
printf("nExit:255");
printf("nnEnter selection:");
scanf("%d",amp;selectionCode);
p=init();
switch(selectionCode){
case 1:
insertStudent();
//printf("1n");
break;
case 2:
//printf("2n");
break;
case 255:
break;
}
}
//p->name="stelios";
//p->id=0;
//printf("Name:%s ID:%d",p->name,p->id);
//free(p);
//p=NULL;
return 0;
}
struct student *init(void)
{
struct student *p;
p=(struct student *)malloc(sizeof(struct student));
return p;
}
void insertStudent(void){
struct student *p;
p=init();
printf("Enter Name:");
scanf("%s",p->name);//return 1;
printf("Enter ID:");
scanf("%d",amp;p->id);
//printf("test");
}
Комментарии:
1. Да, это будет. Но вы же не хотите каждый раз получать экран выбора?
2. @Doug T.Нет, это не домашнее задание. Я знаю Java, и теперь я изучаю c…
Ответ №1:
Частично проблема может заключаться в том, что код не выделяет память для name
поля в структуре. init
Функция выделяет новую структуру, но не инициализирует name
поле. Затем insertStudent
функция использует scanf
для чтения этот неинициализированный указатель. Это приводит к записи в «случайную» память и может привести к любому количеству проблем, включая нарушение доступа.
Комментарии:
1. вы были правы, я изменил указатель на массив (name[30]), и это сработало. Но как я мог бы выделить память внутри структуры, если я хочу использовать указатель?
2. @Stelios: Чтобы использовать указатель, вам нужно было бы выполнить второй вызов malloc после выделения самой структуры.
p->name = malloc(30);
. Если вы придерживаетесь фиксированного размера, вероятно, проще / лучше использовать массив (name[30]). Однако, если позже вы захотите изменить размер, то лучше всего использовать malloc (затем можно снова освободить и malloc или использовать realloc).
Ответ №2:
Похоже, у вас утечка памяти, я бы передал p в insertStudent().
У вас также есть return 1;
в середине вызова insertStudent (), поэтому он будет возвращаться до завершения своей работы.
Ответ №3:
У вас есть «return 1;» после сканирования в имени. Похоже, что логически вы не должны возвращаться в этот момент, поскольку вы хотите ввести идентификатор. Кроме того, вы объявили функцию как возвращающую «void», поэтому возврат единицы является ошибкой.
Редактировать: Реальная проблема в том, что вы никогда не выделяли место для строки имени.
Ответ №4:
попытайтесь:
struct student *insertStudent(void){
struct student *p;
p=init();
printf("Enter Name:");
scanf("%s",p->name);
printf("Enter ID:");
scanf("%d",amp;p->id);
//printf("test");
return p;
}
На главном
case 1:
free(p);
p=insertStudent();
//printf("1n");
При инициализации вы должны выделить место для имени.
Комментарии:
1. Я принимаю ошибку сегментации, возможно, потому, что p не инициализирован. Даже если инициализировать, это тоже цикл..
2. в функции init как вы выделяете память для имени?
Ответ №5:
Какой беспорядок… 🙂 Вы никогда не вводите в malloc() буфер для p-> name, но вы заполняете if с помощью scanf(). Это приводит к повреждению памяти вашей программы. Кроме того… В ваших функциях вы используете переменную p, а также в вашей основной программе. Это НЕ та же переменная, но вы, кажется, предполагаете, что это так. Другая проблема: возвращает 1; после того, как scanf () прерывает функцию insertStudent(), поэтому «введите идентификатор» никогда не выполняется. Кстати, это функция void, поэтому она не должна возвращать значение. Вероятно, компилятор выдал предупреждение об этом.
Вероятно, в этом есть еще что-то неправильное, но это то, что я замечаю после краткого ознакомления с ним.
Ответ №6:
Вам нужно удалить «return 1;» из insertStudent, иначе is не будет компилироваться.
Вы должны инициализировать p-> name с помощью malloc и изменить «scanf(«%s»,p->name);» на «scanf(«%s», amp;p->name);», потому что вам нужен указатель на *char .
Комментарии:
1. Вы правы насчет возврата, просто я забыл это прокомментировать. amp;p-> Имя неверно, потому что, если я хочу использовать amp;, у меня должна быть эта форма amp; * p-> имя. Я запустил это на всякий случай, и я был прав.