C语言如何从输入中获取字符串

use*_*033 2 c input

这是我尝试过的:

printf("Please venter first string\n");
char str[127];
scanf_s("%s", &str);
Run Code Online (Sandbox Code Playgroud)

并得到了这个例外:

在 strcmp.exe 中的 0x0FD2C700 (ucrtbased.dll) 处引发异常:0xC0000005:访问冲突写入位置 0x00500000。

我也试试这个:

printf("Please venter first string\n");
char str[127];
scanf_s("%d", &str);
Run Code Online (Sandbox Code Playgroud)

在这种情况下也不例外,但我得到了又长又奇怪的字符串。

Wea*_*ane 8

让我们从考虑标准的使用开始scanf。如果你写

scanf("%s", &str);
Run Code Online (Sandbox Code Playgroud)

那将是不正确的(尽管它可能有效)。将数组传递给函数时,它会衰减为指向第一个元素的指针,这是scanf需要的,因此该行应该是

scanf("%s", str);
Run Code Online (Sandbox Code Playgroud)

如果你想限制输入长度以防止缓冲区溢出,它可以是这样的(比数组长度少一个以允许nul终止符)

scanf("%126s", str);
Run Code Online (Sandbox Code Playgroud)

据称更安全功能scanf_s需要额外的大小参数来传递针对每个格式类型%c%s%[]这样的下一行(修正后&

scanf_s("%s", str);
Run Code Online (Sandbox Code Playgroud)

缺少那个参数,编译器应该发出警告。代码应该是

scanf_s("%s", str, sizeof str);
Run Code Online (Sandbox Code Playgroud)

但即使这样也是不够的。该Xscanf系列函数返回成功进入值的数量。由于用户(甚至我自己)在输入正确的输入(甚至可能是恶意的)方面是出了名的糟糕,因此您必须始终检查数据是否正确输入。如

if(scanf_s("%s", str, sizeof str) != 1) {
    // inform user and retry etc. etc.
}
Run Code Online (Sandbox Code Playgroud)

正如@chux 所提到的,最好通过 using 获取输入fgets,然后通过各种方式对其进行处理,例如sscanforstrtokstrsepor 对字符串进行更直接的分析。在这种情况下,使用sscanf,您可以多次尝试处理输入,但scanf只有一次机会。请注意strtokstrsep修改字符串,因此如果您需要多次尝试对其进行解码,则需要使用副本。


在你的第二个例子中

scanf_s("%d", &str);
Run Code Online (Sandbox Code Playgroud)

你得到了“除了一个又长又奇怪的字符串”,但你应该得到一个编译器警告:

警告 C4477:“scanf_s”:格式字符串“%d”需要“int 类型的参数,但可变参数 1 的类型为“char ( )[127]”

请注意,您没有初始化str为“空字符串”,如果您在输入错误后继续处理您认为是好的字符串,则可能会发生不好的事情。