传递给函数后,C指针不会被设置

时间:2015-02-24 07:10:41

标签: c pointers

所以我一直在努力学习C一段时间,我终于打了一堵砖墙。我在网上发现了不同的练习题,我真的遇到了这个问题。

最初我在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;

                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;
}

现在问题出现了。我传了指针“学生们”#39;并且第一次传递它是一个空指针,并被函数中的if语句正确捕获。 newStudent变量指向内存地址。

在这些行之后:

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

指针&#39;学生&#39;现在指向一个实际的地址。但是在主要方法中回到while循环之后,“学生们”才开始学习。指针又是一个NULL指针。

作为补充信息,您可以看到放入这些printf&#39;:

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

我真的花了很多时间在这上面,最后让我们来这里问你们所有人。 如果您还需要其他任何内容来澄清这个问题,请告诉我。

彼得

2 个答案:

答案 0 :(得分:3)

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

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

一样打电话
  

addStudentToTree(安培;学生,newStudent,currentStudent);

中的函数

  

* sudents = NULL;

希望有所帮助

答案 1 :(得分:0)

想象一下:

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

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

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

如果您确实理解函数var中的变量main的副本保留其原始&#34;价值,那么你不应该理解你在函数students内分配给变量printStudents的任何值(在你的函数*之外)都不会生效。

话虽如此,以下是通过引用传递此变量的一般准则

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