当我用scanf("%s%s%s", word0, word1, word2)输入多个单词时,除了最后一个单词之外,每个单词的第一个字符都丢失了

问题描述 投票:0回答:1

这是我的代码:

#include <stdio.h>

int main() {
    char word0[4], word1[4], word2[4];
    scanf("%s%s%s", word0, word1, word2);
    printf("word0: ");
    for(int i = 0; i < 4; ++i) printf("%c", word0[i]);
    printf("\nword1: ");
    for(int i = 0; i < 4; ++i) printf("%c", word1[i]);
    printf("\nword2: ");
    for(int i = 0; i < 4; ++i) printf("%c", word2[i]);
}

输入:

zxcv abcd 1234

它输出:

word0: xcv
word1: bcd
word2: 1234

我更改了代码

scanf("%s%s%s", word0, word1, word2);

scanf("%s", word0);
scanf("%s", word1);
scanf("%s", word2);

然后我调试代码:
(对于这种情况,我输入的是

zxcv qwer 0235

ScreenshotScreenshot
我对这个结果完全出乎意料。
scanf()
如何在该行执行后修改变量?

c scanf
1个回答
0
投票

您的数组存在经典的 - 字节太短问题。继续我的评论。在 C 语言中,字符串被定义为以

'\0'
nul-character)结尾的字符序列。这就是所有采用字符串作为参数的函数如何知道字符串结束的位置。

为了防止出现问题,在使用 "%s"

"%[..]"
转换说明符填充数组时,必须始终指定
field-width
修饰符。您必须手动提供 field-width 修饰符,因为它无法使用命名常量指定或作为参数提供给
scanf()
。字段宽度修饰符设置为
size-of-array - 1
以将
scanf()
读取的字符数限制为比数组大小小 1 — 确保为 nul 终止字符保留 1 个字节。

对于您的数组,这将是

"%3s"
——这显示了您遇到的 off-by-one 错误。发生的情况是您超出数组末尾的写入覆盖了下一个数组的第一个字符的地址,依此类推。

要正确使用

scanf()
,您必须始终检查返回值,如果填充数组,请始终使用 field-width 修饰符。

将代码中的简短示例放在一起,并展示几种输出方式,您可以这样做:

#include <stdio.h>

#define MAXC 64   /* if you need a constant, define one (or more) */

int main() {
    /* use a constant to set array size */
    char word0[MAXC], word1[MAXC], word2[MAXC];
    
    /* prompt for input */
    puts ("enter 3 space separated words");
    
    /* ALWAYS use the field-width modifier filling arrays and
     * ALWAYS check the scanf return.
     */
    if (scanf("%63s%63s%63s", word0, word1, word2) != 3) {
        fputs ("error: reading words.\n", stderr);
        return 1;
    }
    putchar ('\n');                     /* tidy up with newline */
    
    fputs ("word0: ", stdout);
    for (int i = 0; word0[i]; i++) {    /* if you want to loop chars */
        putchar (word0[i]);
    }
    putchar ('\n');                     /* tidy up with newline */
    
    fputs ("word1: ", stdout);
    puts (word1);                       /* otherwise just output the word */
    
    fputs ("word2: ", stdout);
    puts (word2);
}

示例使用/输出

用你的例子:

$./bin/3words
enter 3 space separated words
xzcv abcd 1234

word0: xzcv
word1: abcd
word2: 1234

如果您还有其他问题,请告诉我 - 并考虑使用

fgets()
读取所有输入,一次读取一行并避免
scanf()
陷阱...

© www.soinside.com 2019 - 2024. All rights reserved.