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

问题描述 投票:0回答:3

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

假设我有以下数组;

float f_array[10];

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

我有以下几点;

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

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

c
3个回答
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个浮点字符)。我会把它留作练习。

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

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

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

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


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


0
投票
  1. 在每个输入的基础上给用户一些反馈。
  2. 处理每个输入并允许用户随时进行更正。
  3. 使用“atof()”进行转换,但它有几个怪癖: 它通过返回值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 */ } }
© www.soinside.com 2019 - 2024. All rights reserved.