为什么我的代码不适用于我的 VS 代码和代码块?
Why my code doesn't work with my VS Code, and Code Blocks?
我写了下面的C程序:
#include <stdio.h>
int main()
{
char d;
char e;
printf("Babanin adini gir. \n");
scanf("%s", &d);
printf("Ananin adini gir. \n");
scanf("%s", &e);
printf("Senin adin %c ya da %c", d, e);
return 0;
}
它在在线 C 编译器中工作得很好,但在我的 VSCode 或 Codeblocks 中却不行,它只说
Gimme a letter.
s
Gimme another letter.
a
Your letter is or a
像那样,它不读取第一个字母或打印它。
这是为什么?
当您说 char d;
时,您告诉编译器恰好保留一个字节的内存来保存一个字符。
然后当你说 char e;
时,你告诉编译器只保留一个字节的内存来保存另一个字符。
然后你说 scanf("%s", &d);
让编译器读取整个字符串(包括字符串终止符)并尝试将其存储在 char d;
保留的一个字节内存中
你输入的字符 运行 程序占用 space 的一个字节,字符串终止符占用另一个字节,所以现在你将两个字节的数据存储在一个只够大的地方一个字节。
然后为第二次 scanf 调用再次执行此操作。
所以现在您已经访问了您没有保留的内存 - 您可能已经覆盖了一些非常重要的东西。这是未定义的行为,任何事情都可能发生(包括使程序看起来好像在运行)
因此,如果您想像现在这样使用 char
变量,scanf("%s", &d);
应该是 scanf(" %c", &d);
并且其他 scanf 调用应该以相同的方式更改。
scanf
格式字符串需要以 space 开头的原因是告诉 scanf
函数它应该忽略 whitespace(就像换行符一样通过按回车键创建)。如果没有 space,第二个 scanf
将存储换行符作为其字符,因为这是输入的第二个字符。
您可能认为您还可以将变量更改为 char d[2];
和 char e[2];
,以便有空间存储字符和字符串终止符。但这是一个坏主意,因为如果用户在按下回车键之前输入了多个字符,您仍然会写到内存末尾。所以它有完全相同的问题。
您可以做的另一件事(如评论中所建议的那样)是根本不使用 scanf
来读取单个字符。如果您的变量是 char d;
那么您可以使用 d = getchar();
并且效果很好 - 但您仍然需要做一些事情来处理作为第二个字符出现的换行符。这就是为什么我认为 scanf(" %c", &d);
是使其工作的好、简单的方法。
还有一件事要注意:您应该始终检查所调用函数的 return 值。如果读取输入不起作用,您应该告诉用户输入无效,然后不要产生无效输出。
Jerry Jeremiah 的回答很好,但我只想补充一点,如果他的解决方案对您不起作用,您可能需要使用“%c”(带前导 space)而不是“%c”或第二个 scanf 将换行而不是第二个字母。
参考这个帖子:How to do scanf for single char in C
我写了下面的C程序:
#include <stdio.h>
int main()
{
char d;
char e;
printf("Babanin adini gir. \n");
scanf("%s", &d);
printf("Ananin adini gir. \n");
scanf("%s", &e);
printf("Senin adin %c ya da %c", d, e);
return 0;
}
它在在线 C 编译器中工作得很好,但在我的 VSCode 或 Codeblocks 中却不行,它只说
Gimme a letter.
s
Gimme another letter.
a
Your letter is or a
像那样,它不读取第一个字母或打印它。 这是为什么?
当您说 char d;
时,您告诉编译器恰好保留一个字节的内存来保存一个字符。
然后当你说 char e;
时,你告诉编译器只保留一个字节的内存来保存另一个字符。
然后你说 scanf("%s", &d);
让编译器读取整个字符串(包括字符串终止符)并尝试将其存储在 char d;
你输入的字符 运行 程序占用 space 的一个字节,字符串终止符占用另一个字节,所以现在你将两个字节的数据存储在一个只够大的地方一个字节。
然后为第二次 scanf 调用再次执行此操作。
所以现在您已经访问了您没有保留的内存 - 您可能已经覆盖了一些非常重要的东西。这是未定义的行为,任何事情都可能发生(包括使程序看起来好像在运行)
因此,如果您想像现在这样使用 char
变量,scanf("%s", &d);
应该是 scanf(" %c", &d);
并且其他 scanf 调用应该以相同的方式更改。
scanf
格式字符串需要以 space 开头的原因是告诉 scanf
函数它应该忽略 whitespace(就像换行符一样通过按回车键创建)。如果没有 space,第二个 scanf
将存储换行符作为其字符,因为这是输入的第二个字符。
您可能认为您还可以将变量更改为 char d[2];
和 char e[2];
,以便有空间存储字符和字符串终止符。但这是一个坏主意,因为如果用户在按下回车键之前输入了多个字符,您仍然会写到内存末尾。所以它有完全相同的问题。
您可以做的另一件事(如评论中所建议的那样)是根本不使用 scanf
来读取单个字符。如果您的变量是 char d;
那么您可以使用 d = getchar();
并且效果很好 - 但您仍然需要做一些事情来处理作为第二个字符出现的换行符。这就是为什么我认为 scanf(" %c", &d);
是使其工作的好、简单的方法。
还有一件事要注意:您应该始终检查所调用函数的 return 值。如果读取输入不起作用,您应该告诉用户输入无效,然后不要产生无效输出。
Jerry Jeremiah 的回答很好,但我只想补充一点,如果他的解决方案对您不起作用,您可能需要使用“%c”(带前导 space)而不是“%c”或第二个 scanf 将换行而不是第二个字母。
参考这个帖子:How to do scanf for single char in C