为什么我不能获得链表以从 C 中的函数传回?
Why can't I get a linked list to pass back from a function in C?
我正在尝试通过将指针传递到列表的头部来在函数内部创建一个链表。在函数内部,一切正常。但是当我回到 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("\t\t\t***MENU***\n"
" 1. Add a new course\n\n"
................................
"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] = '[=10=]'; // 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 = %s\n", c_head->c_ID, ID, c_tail->c_name, name); // this always works, proving the list was created and the assignments worked
return;
}
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
函数中修改后的指针并将其收集到你用作参数的同一个变量(并在功能)。然后,更改将 反映在调用函数中。
也就是说,作为注释,
- 请see why not to cast
malloc()
和家人C
的return值。
sizeof(char)
保证在C
中是1
。乘以相同是多余的,可以避免。
main()
的推荐签名是int main(void)
在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));
...等等等等
}
我自己不会这样写,但那是你的问题。
我正在尝试通过将指针传递到列表的头部来在函数内部创建一个链表。在函数内部,一切正常。但是当我回到 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("\t\t\t***MENU***\n"
" 1. Add a new course\n\n"
................................
"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] = '[=10=]'; // 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 = %s\n", c_head->c_ID, ID, c_tail->c_name, name); // this always works, proving the list was created and the assignments worked
return;
}
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
函数中修改后的指针并将其收集到你用作参数的同一个变量(并在功能)。然后,更改将 反映在调用函数中。
也就是说,作为注释,
- 请see why not to cast
malloc()
和家人C
的return值。 sizeof(char)
保证在C
中是1
。乘以相同是多余的,可以避免。main()
的推荐签名是int main(void)
在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));
...等等等等
}
我自己不会这样写,但那是你的问题。