我试图通过传递一个指向列表头部的指针来创建一个函数内的链表。在函数内部,一切都很完美。但是当我回到main()
时,指针突然变成了NULL。所以如果我再次调用这个函数,它就像我第一次添加一个节点一样。
我的代码有什么问题?
struct course
{
int c_ID;
char *c_name;
struct course *c_next;
};
void new_course(struct course *c_head, struct course *c_tail); // adds a node
int main ( )
{
// variable declarations
int choice;
char y_n;
// create linked lists
struct course *c_head = NULL;
struct course *c_tail = NULL;
// print out menu, obtain choice, call appropriate function; loop if desired
do
{
printf("ttt***MENU***n"
" 1. Add a new coursenn"
................................
"Enter the number of the menu option you wish to choose: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
new_course(c_head, c_tail);
if (c_tail == NULL)
{
printf("We're screwed.n"); // this excecutes every time
}
break;
.....................
}
printf("Would you like to return to the main menu? Enter y for yes, n for no: ");
scanf(" %c", &y_n);
} while (y_n != 'n' && y_n != 'N');
// free courses
struct course *c_temp = NULL;
c_temp = c_head;
while (c_temp != NULL)
{
c_head = c_head->c_next;
c_temp->c_ID = 0; // reinitialize the student ID
c_temp->c_name[0] = ' '; // reinitialize the student name string
free(c_temp->c_name); // return the string memory to the system
free(c_temp); // return the node memory to the system
c_temp = c_head; // set temp to next item in the list
}
return 0;
}
void new_course(struct course *c_head, struct course *c_tail)
{
// declare variables
int ID;
char name[50];
// obtain user input
printf("Enter the course ID number and the course name, separated by a space: ");
scanf("%d%s", &ID, name);
if(c_head == NULL) // no courses yet
{
c_head = (struct course *) malloc(sizeof(struct course)); // allocate memory for c_head
c_head->c_next = NULL;
c_tail = c_head; // update c_tail
}
else // the list already has nodes
{
c_tail->c_next = (struct course *) malloc(sizeof(struct course)); // allocate memory for new node
c_tail = c_tail->c_next; // update c_tail
c_tail->c_next = NULL;
}
c_tail->c_ID = ID; // assign ID to c_ID component of new node
c_tail->c_name = (char *) malloc(sizeof(char) * strlen(name) + 1); // allocate memory for c_name component of new node
strcpy(c_tail->c_name, name); // assign name to c_name component of new node
printf("%d = %d, %s = %sn", c_head->c_ID, ID, c_tail->c_name, name); // this always works, proving the list was created and the assignments worked
return;
}
在C语言中,所有东西都是按值传递的,包括指针。c_head
和c_tail
在主叫上下文中不能被new_course
修改。要做到这一点,函数签名需要如下所示:
void new_course(struct course **c_head, struct course **c_tail)
和整个new_course
的主体,您需要引用*c_head
和*c_tail
,如:
*c_head = (*c_head)->c_next;
和main
必须这样调用它:
new_course(&c_head, &c_tail);
您需要将指针传递给指针,以便更改c_head和c_tail的值。
像这样调用
new_course(&c_head, &c_tail);
像这样使用
void new_course(struct course **c_head, struct course **c_tail)
{
if((*c_head) == NULL) // no courses yet
{
(*c_head) = (struct course *) malloc(sizeof(struct course));
…等等。
}
我自己不会这样写,但那是你的问题。
C
使用按值传递函数参数。
在你的例子中,你使用的是函数
void new_course(struct course *c_head, struct course *c_tail)
用
调用new_course(c_head, c_tail);
不能,从new_course()
函数中,你可以改变c_head
和c_tail
所指向的值,但是你不能改变这两个指针本身。
如果你必须从new_course()
更改c_head
和c_tail
,你需要传递一个指针给它们,即指针指向指针。
否则,您有另一个选项来处理这种情况。如果您想简单地传递指针并从函数中更改指针本身,则需要从函数中return
修改过的指针,并将其收集到用作参数(并在函数中更改)的相同变量中。然后,更改将反映在调用函数中。
话虽如此,作为提示,
- 请参阅为什么不将
malloc()
和family的返回值强制转换为C
。 -
sizeof(char)
保证为C
中的1
。乘以相同是多余的,可以避免。
main()
的推荐签名为int main(void)