【问题标题】:C How to ignore empty lines in user input?C 如何忽略用户输入中的空行?
【发布时间】:2023-03-29 17:23:02
【问题描述】:

这是我当前的代码:

int num = 0;
char c = '#';

scanf("%d",&num);
do{
    for (int i=0;i<num;i++){
        printf("%c",c);
    }
    printf("\n");
}
while (scanf("%d", &num) == 1);

如果用户不输入任何内容,我将如何让程序不会吐出换行符?

感谢您的帮助,谢谢!

【问题讨论】:

  • 嗯,你所谓的“空”,我会只调用"\n"的输入并将输入的想法保存为""
  • %d of scanf 将忽略(跳过)前面的换行符(空格)。
  • 如果用户在任何数字之前点击^D(或Windows 上的^Z),上述程序将打印一个换行符。 OP 不想要输出。将 do / while 逻辑替换为简单的 while 循环。
  • @WorldSEnder:你的回答很完美。 MartinZabel 忽略了文件结尾的情况,他的评论没有指向真正的问题。

标签: c


【解决方案1】:

此代码应该适用于您想要做的事情:

#include <stdio.h>

int main()
{
    int num = 0;
    char c = '#';
    char readLine[50];

    while ((fgets(readLine, sizeof readLine, stdin) != NULL) && sscanf(readLine, "%d", &num) == 1)
    {
        for (int i=0;i<num;i++){
                printf("%c",c);
        }
        printf("\n");
        fflush(stdout);
    }
    return 0;
}

此代码的行为如下: fgets 将读取您在标准流 (stdin) 中输入的任何内容,并将其放入 readLine 数组中。然后程序将尝试读取您的 readLine 变量中的数字,并使用 sscanf 函数将其放入您的 num 变量中。如果读取了一个数字,程序将执行您在问题中出现的行为(写入 # 字符“num”次),然后返回循环的开头。如果读取的不是数字,则循环停止。

【讨论】:

  • 您没有忽略空行,而是在空行处停止程序。删除 &amp;&amp; (readLine[0] != '\n') 将解决此问题。反正也不需要。
【解决方案2】:

一般来说,避免使用scanf。很容易在输入流上留下未处理的杂物。相反,阅读整行,然后使用sscanf(或其他东西)来处理它。这可以保证您不会被部分读取的行卡住,因为这些行很难调试。

我更喜欢 getlinefgets 来阅读行。 fgets 要求您猜测输入可能有多长,并且输入可能会被截断。 getline 将分配内存来读取行,以避免缓冲区溢出或截断问题。

注意:getline is it's not a C standard function, but a POSIX one 和相当新的(2008 年),尽管在此之前它是一个 GNU 扩展。一些较旧的编译器可能没有它。

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

int main()
{
    char c = '#';
    char *line = NULL;
    size_t linelen = 0;

    /* First read the whole line */
    while( getline(&line, &linelen, stdin) > 0 ) {
        /* Then figure out what's in it */
        long num = 0;
        if( sscanf(line, "%ld", &num) > 0 ) {
            for( int i = 0; i < num; i++ ) {
                printf("%c", c);
            }
            printf("\n");
        }
    }

    free(line);

    return 0;
}

if( sscanf(line, "%ld", &amp;num) &gt; 0 ) { 将通过检查匹配的内容数量来忽略与模式的任何部分不匹配的任何行,例如空白行或充满单词的行。但它仍会将0 作为有效输入处理。

$ ./test
foo
bar
foo123
12
############

1
#
0

2
##

我还将num 移动到循环内部,以保证每次迭代都会重新初始化它,并遵循将变量置于最小范围以避免干扰的一般原则。我将其升级为long int,以便更好地处理用户可能输入的不可预测的大量数字。

【讨论】:

    【解决方案3】:

    这是我多年来使用 fgets() 和 sscanf() 函数完成输入解析的方式。我写的 C++ 不多,如果我可以将代码保留在旧式 ansi C 中,那么我会这样做。 stdio.h 库中的 fgets 和 sscanf 函数是通用的,并且始终在任何平台上可用。

    对于用于读取任何内容的字符数组,我通常将 LINE_SIZE 设置为 256 或 512,即使我知道要读取的行通常为 80 个字符或更少。今天任何一台计算机都有超过 1GB 的 RAM,不必担心分配额外的 500 左右字节。显然,如果您不知道输入行有多长,那么您必须:

    猜猜LINE_SIZE应该设置成什么,不用担心

    或在调用 fgets() 后验证 line[] 中的换行符是否位于空字符之前。

    # include <stdio.h>
    
    # define LINE_SIZE  256
    
    int main ( int argc, char *argv[] )
    {
        FILE *fp;
        char line[LINE_SIZE];
        int nn;
        int value;
    
        fp = fopen( "somefile", "r" );
    
        fgets( line, LINE_SIZE, fp );
    
        /*
            this way to read from standard input (i.e. the keyboard)
            using fgets with stdin prevents compiler warning when using
            deprecated gets function
    
            fgets( line, LINE_SIZE, stdin );
        */
    
        if ( line[0] != '\n' )
        {
            /* definitely not a blank line */
    
            nn = sscanf( line, "%d", &num );
    
            if ( nn == 1 )
            {
                /* some number placed into num variable that met the
                   %d conversion for the sscanf function
                */
            }
        }
        return 0;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-14
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多