如何在C中为单个字符执行scanf

时间:2012-11-24 14:16:44

标签: c char scanf

在C中: 我正试图通过scanf从用户那里获取char,当我运行它时,程序不会等待用户键入任何内容......

这是代码:

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

为什么不工作?

12 个答案:

答案 0 :(得分:195)

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

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

scanf(" %c", &c);

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

答案 1 :(得分:14)

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

请参阅:Why does everyone say not to use scanf? What should I use instead?

使用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;
}

虽然可以使用前导空格以相同的方式修复第3个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 */

答案 2 :(得分:2)

fgets和getchar都不能解决问题。 唯一的解决方法是在使用scanf时在%c之前保留一个空格 scanf(“%c”,ch); //仅适用

在下面的fget中也无法使用。.

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

以下是我想分享的类似内容,

当您使用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));

此致

答案 5 :(得分:1)

这对我有用,请尝试

int main(){
char c;
scanf(" %c",&c);
printf("%c",c);
return 0;
}

答案 6 :(得分:0)

在%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;
}

答案 7 :(得分:0)

尝试使用getchar();代替

语法:

void main() {
    char ch;
    ch = getchar();
}

答案 8 :(得分:0)

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

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

经过测试,可以正常工作。

答案 9 :(得分:-2)

使用字符串代替char 喜欢

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

我相信它很好用。

答案 10 :(得分:-2)

唯一适用于我的代码是:

scanf(" %c",&c);

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

答案 11 :(得分:-4)

这适合我:

    #include <stdio.h>
    int main (void)
    {
        char a;
        scanf ("%c", &a);
        printf ("%c\n", a);
    return 0;
    }

不知道为什么你的代码不起作用。我使用Codelite和gcc