126

在C中:我试图从用户那里获取char,scanf当我运行它时,程序不要等待用户输入任何东西......

这是代码:

char ch;
printf("Enter one char");
scanf("%c", &ch);
printf("%c\n",ch);

为什么不工作?

4

11 回答 11

283

转换说明%c符不会自动跳过任何前导空格,因此如果输入流中有一个杂散的换行符(例如来自前一个条目),scanf调用将立即使用它。

解决此问题的一种方法是在格式字符串中的转换说明符之前放置一个空格:

scanf(" %c", &c);

格式字符串中的scanf空格表示跳过前导空格,第一个非空格字符将使用%c转换说明符读取。

于 2012-11-24T16:31:02.577 回答
31

首先,避免scanf()。使用它不值得痛苦。

见:为什么大家都说不要用scanf?我应该改用什么?

使用空白字符scanf()会忽略输入流中剩余的任意数量的空白字符,如果您需要读取更多输入怎么办?考虑:

#include <stdio.h>

int main(void)
{
   char ch1, ch2;

   scanf("%c", &ch1);  /* Leaves the newline in the input */
   scanf(" %c", &ch2); /* The leading whitespace ensures it's the
                          previous newline is ignored */
   printf("ch1: %c, ch2: %c\n", ch1, ch2);

   /* All good so far */

   char ch3;
   scanf("%c", &ch3); /* Doesn't read input due to the same problem */
   printf("ch3: %c\n", ch3);

   return 0;
}

虽然可以使用前导空格以相同的方式修复第三个 scanf() ,但它并不总是像上面那样简单。另一个主要问题是,scanf()如果输入流中的任何输入与格式不匹配,则不会丢弃它。例如,如果您输入abc一个int诸如:scanf("%d", &int_var);那么abc将不得不读取并丢弃。考虑:

#include <stdio.h>

int main(void)
{
    int i;

    while(1) {
        if (scanf("%d", &i) != 1) { /* Input "abc" */
            printf("Invalid input. Try again\n");
        } else {
            break;
        }
    }

    printf("Int read: %d\n", i);
    return 0;
}

另一个常见问题是混合scanf()fgets(). 考虑:

#include <stdio.h>

int main(void)
{
    int age;
    char name[256];
    printf("Input your age:");
    scanf("%d", &age); /* Input 10 */
    printf("Input your full name [firstname lastname]");
    fgets(name, sizeof name, stdin); /* Doesn't read! */
    return 0;
}

调用fgets()不等待输入,因为读取了前一个 scanf() 调用留下的换行符,并且 fgets() 在遇到换行符时终止输入读取。

还有许多其他与scanf(). 这就是为什么通常建议避免使用它的原因。

那么,有什么选择呢?以下列方式使用fgets()函数来读取单个字符:

#include <stdio.h>

int main(void)
{
    char line[256];
    char ch;

    if (fgets(line, sizeof line, stdin) == NULL) {
        printf("Input error.\n");
        exit(1);
    }

    ch = line[0];
    printf("Character read: %c\n", ch);
    return 0;
}

如果 inut 缓冲区中有足够的空间,使用时要注意的一个细节fgets()将读取换行符。如果不需要,则可以将其删除:

char line[256];

if (fgets(line, sizeof line, stdin) == NULL) {
    printf("Input error.\n");
    exit(1);
}

line[strcpsn(line, "\n")] = 0; /* removes the trailing newline, if present */
于 2016-12-03T15:02:48.383 回答
9

这对我有用 试试看

int main(){
char c;
scanf(" %c",&c);
printf("%c",c);
return 0;
}
于 2018-07-10T14:54:46.740 回答
5

这里有一个类似的东西,我想分享,

在使用 Visual Studio 时,您可能会收到如下错误:

'scanf':函数或变量可能不安全。考虑scanf_s改用。要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS

为防止这种情况,您应该按以下格式编写

单个字符可以按如下方式读取:

char c;
scanf_s("%c", &c, 1);

当读取非空终止字符串的多个字符时,整数用作宽度规范和缓冲区大小。

char c[4];
scanf_s("%4c", &c, _countof(c));
于 2015-01-13T08:46:28.143 回答
3

fgets 和 getchar 都不能解决这个问题。唯一的解决方法是在使用 scanf scanf(" %c",ch); 时在 %c 之前保留一个空格;// 只会工作

在以下 fgets 也不起作用..

char line[256];
char ch;
int i;

printf("Enter a num : ");
scanf("%d",&i);
printf("Enter a char : ");

if (fgets(line, sizeof line, stdin) == NULL) {
    printf("Input error.\n");
    exit(1);
}

ch = line[0];
printf("Character read: %c\n", ch);
于 2018-11-16T18:10:40.813 回答
1

尝试使用 getchar(); 反而

句法:

void main() {
    char ch;
    ch = getchar();
}
于 2017-10-01T15:29:32.160 回答
-1

在 scanf 放之前fflush(stdin);清除缓冲区。

于 2014-06-30T18:26:38.950 回答
-1

唯一对我有用的代码是:

scanf(" %c",&c);

我遇到了同样的问题,而且只有单个字符。经过一个小时的随机测试,我还不能报告问题。有人会认为 C 现在将具有从键盘检索单个字符的防弹功能,而不是一系列可能的变通办法......只是说......

于 2019-08-06T04:41:53.390 回答
-2

使用字符串而不是char 喜欢

char c[10];
scanf ("%s", c);

我相信它很好用。

于 2016-06-22T16:47:21.253 回答
-3

在 %c 转换说明符之前提供一个空格,以便编译器忽略空格。程序可以写成如下:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char ch;
    printf("Enter one char");
    scanf(" %c", &ch); /*Space is given before %c*/
    printf("%c\n",ch);
return 0;
}
于 2014-10-11T15:03:02.633 回答
-3

您必须使用有效的变量。ch不是该程序的有效变量。使用char Aaa

char aaa;
scanf("%c",&Aaa);

经过测试,它可以工作。

于 2018-12-17T01:01:41.860 回答