当我将学生添加到链接列表中时,将添加他们,我的计数功能将确认添加了正确数量的学生。但是,使用我的打印功能后,只会将最新的条目打印到添加的第n个学生中。可以肯定我的addStudent函数可以正常工作,但是我也可以肯定我的打印函数也是正确的。我的教授最初写的是RETURN NULL。作为addStudent函数的返回部分,但似乎不起作用,也没有将学生添加到计数或链接列表中。
Student* addStudent(Student *headStudentList, char last[], char first[])
{
if(headStudentList == NULL){
Student * newNode = malloc(sizeof(Student));
newNode->firstName = first;
newNode->lastName = last;
newNode->next = NULL;
headStudentList = newNode;
}
else {
int check = 0;
for(Student *cur = headStudentList; cur != NULL; cur = cur->next)
{
if(strcmp(first,cur->firstName)== 0 && strcmp(last, cur->lastName)== 0){
check++;quit
}
}
if (check == 0) {
Student * newNode = malloc(sizeof(Student));
newNode->firstName = first;
newNode->lastName = last;
newNode->next = headStudentList;
headStudentList = newNode;
}
if (check != 0){
printf("This Name Already Exists In The List. Enter A Different Name");
}
}
return headStudentList;
}
void print(Student *headStudentList)
{
for(Student *cur = headStudentList; cur != NULL; cur = cur->next) {
printf("\nStudent Name: ");
printf("%s, ", cur->lastName);
printf("%s ", cur->firstName);
printf("\n");
}
return;
}
这里是主要文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gradebook.h"
typedef
enum {
ADD_STUDENT,
ADD_GRADE,
COUNT,
PRINT_STUDENT,
PRINT,
ADD_STUDENT_ORDERED,
ADD_GRADE_ORDERED,
REMOVE_GRADE,
REMOVE_STUDENT,
HELP,
QUIT,
INVALID
}
Option
;
char *actions[11] = {
"addStudent",
"addGrade",
"count",
"printStudent",
"print",
"addStudentOrdered",
"addGradeOrdered",
"removeGrade",
"removeStudent",
"help",
"quit"
};
int getActionID(char action[])
{
int i;
for (i=0; i<11; i++) {
if (strcmp(action, actions[i])==0) return i;
}
return i; // 11 for invalid action
}
int isValidGradeName(char gradeName[])
{
char type;
int chap, sec;
sscanf(gradeName, "%c%d.%d", &type, &chap, &sec);
if (type!='P' && type!='C' && type!='L') return 0;
if (chap<=0 || sec<=0) return 0;
char name2[100];
sprintf(name2, "%c%d.%d", type, chap, sec);
if (strcmp(gradeName, name2)!=0) return 0;
return 1;
}
void printHelp(void) {
printf("\nThe valid commands:\n\n");
printf("\taddStudent lastname firstname\n");
printf("\t*** Add a student (add-at-front)\n");
printf("\taddGrade lastname firstname gradename value\n");
printf("\t*** Add a grade to an existing student (add-at-end)\n");
printf("\tcount\n");
printf("\t*** Print the number of students\n");
printf("\tprintStudent lastname firstname\n");
printf("\t*** Print a student\n");
printf("\tprint\n");
printf("\t*** Print all students\n");
printf("\taddStudentOrdered lastname firstname\n");
printf("\t*** Add a student (in alphabetical order)\n");
printf("\taddGradeOrdered lastname firstname gradename value\n");
printf("\t*** Add a grade in order to an existing student\n");
printf("\tremoveGrade lastname firstname gradename\n");
printf("\t*** Remove a grade from a student\n");
printf("\tremoveStudent lastname firstname\n");
printf("\t*** Remove a student\n");
printf("\thelp\n");
printf("\t*** Display this list\n");
printf("\tquit\n");
printf("\t*** Exit the program\n");
printf("\nNote: a valid grade name starts with a letter (P, C or L),\n");
printf("followed by a chapter number, a dot, and a section number.\n\n");
}
int main(int argc, char* argv[])
{
char action[100];
char last[100], first[100];
char gradeName[100];
double value;
char rest[300];
Student *headStudentList=NULL;
while (1) {
printf("\nEnter a command: ");
scanf("%s", action);
int action_id=getActionID(action);
if (action_id==QUIT) break;
switch (action_id) {
case ADD_STUDENT:
scanf("%s%s", last, first);
headStudentList = addStudent(headStudentList, last, first);
break;
case ADD_GRADE:
scanf("%s%s", last, first);
scanf("%s", gradeName);
if (isValidGradeName(gradeName)) {
scanf("%lf", &value);
addGrade(headStudentList, last, first, gradeName, value);
}
else {
printf("\n%s: invalid grade name. Type help for help.\n", gradeName);
fgets(rest, 300, stdin); // skip the rest of line
}
break;
case COUNT:
printf("\nThere are %d students\n", count(headStudentList));
break;
case PRINT_STUDENT:
scanf("%s%s", last, first);
printStudent(headStudentList, last, first);
break;
case PRINT:
print(headStudentList);
break;
case ADD_STUDENT_ORDERED:
scanf("%s%s", last, first);
headStudentList = addStudentOrdered(headStudentList, last, first);
break;
case ADD_GRADE_ORDERED:
scanf("%s%s", last, first);
scanf("%s", gradeName);
if (isValidGradeName(gradeName)) {
scanf("%lf", &value);
addGradeOrdered(headStudentList, last, first, gradeName, value);
}
else {
printf("\n%s: invalid grade name. Type help for help.\n", gradeName);
fgets(rest, 300, stdin); // skip the rest of line
}
break;
case REMOVE_GRADE:
scanf("%s%s", last, first);
scanf("%s", gradeName);
if (isValidGradeName(gradeName)) {
removeGrade(headStudentList, last, first, gradeName);
}
else {
printf("\n%s: invalid grade name. Type help for help.\n", gradeName);
fgets(rest, 300, stdin); // skip the rest of line
}
break;
case REMOVE_STUDENT:
scanf("%s%s", last, first);
headStudentList = removeStudent(headStudentList, last, first);
break;
case HELP:
printHelp();
break;
case INVALID:
printf("\n%s: invalid action. Type help for help.\n", action);
fgets(rest, 300, stdin); // skip the rest of line
break;
}
}
return 0;
}
答案 0 :(得分:2)
您每次都为last
和first
传递相同的数组。然后,您将此指针的值复制到每个firstName
的{{1}}和lastName
成员中。这意味着他们都指向同一个地方。然后,当您输入新的名字和姓氏时,它将覆盖以前的名字。这就是列表中所有成员都显示相同内容的原因。
您需要为每个字符串的副本分配空间,并将此空间分配给Student
和firstName
。您可以使用lastName
来做到这一点。
所以您在任何地方都可以这样做:
strdup
相反,这样做:
newNode->firstName = first;
newNode->lastName = last;
将学生从列表中删除后,您需要确保在致电newNode->firstName = strdup(first);
newNode->lastName = strdup(last);
上的free
之前先对其中的每个呼叫free
。