防止循环中无效的数组输入

时间:2018-11-05 09:42:09

标签: c arrays input

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

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

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中的无效输入?浮点类型可能有问题吗?

3 个答案:

答案 0 :(得分:3)

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

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

检查scanf(或sscanfreturns 是什么是检查其成功与否的正确方法。

答案 1 :(得分:2)

fscanf()

  

对于除n以外的每个转换说明符,最长的输入字符序列不超过任何指定的字段宽度,而该长度恰好是转换说明符所期望的或者是它所期望的序列的前缀,是从流。 此消费序列后的第一个字符(如果有)仍未读取。如果消费序列的长度为零或无法按上述指定转换消费序列,则除非文件结尾,否则匹配失败,编码错误或读取错误阻止了来自流的输入,在这种情况下,这是输入失败。

因此,如果scanf()无法使用所有(或任何)字符,它们将保留在输入流中,而下一个scanf()将以第一个字符失败的方式失败,依此类推。

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

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

答案 2 :(得分:1)

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

相关问题