【问题标题】:C Programming - Allow / determine / check "space (&#32)" input in integerC 编程 - 允许/确定/检查整数输入的“空格 (&#32)”
【发布时间】:2016-07-13 15:39:07
【问题描述】:

首先,对不起我的英语不好,好的,请转到上面的这个问题。我在许多网站上浏览了很多关于这个问题的参考资料,但我还没有找到正确的答案。

我正在尝试制作一个 C 程序,该程序可以确定用户是否输入整数,如果用户没有输入整数,则程序重试提示用户输入整数等等。当我在条件语句上使用 scanf() 返回值时一切正常,但问题是,当用户输入“空白/空白/空格”(在 ascii 代码上为 )并按“输入”时,我的程序只是保持运行等待用户输入一些字符或整数。

我只是希望如果输入是'whitespace/blackspace/space',程序会重复提示用户输入一个整数或程序停止。

这是案例代码:

#include <stdio.h>

int main() {

    int number, isInt;

    printf("Input a number : ");

    do {
        if ((isInt = scanf("%d", &number)) == 0) {
            printf("retry : ");
            scanf("%*s");
        } else if (number < 0) {
            printf("retry : ");
        }
    } while (isInt == 0 || number < 0); 

    printf("%d\n", number);

    return 0;
}

我是 C 的新手,对此感到好奇。我知道如果我使用 %[^\n]

请帮我打破我的好奇心,问候:D

【问题讨论】:

标签: c whitespace space


【解决方案1】:

scanf 将忽略空格并继续查找,直到找到非空格,然后再尝试进行转换。

我建议使用 fgets 获取一行输入,然后使用 sscanf 处理。像这样的:

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

int main() {    
    int number=-1;    
    printf("Input a number : ");
    do {
        char line[80];
        if(!fgets(line,sizeof(line),stdin)){
            printf("line read error\n");
            exit(1);
        }
        if (sscanf(line,"%d", &number) !=1) {
            printf("retry : ");
        } else if (number < 0) {
            printf("retry : ");
        }
    } while ( number < 0); 
    printf("%d\n", number);
    return 0;
}

【讨论】:

  • scanf( "%*s" ) 调用不是未定义的,因为存在分配抑制字符*;它将读取但不尝试分配下一个输入字符串。
  • 我的错误...修复
  • 这是我想要的答案,正好解决了我的好奇心问题。谢谢兄弟(y)!
【解决方案2】:

格式说明符“%*s”在遇到空格(制表符、空格、换行符)时将停止输入字符,因此如果用户输入任何这些字符,它们将不会被使用。

“%d”将占用所有此类前导空白。

当用户输入一些“有效”数字时,代码将直接进入“else”语句

当用户输入一些 ascii 值,例如 'a' 时,'%d' 将完成输入,代码将直接进入 'else' 语句。 那时,'number'变量将不会被设置 所以“数字”将包含碰巧在“数字”变量所在的堆栈上的每个垃圾。 那个“可能”恰好是一个大于 0 的整数。

'scanf()' 调用返回的值可以是 0 或 1 以外的值,例如 EOF

“退格”将被终端驱动程序使用,因此永远不要访问程序。

所以你的程序完全符合预期,但可能不是你想要的。

【讨论】:

    【解决方案3】:

    %s 将跳过任何前导空格,然后读取 -空格字符,直到它再次看到空格。因此,scanf( "*%s" ); 调用将阻塞,直到它看到至少一个非空白字符。

    %[ 转换说明符不会跳过任何前导空格,因此这可能是可接受的替代:

    scanf( "%*[^\n]" );
    

    这在一个快速而肮脏的测试中“有效”,虽然老实说更好的方法是将所有输入读取为文本,然后使用strtol 将文本转换为目标类型。这是我的意思的一个工作示例:

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    
    #define BUF_SIZE 20
    
    int main( void )
    {
      int value = -1;
      char buf[BUF_SIZE];
    
      do
      {
        printf( "Gimme a non-negative value: " );
        if ( fgets( buf, sizeof buf, stdin ) )
        {
          char *newline = strchr( buf, '\n' );
          if ( !newline )
          {
            printf( "Input too long for buffer, flushing..." );
            while ( fgets( buf, sizeof buf, stdin ) && !strchr( buf, '\n' ) )
              ;
            printf( "try again\n" );
          }
          else
          {
            *newline = 0; // Remove the newline character from the buffer
    
            char *chk;    // chk will point to the first character *not* converted
                          // by strtol.  If that character is anything other
                          // than 0 or whitespace, then the input string was
                          // not a valid integer.
    
            int tmp = (int) strtol( buf, &chk, 0 );
            if ( *chk != 0 && !isspace( *chk ) )
            {
              printf( "%s is not a valid integer, try again\n", buf );
            }
            else if ( tmp < 0 )
            {
              printf( "%d is negative, try again\n", tmp );
            }
            else
            {
              value = tmp;
            }
          }
        }
        else
        {
          printf( "Input failure, bailing out completely\n" );
          break;
        }
      } while ( value < 0 );
    
      printf( "value is %d\n", value );
      return 0;
    }
    

    下面是一个运行示例,对每个测试用例进行了练习:

    $ ./format2
    Gimme a non-negative value: Supercalifragilisticexpealidocious
    Input too long for buffer, flushing...try again
    Gimme a non-negative value: 123fgh
    123fgh is not a valid integer, try again
    Gimme a non-negative value: -12345
    -12345 is negative, try again
    Gimme a non-negative value: 1234
    value is 1234
    

    为了测试fgets失败,我输入Ctrl-d发送EOF:

    $ ./format2
    Gimme a non-negative value: Input failure, bailing out completely
    value is -1
    

    【讨论】:

    • 很酷的答案,兄弟,谢谢你的帮助,要把这个放到我的好奇心图书馆(y)!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多