struct 的字符串成员附加其他字符串成员,均使用 scanf 解析

String member of struct is appending other string member, both parsed with scanf

我对 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 怎么能存储更多,为什么要附加另一个字符串? 帮帮我!

If CODE_LENGTH is 7 how can code store more than that and why is it appending the other string?

它不能,事实上它只能存储 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

注意如果输入大于buffer所能接受的,剩余的字符会保留在stdinbuffer中,被下一个scanf解析,可能需要clear它。我刚刚回答了一个关于如何以稳健的方式做到这一点的问题,仍然使用 scanf check it out.


Off-topic:

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

您应该删除强制转换,它不是必需的并且可以隐藏分配错误。

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

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

您可能正在读取一串 7(或更多?)字符,例如 CS6101D,这将需要 8 chars 将被存储,因为您还需要一个 char 作为 NUL 终止符 '[=13=]'scanf 将自动添加。

因此,您的代码正试图在 courses[i].code[8] 上写入,它有一个越界索引。这是 C 语言中未定义的行为,可能导致任何结果,包括您得到的结果。