检查用户输入数组是否太长?

时间:2013-12-30 16:45:18

标签: c

我让用户输入4个号码。它们可以输入:1 2 3 4或1234或1 2 34等,我目前正在使用

int array[4];
scanf("%1x%1x%1x%1x", &array[0], &array[1], &array[2], &array[3]);

但是,如果用户输入太多数字,我想显示错误:12345或1 2 3 4 5或1 2 345等。

我该怎么做?

我是C的新手,所以请尽可能多地解释。

//

感谢您的帮助。 我现在要做的是:

char line[101];
    printf("Please input);
    fgets(line, 101, stdin);
    if (strlen(line)>5)
    {
        printf("Input is too large");
    }
    else
    {
        array[0]=line[0]-'0'; array[1]=line[1]-'0'; array[2]=line[2]-'0'; array[3]=line[3]-'0';
        printf("%d%d%d%d", array[0], array[1], array[2], array[3]);
    }

这是一种明智且可接受的方式吗?它编译并似乎适用于Visual Studios。它会在C上编译并运行吗?

6 个答案:

答案 0 :(得分:1)

您的问题可能是特定于操作系统的。我假设它可能是Linux。

如果您接受为输入行大小设置上限,则可以先使用getline(3)(或readline(3),或甚至fgets(3)读取整行,然后解析该行(例如,使用sscanf(3)并使用%n格式说明符)。不要忘记测试sscanf的结果(读取项目的数量)。

所以也许像

int a=0,b=0,c=0,d=0;
char* line=NULL;
size_t linesize=0;
int lastpos= -1;
ssize_t linelen=getline(&line,&linesize,stdin);
if (linelen<0) { perror("getline"); exit(EXIT_FAILURE); };
int nbscanned=sscanf(line," %1d%1d%1d%1d %n", &a,&b,&c,&d,&lastpos);
if (nbscanned>=4 && lastpos==linelen) {
  // be happy
  do_something_with(a,b,c,d);
}
else {
  // be unhappy
  fprintf(stderr, "wrong input line %s\n", line);
  exit(EXIT_FAILURE);
}
free(line); line=NULL;

一旦你拥有了整行,你就可以通过其他方式解析它,比如连续调用strtol(3)

然后,问题是如果 stdin 有多行,会发生什么。在这种情况下,我猜不出你想要什么。也许feof(3)是相关的。

我认为我的解决方案可能不是特定于Linux的,但我不知道。它可能适用于Posix 2008兼容的操作系统。

拥有sscanf转化规范时,请注意%n的结果。该手册页告诉标准可能在那个角落案例中是矛盾的。

如果您的操作系统不符合Posix(例如Windows),那么您应该找到另一种方法。如果您接受将线路尺寸限制为例如128你可以编码

char line[128];
memset (line, 0, sizeof(line));
fgets(line, sizeof(line), stdin);
ssize_t linelen = strlen(line);

然后你会附加前一个(即第一个)代码块的sscanf和后续代码(但没有最后一行调用free(line))。

答案 1 :(得分:1)

OP处于正确的轨道上,但需要进行调整以处理错误。

使用scanf()的当前方法可用于检测问题,但无法很好地恢复。相反,请使用fgets()/sscanf()组合。

char line[101];
if (fgets(line, sizeof line, stdin) == NULL) HandleEOForIOError();
unsigned arr[4];
int ch;
int cnt = sscanf(line, "%1x%1x%1x%1x %c", &arr[0], &arr[1], &arr[2],&arr[3],&ch);
if (cnt == 4) JustRight();
if (cnt < 4) Handle_TooFew();
if (cnt > 4) Handle_TooMany();  // cnt == 5 

ch在4个数字后捕获任何潜伏的非空白char
如果在%1u中查找1位十进制数字,请使用unsigned 如果在%1d中查找1个十进制数字,请使用int


OP第二种方法array[0]=line[0]-'0'; ...,不错,但有一些缺点。它不执行良好的错误检查(非数字)也不像第一个那样处理十六进制数字。此外,它不允许引导或散布空间。

答案 2 :(得分:0)

您要获得的是4位数字,它们之间有或没有空格。为此,您可以将字符串作为输入,然后逐个字符检查该字符串并计算字符串中的数字位数(以及空格和其他字符),并执行所需的操作/显示所需的消息。

答案 3 :(得分:0)

你不能用scanf做到这一点。问题是,有一些方法可以让scanf搜索4个数字之后的某些内容,但是如果用户没有输入更多数字,它们将只是坐在那里等待更多的用户输入。所以你需要使用gets()或fgets()并解析字符串来做到这一点。

答案 4 :(得分:0)

你可能更容易改变你的程序,所以你一次要求一个数字 - 然后你问了4次,你已经完成了它,所以这些内容,伪代码:

i = 0
while i < 4
ask for number
scanf number and save in array at index i

答案 5 :(得分:0)

E.g

#include <stdio.h>

int main(void){
    int array[4], ch;
    size_t i, size = sizeof(array)/sizeof(*array);//4  

    i = 0;
    while(i < size){
        if(1!=scanf("%1x", &array[i])){
             //printf("invalid input");
             scanf("%*[^0123456789abcdefABCDEF]");//or "%*[^0-9A-Fa-f]"
        } else {
            ++i;
        }
    }
    if('\n' != (ch = getchar())){
        printf("Extra input !\n");
        scanf("%*[^\n]");//remove extra input
    }
    for(i=0;i<size;++i){
        printf("%x", array[i]);
    }
    printf("\n");
    return 0;
}