【问题标题】:Why am I getting garbage value after displaying the data为什么显示数据后我得到垃圾值
【发布时间】:2017-08-26 13:03:18
【问题描述】:
  1. 我在显示记录时得到垃圾值。

  2. 我必须用 C 语言创建一个学生数据库,使用结构数组且不使用指针。

  3. 还有其他方法吗?

  4. 如何使用结构数组?

    #include <stdio.h>
    
    struct student {
        char first_name[10],last_name[10];
        int roll;
        char address[20];
        float marks;
    };
    
    void accept(struct student);
    void display(struct student);
    
    void main() {
        struct student S[10];
        int n, i;
        printf("Enter the number of records to enter : ");
        scanf("%d", &n);
    
        for (i = 0; i < n; i++) {
            accept(S[i]);
        }
    
        for (i = 0; i < n; i++) {
            display(S[i]);
        }
    }
    
    void accept(struct student S) {
        scanf("%s", S.first_name);
        scanf("%s", S.last_name);
        scanf("%d", &S.roll);
        scanf("%s", S.address);
        scanf("%f", &S.marks);
    }
    
    void display(struct student S) {
        printf("\n%s", S.first_name);
        printf("\n%s", S.last_name);
        printf("\n%d", S.roll);
        printf("\n%s", S.address);
    }
    

【问题讨论】:

  • C11 标准草案 n1570:6.5.2.2 函数调用 4 参数可以是任何完整对象类型的表达式。在准备调用函数时,会评估参数,并为每个参数分配相应参数的值。 93)一个函数可以改变其参数的值,但这些改变不会影响参数的值[...]
  • 所以,void accept(struct student *S){ scanf("%s", S-&gt;first_name);.. 打电话给accept(&amp;S[i]);
  • 非常感谢朋友。

标签: c arrays database structure


【解决方案1】:

C 中的一切都是按值传递。这意味着您正在修改堆栈帧中的变量副本,而作为参数传递的真实变量保持不变。

您必须传递一个指向要在函数中修改的变量的指针。

// Function declaration
void accept(struct student *);

// Call
accept(&S[i]);

// Usage in function via dereference operator
scanf("%s",S->first_name);

如果您想输入未知数量的记录,您应该使用VLA (since c99) 或动态分配结构。

VLA

scanf("%d",&n);
struct student S[n];

动态调用

scanf("%d",&n);
struct student * S = malloc(sizeof(struct student) * n);

因为在您的情况下,如果用户输入超过 9 条记录,您将超出界限,这具有未定义的行为。

【讨论】:

  • 非常感谢朋友。
  • void display(struct * student);display(&amp;S[i]); --> void accept(struct student *); accept(&amp;S[i]);
  • 叹息..void accept(struct * student);:这是语法错误。
  • 哦,我应该多加注意
【解决方案2】:

您的代码中有多个问题:

  • 不带参数的main 的标准原型是int main(void)
  • 您应该使用calloc 动态分配数组。
  • 您应该将结构指针传递给acceptdisplay 函数,而不是按值传递结构。按值传递目标结构是不正确的,因为accept 函数无法修改main 函数中的结构,该结构保持未初始化并导致显示垃圾。请注意,访问未初始化的数据实际上是未定义的行为,因此程序可能会以更糟糕的方式运行。
  • 您应该为scanf() 提供要存储到字符数组中的最大参数数,以避免潜在的缓冲区溢出。
  • 您应该验证scanf() 的返回值,以避免在无效输入时出现未定义的行为。
  • 您可以使用%[^\n] 扫描集来允许在地址字段中嵌入空格。

这是修改后的版本:

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

struct student {
    char first_name[10], last_name[10];
    int roll;
    char address[20];
    float marks;
};

void accept(struct student *sp);
void display(const struct student *sp);

int main(void) {
    struct student *S;
    int n, i, j;
    printf("Enter the number of records to enter : ");
    if (scanf("%d", &n) != 1)
        return 1;

    S = calloc(sizeof(*S), n);
    if (S == NULL) {
        return 1;
    }
    for (i = 0; i < n; i++) {
        accept(&S[i]);
    }
    for (i = 0; i < n; i++) {
        display(&S[i]);
    }
    free(S);
    return 0;
}

void accept(struct student *sp) {
    if (scanf("%9s%9s&d %19[^\n]%f",
        sp->first_name, sp->last_name, &sp->roll,
        sp->address, &sp->marks) != 5) {
        printf("missing input\n");
        exit(1);
    }
}

void display(const struct student *sp) {
    printf("%s\n", sp->first_name);
    printf("%s\n", sp->last_name);
    printf("%d\n", sp->roll);
    printf("%s\n", sp->address);
    printf("%f\n", sp->marks);
    printf("\n");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    相关资源
    最近更新 更多