首先,对不起我的英语。
对于一个项目,我必须制作一个车库管理程序。这是一个链接的力学列表。我现在做了一个功能:一个用于在此列表中添加机制(addMec),另一个用于删除机制(remMec)。
这是addMec函数:
void addMec(mechanics* first)
{
mechanics *new = malloc(sizeof(mechanic));
int speciality();
if(first==NULL)
{
return(0);
} else
{
printf("Add mechanic : \n");
// Ask for needed informations.
printf("Employee-Number : ");
scanf("%5d",&new->number);
printf("\nName : ");
scanf("%s",&new->name);
printf("\nFirst Name : ");
scanf("%s",&new->first_name);
new->speciality = speciality();
// Add to end -> new->next = NULL
new->next = NULL;
printf("%d %s %s %d\n",new->number,
new->name, new->first_name, new->speciality);
mechanics *current = first;
while(current->next!=NULL)
{
current = current->next;
}
current->next = new;
}
}
此功能不会在列表中添加任何内容。如果我尝试调试程序,我会收到一条SIGSEGV消息。
功能remMec
int remMec(mechanics* first)
{
int numrem, ret = 0;
mechanics *current, *intercale;
printf("Supprimer l'employe numero : ");
scanf("%5d",&numrem);
// On parcoure la liste à la recherche du numero d'employe.
current = first;
while(current->next != NULL)
{
// Nécéssaire si l'élément à supprimer est le premier de la liste.
if(current->number == first->number)
{
if(current->number == numrem && current != NULL)
{
intercale = first;
first = first->next;
free(intercale);
ret = 1;
}
}
if(current->number == numrem)
{
intercale = current->next;
current->next = intercale->next;
free(intercale);
ret = 1;
}
current = current->next;
}
if(ret)
{
return 1;
} else
{
return 0;
}
}
此函数的问题在于它删除了搜索元素的下一个元素。 示例:在列表中: 15264约翰克里斯1 12569克里斯约翰2 如果我试图删除John Chris,它将删除Chris John
这是结构:
typedef struct{
char name[31],first_name[31];
int speciality, number;
struct mechanic *next;
}mechanic;
编辑:当我尝试显示列表时,似乎发生了SIGSEGV。这是函数:
void displayList(mechanic *first, int n)
{
int i;
mechanic *courant = malloc(sizeof(mechanic));
current = first;
printf("Mechanics :\n");
for(i = 1; i<n; i++)
{
printf("%5d %s %s",current->number,current->name, current->first_name);
switch(current->speciality)
{
case 1: printf(" Wheels\n");break;
case 2: printf(" Motor\n");break;
case 3: printf(" Carrosserie\n");break;
case 4: printf(" Chassis\n");break;
default: printf(" Maintenance\n");break;
}
current = current->next;
}
}
主要:
int main()
{
int nbMec = 1,i,choise;
int menu();
int remMec(mechanics*);
void afficherListe(mechanics*, int);
void addMec(mechanics*);
mechanics *first, *current, *nextM;
first = malloc(sizeof(mechanics));
current = first;
FILE *fdat, *fdat2;
fdat = fopen("clients.dat","r");
fdat2 = fopen("employe.dat","r");
// Lecture du fichier contenant les mécaniciens
fscanf(fdat2,"%5d",¤t->number);
while(!feof(fdat2))
{
fscanf(fdat2,"%s%s%1d",¤t->name, ¤t->first_name, ¤t->speciality);
nextM = malloc(sizeof(mechanics));
current->next = nextM;
nbMec++;
current = nextM;
fscanf(fdat2,"%5d",¤tM->number);
}
//Finir la liste avec NULL
current = first;
for(i = 1; i<nbMec; i++){
current = current->next;
}
current->next = NULL;
free(nextM);
DisplayList(first,nbMec);
// Redirection en fonction du choix dans le menu
choise = menu();
if(choise == 1)
{
// Ajout d'un mécano
addMec(first);
nbMec++;
displayList(first,nbMec);
} else if (choise == 2)
{
if(remMec(first))
{
printf("Mecanicien efface de la liste.\n");
nbMec--;
} else
{
printf("Impossible.\n");
}
afficherListe(first,nbMec);
} else
{
//Ajout d'un rendez-vous
}
return 0;
}
这是employe.dat文件:
12345 Ric Hochet 1
13456 Jean Valjean 2
14567 Rick Grimes 3
15007 James Bond 4
16789 Rogge Jacquie 5
记录示例:
XXXXX CCCCC CCCCC X
number name first_name speciality
你能帮帮我吗?
谢谢!
答案 0 :(得分:1)
你的第一个功能是这样开始的:
void addMec(mechanics* first)
{
mechanics *new = malloc(sizeof(mechanic));
int speciality();
if(first==NULL)
{
return(0);
} else
{
......
......
这不会编译!首先是因为return
带有void
函数的值,第二个是未定义的类型名称。
即使它确实如此,也没有任何意义。首先,分配一块内存并将指针存储在new
变量中。然后测试first
是否为NULL
,如果是,则从函数返回。
仔细看:你从这个功能回来了。因此,您不输入新变量的任何数据,不会将附加到列表中。这意味着,如果之前没有从文件中填充,那么您的程序可以不构建用户输入的任何列表。
此外,从函数返回时,所有本地自动变量都将丢失。其中包含new
。这意味着您不再能够访问刚刚分配的块 - 它会丢失。您分配了一些内存但无法以任何方式使用它。这就是我们所说的内存泄漏。
为了使函数更具可读性(并且更容易进一步开发),我将它分成两部分:一部分用于创建一个新对象并将其放入列表中,一个子例程用用户输入填充它:
void inputMec(mechanic *mec)
{
int speciality();
printf("Add mechanic : \n");
// Ask for needed informations.
printf("Employee-Number : ");
scanf("%5d", & mec->number);
printf("\nName : ");
scanf("%s", & mec->name);
printf("\nFirst Name : ");
scanf("%s", & mec->first_name);
mec->speciality = speciality();
}
void addMec(mechanic* first)
{
if(first != NULL) // only if the list's head exists
{
mechanic *new = malloc(sizeof(mechanic));
if(new != NULL) // a new object created sucessfully
{
inputMec(new);
printf("%d %s %s %d\n",new->number,
new->name, new->first_name, new->speciality);
// find the last item in the list
mechanic *last = first;
while(last->next != NULL) // still not the last one?
{
last = last->next; // step forward
}
last->next = new; // append after the last
new->next = NULL; // terminate the list
}
}
}
如果列表中的排序不重要(从您的代码中看起来如此),那么您可以更轻松地在列表的开头添加新项目:
// insert the item just after the list's head
new->next = first->next; // append the list after the new item
first->next = new; // link the new item to the head
在实际的编程任务中,您还必须考虑限制和验证输入,这两者都是内部限制(字符串非空?它们不是太长了吗?是字典范围中的speciality
值吗? )和外部一致性(员工的标识符是否不同?是他们的名字+ first_name对不同吗?)
如果内部不一致,您可能会要求正确的数据,并循环读取输入直到它正确,或放弃输入操作;在后一种情况下,inputMec
例程应该return
某种状态。然后调用程序例程addMec
应该测试状态以决定是否在列表中插入新项目,或者在输入失败时将free()
插入列表中。
如果发生外部冲突,您可以打印相应的消息,暂时保留新项目并迭代读取输入以获取非冲突数据,或者您可以放弃操作free()
对象并返回主菜单,用户所在可以再次进入添加机制。
答案 1 :(得分:1)
我找到了解决方案: 关于addMec,感谢CiaPan 。 在这些问题之后,我选择在列表的开头添加一个新的机制。 我还创建了一个包含第一个元素的列表结构。 这是正确的addMec(请注意,对于该项目,我已添加了rep(修复)数组):
void addMec(list *list, int number, char name[], char first_name[], int speciality)
{
int i;
mechanics *new = malloc(sizeof(mechanics));
if(list == NULL || new == NULL)
{
exit(EXIT_FAILURE);
}
new->number = number;
strcpy(new->name,name);
strcpy(new->first_name,first_name);
new->speciality = speciality;
for(i = 1; i<=50; i++)
{
new->rep->year=0;
new->rep->day = 0;
new->rep->month = 0;
new->rep->price = 0;
new->rep->emergency = 0;
strcpy(new->rep->brkdwn,"");
}
new->next = list->first;
list->first = new;
list->nbElmt++;
}
关于remMec,我在另一个网站上搜索,一个名为 pagrette 的用户解释了我。 有了这些行,
intercale = current->next;
current->next = intercale->next;
free(intercale);
我只是释放下一个元素 谢谢你的帮助!