如何管理用户的输入数据?

时间:2017-12-31 01:53:19

标签: c

我想了解一些帮助,了解如何在C程序中输入数据。到目前为止,我使用了java语法,方便try {} catch(){};条款,但我没有在C上看到它(或者我没有找到它?)。

假设我有以下数组;

float f_array[10];

通常我输入数据我要么使用scanf(...);或者我可以从中读取输入的文件,但为了简单起见,我们假设我使用scanf(...);

我有以下内容;

int i;
for(i = 0; i<10; i++){
    scanf("%f", &f_array[i]);
}

现在,我的问题是如何限制用户输入字符或字符串或错误的数据类型?另外,我应该在实际将值放入其中之前尝试初始化数组吗?

3 个答案:

答案 0 :(得分:1)

请注意scanf()返回成功读取的元素数,您可以查看它:

int success = scanf(...);
if (!success) {
    scanf("%*[^\n]%*c"):
    // OR while(getchar() != '\n');
}
然而,有一个复杂的解决方案。您不能使用scanf(),而是编写一个自定义输入法来处理击键并过滤掉无效字符,可能使用getch()(Windows / nCurses)。这是一个最小化的Windows版本:

void readFloat(float* in){
    int ch, ind = 0;
    char buf[100];
    while (1){
        ch = getch();
        if (ch >= '0' && ch <= '9' || ch == '.') {
            buf[ind++] = (char)ch;
            putchar(ch);
        }
        else if (ch == 8) /* Backspace */ {
            printf("\b \b");
            ind --;
        }
    }
    buf[ind] = '\0';
    float ret;
    sscanf(buf, "%f", &ret);
    return ret;
}

代码的可能结果是:

用户输入(按键):123aaa.bbb456
程序过滤器(显示在屏幕上):123.456
返回值:(float)123.456

答案 1 :(得分:0)

  

现在,我的问题是如何限制用户输入字符或字符串或错误的数据类型?

如果没有专用硬件支持(例如,使用没有字母键的键盘,或某些设备会让用户受到电击以阻止他们点击'A'键),则无法限制用户输入不需要的数据。

相反,您需要使用ASSUMPTION编写代码,用户将输入无效或格式不正确的数据,并应对此问题。如果你能够假设一个只提供正确输入的顺从且易于处理的用户,那么你的代码确实更简单。但现实世界并非如此。

scanf() - 直接从stdin读取和解释数据实际上并不适用于这样的假设。来自scanf()的返回值可以指示事后的问题(例如,返回值是成功输入的字段数,或EOF)。但是,当出现问题时,scanf()会以您无法控制的方式处理它。假设你的代码有一个

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

,用户点击'X'后跟Enter键。 scanf()将识别'X'字符正在等待阅读,并立即返回。它返回的值不是1(这表示成功)。更糟糕的是,'X'将被后续调用scanf()读取,同样会再次发生(除非指定了不同的格式)。这意味着,如果您以这种方式在循环中调用scanf(),则会反复发生这种情况。

有些人会告诉您只需找到一种方法来阅读和丢弃角色'X'。这种方法的问题在于,用户有很多方法输入错误的输入,您需要考虑所有这些输入。如果用户做了你(或你的代码)没想到的事情,你会遇到问题(例如,程序挂起等待相同的输入重复,输入被用作数据,如果没有)。你回到了起步的地方。

更健壮的方法是简单地读取一行输入,并在尝试从中提取浮点值之前进行检查,例如

  char buffer[20];
  int got_one = 0;
  while (!gotone && fgets(buffer, sizeof buffer, stdin) != NULL)
  {
       if (check_string(buffer))
       {
            if (sscanf(buffer, "%f", &f_array[i]) == 1)
            {
                /*  yay - we got a floating point value */

                got_one = 1;
            }
            else
            {
                fprintf(stderr, "Floating point scanning failed.  Try again\n");
            }
       }
       else
       {
             fprintf(stderr, "Bad data discarded.  Try again\n");
       }
  }

基本上,这提供了几个钩子,因此您可以通过各种方式检查用户输入。如果你愿意,它可以适用于丢弃一部分线,并扫描左边的有用数据。

然而,关键是代码不会假设用户表现良好。它只会在经过一次检查后尝试读取浮点值,并且如果读取失败仍会处理。

该代码还可以用于处理输入溢出缓冲区的数据的用户(例如,在一行中输入30个浮点字符)。我会把它留作练习。

  

另外,我是否应该在实际将值放入其中之前尝试初始化数组?

这取决于您的代码的需求,但一般来说我不会打扰。

使用我上面建议的方法,您可以避免使用数组(或数组元素)的情况,除非实际放入了有效数据。

所有初始化数组的工作都是模糊的情况,其中输入的代码(从用户读取)没有正确处理错误的用户输入。

答案 2 :(得分:0)

  1. 根据每个输入向用户提供一些反馈。
  2. 处理每个输入并允许用户随时进行更正。
  3. 使用&#34; atof()&#34;做转换,但它有几个怪癖:
    它通过返回0.0的值告诉您有错误 如果/当它找到一个无效的char并且返回它到那个点时的内容,它就会停止处理
    例如。 6.35k给出6.35 - 这通常可以正常工作; 否则你必须自己检查无效的字符。

    试试这个

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main () {
    float f_array[10];
    int   i;
    float input_value;
    char  temp_string[32];
    
    for(i = 0; i<10; i++){
        printf("input a floating point number: ");
        scanf("%s",&temp_string[0]);
        input_value = atof(temp_string);
        while(input_value == 0.0) {
            printf("%s is not a valid floating point number\n");
            printf("example is 5.6 or 1e32 or 17\n");
            printf("try again - input a floating point number: ");
            scanf("%s",&temp_string[0]);
            input_value = atof(temp_string);
        }
        f_array[i] = input_value;
        printf("String value = %s, Float value = %f\n", temp_string, input_value);
    }
    /* use the data */
    for(i = 0; i<10; i++){
        printf("%f\n",f_array[i]);
        /* do something */
    }
    }