【问题标题】:Protect against invalid array input in loop防止循环中的无效数组输入
【发布时间】:2018-11-05 09:42:08
【问题描述】:

在输入无效的情况下保护程序的问题与编程一样古老,我在这个网站上发现了很多关于此的问题,但对我的情况没有任何帮助。

我有一个函数可以将值加载到浮点二维数组中。

void load_val(
                     float matrix[MAX_SIZE][MAX_SIZE],
                     const int line_num,
                     const int column_num
                     )
{
    for (int i=0; i<line_num; ++i)
    {
        printf("Give number\n");
        for (int j=0; j<column_num; ++j)
        {
            scanf("%f", &matrix[i][j]);
        }
    }

}

显然,当用户输入一个字母时,程序会进入一个无限循环。 我对这个问题使用了两种解决方案,但都没有奏效。 第一个是使用 scanf 在输入无效时返回 0 的事实。

所以不是

scanf("%f", &matrix[i][j]);

我写的

while (scanf("%f", &matrix[i][j])==1);

但它仍然给我一个无限循环。

另一种解决方案只是使用"isdigit" 函数。

int h = scanf("%f", &matrix[i][j]);
            if (isdigit(h)==0)
            {
                puts("INVALID");
                j--;
            }

但我真的不想使用其他库,它也不起作用。 问题似乎是,在我检查输入是否有效之前,程序就因为输入而发疯了。

我什至试过这个

float h;
if (scanf("%f", &h)==1)
       {
          matrix[i][j]=h;
       }
else
       {
          puts("INVALID");
          j--;
       };

仍然 - 无限循环。 如何在程序发疯之前检查此loop-inside-a-loop 中的无效输入?可能是浮点类型的问题吗?

【问题讨论】:

  • 使用fgets 获取字符串中的输入。然后解析字符串以检查浮点数。如果你得到一个不需要的字符,你可以跳过它,或者警告用户。
  • 在不相关的说明中,您对isdigit 的使用可能是错误的。特别是因为您似乎知道 scanf 返回什么。它也是一个标准的 C 函数,因此不会使用“其他库”。

标签: c arrays input


【解决方案1】:

问题在于,当您提供无效输入时,scanf 不会将其从输入缓冲区中删除。每次您在循环中调用 scanf 时,它都会一遍又一遍地读取相同的输入。

因此通常建议您使用fgets 读取整行,然后使用sscanf 解析该行。

然后检查scanf(或sscanfreturns 是检查它是否成功的正确方法。

【讨论】:

    【解决方案2】:

    fscanf():

    对于除 n 之外的每个转换说明符,最长的输入字符序列不超过任何指定的字段宽度,并且要么正是转换说明符所期望的,要么是它所期望的序列的前缀,是从流。 在这个消费序列之后的第一个字符(如果有的话)保持未读。 如果消费序列的长度为零,或者如果消费序列不能按上面指定的方式转换,则匹配失败,除非文件结束、编码错误或读取错误阻止了来自流的输入,在这种情况下是输入失败。

    因此,如果 scanf() 不能使用所有(或任何)字符,它们将保留在输入流中,并且下一个 scanf() 将像第一个一样失败,依此类推。

    为防止这种情况发生,您可以从输入流中读取并丢弃字符,直到遇到换行符:

    float value;
    if(scanf("%f", value) != 1) {
        int ch;
        while((ch = getchar()) != EOF && ch != '\n');
    }
    

    【讨论】:

      【解决方案3】:

      如果scanf 遇到与输入格式不匹配的字节,那么这些字节将仅留在输入流中。重复调用scanf 只会卡在相同的无效字符上。如果您想处理无效输入,最好将所有可用输入读入缓冲区(例如使用fgets),然后在缓冲区上使用sscanf,可能在一个循环中,以便您可以将缓冲区指针推进到无效输入。见https://stackoverflow.com/a/5969401/982257

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 2021-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-08
        相关资源
        最近更新 更多