1

我对 C 有一个奇怪的问题。

我有一个.c实现结构的文件,另一个使用它。有问题的结构是关于学生的基本信息(姓名和年级)。实现文件具有功能

  • 初始化
  • 读名字
  • 阅读等级
  • 释放内存(删除实例)

主文件如下:

int main (void){
    char inBuff[30];
    char* name = NULL;
    int grade;
    Student Stu;

    printf("main: Please enter the name\n");
    fgets(inBuff, 30, stdin);
    name = malloc((sizeof(char)+1)*strlen(inBuff));
    strncpy (name, inBuff, 20);

    printf("main: Please enter the grade\n");
    scanf("%d", &grade);

    InitializeStudent (name, grade, &Stu);

    /*value testing*/
    printf("main: %s\n", Stu.name);
    printf("main: %d\n", Stu.grade);

    printf ("main: The student's name is %s\n", NameOfStudent(Stu));
    printf ("main: The student's grade is %d\n", GradeOfStudent(Stu));

    FreeStudent(&Stu);
    free (name);
    return 0;
}

printf()函数中的语句InitializeStudent()似乎显示了正确分配的值。但是,无论输入如何, Stu.nameand NameOfStudent(Stu)returnASCIIStu.Gradeand都GradeOfStudent(Stu)return 2675716(这似乎是一个内存地址)。

值得注意的是,它已被指定为按值传递而不是使用指针(即NameOfStudent()GradeOfStudent()应制作结构的副本并将其传递给函数)并分别具有char*int返回类型,而InitializeStudent()被传递一个指针,是一个空函数。

同样重要的是,Student 的 name 字段初始化为

char name[20];

而不是

char* name;

Student结构定义如下:

#define MAXNAMESIZE 20
typedef struct {
    char name[MAXNAMESIZE];
    int grade;
} Student;

根据要求,初始化学生的代码如下

void InitializeStudent (char *name, int grade, Student *S) {
    printf ("InitializeStudent: entered initialization\n");
    int i = 0;
    S = malloc (sizeof(Student));
    for (i = 0; i< strlen(name); i++)
        if (name[i] == '\n')
            name[i] = '\0';
    strncpy(S->name, name, 20);
    S->grade = grade;

    printf ("InitializeStudent: %s\n", S->name);
    printf ("InitializeStudent: %d\n", S->grade);
}
4

1 回答 1

2

问题是您StudentInitializeStudent函数中分配结构,当您将指针传递给已分配的结构时。

而且因为参数是按值传递(即复制)给函数的,所以指针S是一个副本,所以当你分配给它时,你只分配给函数中的本地副本。这就是为什么main函数中的结构没有初始化的原因,因为你只初始化了你在InitializeStudent函数中分配的结构,而不是你传入的那个。

最后,请注意strncpy源字符串是否比您传递给它的长度长,那么该函数将不会添加字符串终止符。


哦,顺便说一句,有一种更简单的方法可以从中删除换行符fgets:只需“删除”最后一个字符:

/* If `name` is not a `NULL` pointer, and the length is larger than zero
 * and the last character is a newline...
 */
if (name != NULL && strlen(name) > 0 && name[strlen(name) - 1] == '\n')
    name[strlen(name) - 1] = '\0';
于 2013-09-27T17:18:14.770 回答