我想了解一些帮助,了解如何在C程序中输入数据。到目前为止,我使用了java语法,方便try {} catch(){};条款,但我没有在C上看到它(或者我没有找到它?)。
假设我有以下数组;
float f_array[10];
通常我输入数据我要么使用scanf(...);或者我可以从中读取输入的文件,但为了简单起见,我们假设我使用scanf(...);
我有以下内容;
int i;
for(i = 0; i<10; i++){
scanf("%f", &f_array[i]);
}
现在,我的问题是如何限制用户输入字符或字符串或错误的数据类型?另外,我应该在实际将值放入其中之前尝试初始化数组吗?
答案 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)
使用&#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 */
}
}