以下是我的代码:

#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);

and then I debug the code:
(For this case I was input with zxcv qwer 0235)
Screenshot Screenshot
I am 至tally unexpected with those result.
How can scanf() modify the variable after the line has executed?

推荐答案

您的数组有一个典型的too-short-by-one字节问题.继续我的 comments .在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 (not Magic-Numbers) */
    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);
}

(Note: puts()将始终将'\n'附加到正在输出的字符串.如果您需要行结束控制,那么使用fputs(),但不需要.关键是,当您的输出字符串中没有转换时,您不需要调用变量printf()函数.)

Example Use/Output

使用您的示例:

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

word0: xzcv
word1: abcd
word2: 1234

或者三个不同大小的单词:

$ ./bin/3words
enter 3 space separated words
My Elephant Sings

word0: My
word1: Elephant
word2: Sings

如果您有进一步的问题,请告诉我--并考虑用fgets()来阅读所有输入,一次读一行,避免scanf()个trap ……

C++相关问答推荐

在C中使用强制转换将uint16_t转换为uint8_t [2]是否有效?

核心转储文件中出现奇怪的大小变化

如何将常量char*复制到char数组

轮询libusb_pollfd struct 列表的正确方式是什么?

为什么此共享库没有预期的依赖项?

RawMotion的XInput2错误(具有较高值的XISelectEvents上的BadValue)

在移动数组元素时获得意外输出

在C++中父进程和子进程中的TAILQ队列同步问题

如何将大写/小写土耳其字母相互转换?

如何对现有的双向循环链表进行排序?

正在try 理解C++中的`正在释放的指针未被分配‘错误

UpDown控制与预期相反

如何不断地用C读取文件?

使用 strtok 多次分割一个字符串会导致意外行为

如何为avr atmega32微控制器构建C代码,通过光电二极管捕获光强度并通过串行通信传输数据

System V 消息队列由于某种原因定期重置

C/C++编译器可以在编译过程中通过按引用传递来优化按值传递吗?

如何修复数组数据与列标题未对齐的问题?

为什么 C 字符串并不总是等同于字符数组?

无法在 C 中打开文本文件,我想从中读取文本作为数据并将其写入数组