【问题标题】:String member of struct is appending other string member, both parsed with scanfstruct 的字符串成员正在附加其他字符串成员,均使用 scanf 解析
【发布时间】:2021-01-29 21:35:15
【问题描述】:

我对 C 有点陌生。所以,我动态创建了一个结构数组,并希望从用户那里获取输入并存储在数组中。

struct course{
    char code[CODE_LENGTH];
    char name[NAME_LENGTH];
    int credits;
};

第二个字符串成员name 存储得很好。 第一个字符串成员 code 附加了第二个字符串成员。

程序代码:

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

#define CODE_LENGTH 7
#define NAME_LENGTH 3

struct course *createList(){
    int n;
    printf("Enter no. of courses you wish to take: ");
    scanf("%d", &n);
    
    struct course *courses = (struct course*)malloc(sizeof(struct course)*n);

    for(int i=0;i<n;i++){
        printf("Enter Course Code: ");
        scanf("%s",courses[i].code);
        printf("Enter Course name: ");
        scanf("%s",courses[i].name);
        printf("Enter no. of credits: ");
        scanf("%d",&courses[i].credits);
        printf("\n");

        printf("%s\n%s ",courses[i].code,courses[i].name);
    }
    return courses;
}
int main(){
    struct course *c = NULL;
    int credit;
    c=createList();
    free(c);
    return 0;
}

输出:

Enter no. of courses you wish to take: 2
Enter Course Code: CS6101D
Enter Course name: DS
Enter no. of credits: 4

CS6101DDS
DS Enter Course Code: 

如果CODE_LENGTH 是7,code 怎么能存储更多,为什么还要附加另一个字符串? 帮帮我!

【问题讨论】:

  • C 和 C++ 是不同的编程语言。
  • 无关:建议使用struct course *courses = malloc(n * sizeof *courses);而不是C中的struct course *courses = (struct course*)malloc(sizeof(struct course)*n);,它更短更安全。

标签: arrays c string struct dynamic-memory-allocation


【解决方案1】:

如果CODE_LENGTH 是 7,代码如何存储更多,为什么还要附加另一个字符串?

不能,事实上它只能存储6个字符加上空字节,你程序的不稳定行为是undefined behavior的结果。

您的代码极易受到缓冲区溢出的影响,您永远不应该在 scanf 中使用 %s 说明符,就像它一样,它并不比 gets 好,并且因为太危险且容易受到攻击而从标准中删除缓冲区溢出攻击,必须将输入限制为目标缓冲区的大小:

printf("Enter Course Code: "); 
scanf("%6s", courses[i].code);// %6s, 7 - 1, last element stores null byte
printf("Enter Course name: "); 
scanf("%2s", courses[i].name) //same idea

请注意,如果输入大于缓冲区的容量,剩余的字符将保留在stdin 缓冲区中,并由下一个scanf 解析,您可能需要将其清除。我刚刚回答了一个关于如何以稳健的方式仍然使用 scanf check it out 的问题。


题外话:

struct course *courses = (struct course*)malloc(sizeof(struct course)*n);

您应该删除演员表,它不是必需的,并且可以隐藏分配错误。

使用变量本身来推断大小也是一个好习惯,它使代码更易于维护:

struct course *courses = malloc(sizeof *courses * n);

【讨论】:

    【解决方案2】:

    您可能正在读取 7(或更多?)字符的字符串,例如 CS6101D,这将需要存储 8 chars,因为NUL 终止符'\0' 需要多一个charscanf 会自动添加。

    因此,您的代码正试图在courses[i].code[8] 上写入,它具有超出范围的索引。这是 C 中未定义的行为,可能会导致任何结果,包括您得到的结果。

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 2013-12-12
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 2018-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多