在 C 中存储和打印出结构的元素

storing and printing out elements of structs in C

我创建了一个简单的结构:

struct album {
    char title[20];
    char artist[20];
};

后来在程序中我创建了一个实例 a (struct album a;)。我只需要让用户输入标题和艺术家,以便我将它们保存在适当的位置,然后打印值:

printf("Please enter your album: \n");
printf("album name: ");
scanf("%.20s", a.title);

fflush(stdin);
printf("artist: ");
scanf("%.20s", a.artist);

printf("======\n");
printf("The album's name is %s and the artist is %s\n", a.title, a.artist);

然而当我运行这个时,我得到这个结果:

部分输入文本丢失。这里到底出了什么问题?

使用 scanf 中的 %s 说明符,长度说明符是 要写入的字符数 。这与大多数需要整个缓冲区大小的函数不同。

由于您的缓冲区需要包含空终止符,因此您需要在此处使用 "%.19s"。另一种选择是不对值进行硬编码:

scanf("%.*s", (int)sizeof a.title - 1, a.title);

请注意,这仅在 a.title 是数组(而非指针)时有效,并且强制转换是必要的,因为 int 可能是比 size_t 更小的类型,但是 * 期望 int.

正如其他人所指出的,%s 用于阅读直到下一个空格。您可以使用 %[ 阅读到下一行,例如:

scanf("%.19[^\n]", a.title);

^的意思是继续阅读,直到命中以下任何一个字符,\n实际上是指换行符,而不是一般的空格。

执行此操作后您需要刷新缓冲区,因为换行符仍将在缓冲区中。但是 fflush(stdin); 不可移植。丢弃当前行的其余部分的可移植方法是:

int ch;  while( (ch = getchar()) != EOF && ch != '\n' ) { }

scanf 读取最多为白色的字符 space。因此,如果您输入 Michel Jackson,Michel 和 Jackson 之间的 space 会终止您的字符串,因此您只会得到字符串 Michel。

尝试使用类似 fgets 的东西:

fgets(a.artist, 20, stdin);

fgets 获取在新行而不是白色终止字符串 space。

**如果您确实使用 fgets,请确保从字符串末尾删除换行符,因为您不希望末尾有换行符。