C:scanf输入单字符和验证

问题描述 投票:0回答:5

我在C中验证单字符scanf输入时遇到问题,我找不到现有的解决方案...

方案是:方法采用单字母'char'类型输入,然后验证此输入,如果不符合条件,则弹出错误消息并重新输入,否则返回此字符值。

我的代码是:

char GetStuff(void)
{
    char c;
    scanf("%c", &c);
    while(c != 'A' || c != 'P')
    {
          printf("invalid input, enter again (A for AM or P for PM): ");
          scanf ("%c", &dtChar);
    }
    return c;
}

然而,无论我输入什么输入,我都得到了无限循环的错误消息。我读了一些其他帖子并猜测%c说明符在我输入时没有自动摆脱换行的问题,到目前为止我有尝试:

  1. 在%c之前/之后放置一个空格,如: scanf(" %c", &c);
  2. 写一个单独的方法或包含在这个GetStuff方法中清理换行符,如: void cleanBuffer(){ int n; while((n = getchar()) != EOF && n != '\n' ); }

有谁能帮我解决这个问题吗?先感谢您。

c scanf
5个回答
1
投票
#include <stdio.h>

char GetStuff(void) {
    char c;
    scanf("%c", &c);
    getchar();
    while ((c != 'A') && (c != 'a') && (c != 'P') && (c != 'p')) {
        printf("invalid input, enter again (A for AM or P for PM): ");
        scanf ("%c", &c);
        getchar();
    }
    return c;
}

int main(void) {
    printf("Calling GetStuff()...\n");
    char x = GetStuff();
    printf("User entered %c\n", x);
    return 0;
}

您使用while (c != 'A' || c != 'P')作为循环条件,但这将始终返回true。您打算使用的是&&“和”运算符,而不是|| “或”运营商。

另外,在scanf语句之后调用getchar()来捕获换行符。这应该按照你想要的方式工作。


1
投票

在内部循环中,你在dtChar中输入,但你的循环条件检查变量c,它在循环中没有更新,这导致无限循环

你也会改变你的状况

while(c != 'A' || c != 'P')

while(c != 'A' && c != 'P') 

如果您希望用户输入“A”或“P”


1
投票

请考虑以下代码段:

#include <stdio.h>
#include <ctype.h>

char GetStuff(void)
{
    char c;
    do {
          printf("Please enter A for AM or P for PM: ");
          scanf ("%c", &c);
          // clean input buffer (till the end of line)
          while(getchar()!='\n');
    } while(toupper(c) != 'A' && toupper(c) != 'P');
    return c;
}

int main(void)
{
    printf("Your input is'%c'\n", GetStuff());
    return 0;
}

注意要点:

  • 条件while(c != 'A' || c != 'P')将永远为真(因为一个字符不能同时是'A'和'P'),所以使用while(c != 'A' && c != 'P')代替
  • 如果你使用scanf循环,不需要两个do..while
  • 使用scanf输入字符后,建议清除缓冲区中的所有字符,例如与while(getchar()!='\n');(这将清除所有输入,包括不正确和冗余字符)
  • 使用toupper避免进行4比较(实际上单个c=toupper(c)内循环可以最小化你的时间为while(c != 'A' && c != 'P')

更新:

添加消息“无效输入”并添加一些其他有用的改进...新代码如下:

#include <stdio.h>
#include <ctype.h>

void CleanBuffer(){
    int n;
    while((n = getchar()) != EOF && n != '\n' );
}

char GetStuff(void)
{
    char c;
    do {
          printf("Please enter A for AM or P for PM: ");
          scanf (" %c", &c);
          c = toupper(c); // here letter become uppercase
          CleanBuffer();
    } while( (c != 'A' && c != 'P')?printf("Invalid input! "):0 );
    return c;
}

int main(void)
{
    printf("You have entered: %c\n", GetStuff());
    return 0;
}

注意:函数将以大写形式返回“A”或“P”,因此如果不需要,请在更新之前更改代码(使用两个toupper,并且不要在c之后更改scanf)。你也可以使用tolower作为选项(当然与'a''p'比较)。


0
投票

另一种可能的解决正如其他人提到的那样,条件是用&&完成的。无论如何,最大的问题是如何删除控制台输入线上剩下的内容。由于控制台按行工作,我们删除所有内容到下一个'\n'。如果用户在调用GetStuff()之前已经在输入行上留下了某些内容,那么在while循环之前添加对SkipRestOfTheLine()的调用会很有用。

一般来说,我建议先使用while(1)循环,然后再使其更好(例如在你发布的cleanBuffer()中)。

#include <stdlib.h>
#include <stdio.h>

void SkipRestOfTheLine(void)
{
    while (1) {
        int c = fgetc(stdin);
        if (c == EOF || c == '\n')
            break;
    }
}

char GetStuff(void)
{
    while (1) {
        int c = fgetc(stdin);
        if (c == EOF)
            exit(EXIT_FAILURE); // Deal with this case in an appropriate way
        if (c == 'A' || c == 'P')
            return c;
        printf("invalid input, enter again (A for AM or P for PM): ");
        SkipRestOfTheLine();
    }
}

int main(void)
{
    char c = GetStuff();
    return 0;
}

-1
投票

试试这个,

   char GetStuff(void)
    {
        char c;
        scanf("%c", &c);
        while (((c != 'A') || (c != 'a')) && ((c != 'P') || (c != 'p'))==1)
        {
              printf("invalid input, enter again (A for AM or P for PM): ");
              scanf ("%c", &dtChar);
        }
        return c;
    }

我希望这可行,有一段时间因为没有给出适当的支架,它会卡在循环中。

© www.soinside.com 2019 - 2024. All rights reserved.