为什么我不能获得链表以从 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_headc_tail指向的,但是你不能改变这两个指针本身。

如果您必须从 new_course() 更改 c_headc_tail,您需要传递一个指向它们的指针,即指向指针的指针。

否则,您还有另一种选择来处理这种情况。如果你想简单地传递指针并从函数中更改指针本身,你需要 return 函数中修改后的指针并将其收集到你用作参数的同一个变量(并在功能)。然后,更改将 反映在调用函数中

也就是说,作为注释,

  1. see why not to castmalloc()和家人C的return值。
  2. sizeof(char)保证在C中是1。乘以相同是多余的,可以避免。
  3. main()的推荐签名是int main(void)

在C语言中,一切都是按值传递的,包括指针。调用者上下文中 c_headc_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)); 

...等等等等

}

我自己不会这样写,但那是你的问题。