C 指针在传递给函数后未设置

C pointer does not get set after being passed to a function

所以我一直在努力学习 C 语言一段时间,但我终于碰壁了。我在网上发现了不同的练习题,我真的遇到了这个问题。

最初我在主函数中编写了这段代码,它运行良好并提供了所需的输出(这里是 正在运行的示例

#include <stdio.h>
#include <stdlib.h>

typedef struct Student STUDENT;
typedef struct Teacher TEACHER;
typedef struct Course COURSE;

int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent);
void printStudents(STUDENT *s);

struct Student
{
    int StudentNumber;
    char FirstName[BUFSIZ];
    STUDENT *left, *right;
};

struct Teacher
{
    int TeacherNumber;
    char FirstName[BUFSIZ];
    TEACHER *left, *right;
};

struct Course
{
    int CourseNumber;
    char CourseName[BUFSIZ];
    int SemesterNumber;
    COURSE *left, *right;
};

int main()
{
    FILE *db = fopen("DatabaseFile.txt", "r");
    char line[BUFSIZ]; 

    STUDENT *newStudent, *currentStudent, *students;
    students = NULL;

    if (db != NULL)
    {
        while (fgets(line, sizeof(line), db) != NULL)
        {   
            if (line[0] == 'S')
            {
                newStudent = malloc(sizeof(STUDENT));

                if (sscanf(line, "S %d %s", &newStudent->StudentNumber, newStudent->FirstName) == 2)
                {
                    newStudent->left = NULL;
                    newStudent->right = NULL;

                if (students == NULL)
                {   
                    students = newStudent;      

                }
                else
                {
                    currentStudent = students;

                    while(currentStudent)
                    {
                        if (newStudent->StudentNumber != currentStudent->StudentNumber)
                        {
                            if (newStudent->StudentNumber < currentStudent->StudentNumber)
                            {
                                if (currentStudent->left == NULL)
                                {
                                    currentStudent->left = newStudent;
                                    break;
                                }
                                else
                                {
                                    currentStudent = currentStudent->left;
                                }
                            }
                            else
                            {
                                if (currentStudent->right == NULL)
                                {
                                    currentStudent->right = newStudent;
                                    break;
                                }
                                else
                                {
                                    currentStudent = currentStudent->right;
                                }
                            }
                        }

                    }
                }               

                }

            }
        }
    }
    printStudents(students);
}

它成功地填充了树,然后遍历它给出了以下输出:

Student Number: 203214 Student Name: Agneta
Student Number: 208214 Student Name: Janeta
Student Number: 213363 Student Name: Jill
Student Number: 215263 Student Name: Hansi
Student Number: 215363 Student Name: Laurent
Student Number: 228214 Student Name: James

现在练习题的一部分也将它移到函数中,这样一切都不会 运行 在 main 方法中。

我是这样做的:

#include <stdio.h>
#include <stdlib.h>

typedef struct Student STUDENT;
typedef struct Teacher TEACHER;
typedef struct Course COURSE;

int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent);
void printStudents(STUDENT *s);

struct Student
{
    int StudentNumber;
    char FirstName[BUFSIZ];
    STUDENT *left, *right;
};

struct Teacher
{
    int TeacherNumber;
    char FirstName[BUFSIZ];
    TEACHER *left, *right;
};

struct Course
{
    int CourseNumber;
    char CourseName[BUFSIZ];
    int SemesterNumber;
    COURSE *left, *right;
};

int main()
{
    FILE *db = fopen("DatabaseFile.txt", "r");
    char line[BUFSIZ]; 

    STUDENT *newStudent, *currentStudent, *students;
    students = NULL;

    if (db != NULL)
    {
        while (fgets(line, sizeof(line), db) != NULL)
        {   
            if (line[0] == 'S')
            {
                newStudent = malloc(sizeof(STUDENT));

                if (sscanf(line, "S %d %s", &newStudent->StudentNumber, newStudent->FirstName) == 2)
                {
                    newStudent->left = NULL;
                    newStudent->right = NULL;
                    addStudentToTree(students, newStudent, currentStudent);                 
                }

            }
        }
    }
    printStudents(students);
}

int addStudentToTree(STUDENT *students, STUDENT *newStudent, STUDENT *currentStudent)
{

    if (students == NULL)
    {   
        students = newStudent;
        return 1;
    }
    else
    {
        currentStudent = students;

        while(currentStudent)
        {
            if (newStudent->StudentNumber != currentStudent->StudentNumber)
            {
                if (newStudent->StudentNumber < currentStudent->StudentNumber)
                {
                    if (currentStudent->left == NULL)
                    {
                        currentStudent->left = newStudent;
                        return 1;
                    }
                    else
                    {
                        currentStudent = currentStudent->left;
                    }
                }
                else
                {
                    if (currentStudent->right == NULL)
                    {
                        currentStudent->right = newStudent;
                        return 1;
                    }
                    else
                    {
                        currentStudent = currentStudent->right;
                    }
                }
            }

        }
    }
    return 0;
}

现在问题来了。我传入指针 'students' ,第一次传递时它是一个空指针,并被函数中的 if 语句正确捕获。 newStudent 变量指向内存地址。

在这些行之后:

if (students == NULL)
{   
    students = newStudent;
    return 1;
}

指针 'students' 现在指向一个实际地址。但是在返回到 main 方法中的 while 循环后,'students' 指针再次成为 NULL 指针。

作为附加信息,您可以看到放入这些 printf:

if (students == NULL)
    {   
        printf("students: %p, newStudent: %p\n",students, newStudent );
        students = newStudent;
        printf("students: %p\n",students);
        return 1;
    }

产生这个输出:

students: 0x0, newStudent: 0x7fc6e2001200
students: 0x7fc6e2001200
students: 0x0, newStudent: 0x7fc6e2001800
students: 0x7fc6e2001800
students: 0x0, newStudent: 0x7fc6e2005200
students: 0x7fc6e2005200
students: 0x0, newStudent: 0x7fc6e2005800
students: 0x7fc6e2005800
students: 0x0, newStudent: 0x7fc6e2005e00
students: 0x7fc6e2005e00
students: 0x0, newStudent: 0x7fc6e2006400
students: 0x7fc6e2006400

我真的花了很多时间在这上面,终于屈服了,来这里问问大家。 如果您还需要澄清这个问题,请告诉我。

彼得

你需要传递指针的地址...在这种情况下,参数是在堆栈上创建的,当函数退出时,堆栈被展开并且你的参数不再有效

int addStudentToTree(STUDENT **students, STUDENT *newStudent, STUDENT *currentStudent);

一样打电话

addStudentToTree(&students,newStudent,currentStudent);

在函数中像

*sudents=NULL;

希望对您有所帮助

想象一下:

void func(int var)
{
    var = 1;
}

int main()
{
    int var = 0;
    func(var);
    // What is the value of 'var' at this point?
    ...
}

如果您对上述问题的回答是1,那么您可能应该回到基础知识,从头开始学习这门语言。

如果您确实了解函数 main 中变量 var 的副本保留其 "original" 值,那么您理解您分配给的任何值应该没有任何问题变量 students 在函数 printStudents 内的(副本)不会在该函数外生效。

也就是说,这里是通过引用传递此变量的一般准则

  1. 函数声明中的变量类型加上* - printStudents(STUDENT** s)
  2. * 添加到您在函数 printStudents
  3. 中对该变量所做的每个引用
  4. 在每个调用函数的地方在变量前加上& - printStudents(&s)