如何实现严格检查getInt()函数?

时间:2012-11-08 11:43:09

标签: c

我编写了以下代码来从键盘获取整数。 它将提示错误消息,直到您给出有效的整数值(负数或正数)。

一个条件是它必须检查每个可能的测试用例

像:

-3.2 
5.0
984237.4329
0.343
.434
12344.
adfs34
233adds
3892710492374329
helloIamNotainteger 

对于所有这些测试,它应该失败。它只会传递给int >=INT_MIN && int <=INT_MAX 值。

我的正在运行的代码是:

#include<stdio.h>
#include<limits.h>

int min=INT_MIN;
int max=INT_MAX;

int main()
{
        char str[50],c; //I have taken size 50 please ignore this 
        int check;
 do
 {
        int flag=1,i=0,j=0,num=0;
        check=0;
        printf("Enter an Integer : ");
        while((c=getchar())!='\n')
                str[i++]=c;
        if(str[0] == '-')
        {
                flag = -1;
                j++;
        }
        for(;j<i;j++)
        {
                if(str[j] >= '0' && str[j] <= '9')
                        num=(str[j]-'0') + num*10;
                else
                        break;

        }
        if(j<i)
        {
          printf("Not an Integer, Please input an integer \n");
        }
        else if(num < min || num >max)
        {
          printf("Integer is out of range,Please input an integer \n");
        }
        else
        {
                num *=flag;
                printf("The given number is : %d\n",num);
                check=1;
        }
 }while(check == 0);
        return 0;

}

一个例子:对于这样的价值。
83429439803248832409(它是整数但由于范围会失败)但它会传递并给出一些其他整数值。

如何在我的代码中解决此问题或更好地实现getInt()

5 个答案:

答案 0 :(得分:2)

最简单的方法是使用标准库函数。

#include <limits.h>
#include <stdlib.h>

int getInt (const char *s)
{
    long int n = strtol (s, NULL, 10);

    if (n < INT_MIN || n > INT_MAX)
        /* handle overflows */
    else
        return (int) n;
}

要处理其他错误,您可以使用多种条件。

#include <errno.h>

int getInt (const char *s, size_t size)
{
    const char *pEnd1 = s + size;
    char *pEnd2;
    long int n;

    errno = 0;

    n = strtol (s, &pEnd2, 10);

    if (n < INT_MIN || n > INT_MAX || errno != 0 || pEnd1 != pEnd2)
        /* error */
    else
        return (int) n;
} 

答案 1 :(得分:0)

嘿,你试图将一个大于32768的值存储到整数(非unsigned)中。因此,当您这样做时,它将显示存储变量中存在的一些垃圾值。如你所知,c中的整数有内存限制。像无符号类型的int数据类型可以存储0到65535之间的值。因此,尝试存储多于一个的数字将导致问题。如果需要存储更大的数字,请尝试使用long int数据类型。也许它可能有所帮助。但是该数据类型也具有内存限制,其值接近4lakh或其他值。

希望有所帮助。

答案 2 :(得分:0)

虽然这最适合作为对 Kirilenko 检查解决方案的评论,但我的说明会很长,所以我会将其作为答案发布。

会聚函数的主要问题是难以(strtol())不可能(atoi())来测试转换是否达到了预期的效果。

因此,当尝试使事情更可靠(如atoi())并且更易于使用(如strtol())时,将使用 Kirilenko 等解决方案。

无论如何, Omkant 提供的方法在转换中出现问题(从调用者的角度来看)时仍然会出现错误的设计错误。

所以接口最好像许多其他系统函数那样,将结果作为函数值返回:

/* 
 * Tryies to convert the first 'size' characters of 's' to an 'int' and optionally 
 * writes it to '*result'.
 * 
 * Returns the number of characters converted or any qualified negative error code
 * on failure.
 */
int getInt(
  const char * s,  /* source string to try to be converted to an integer */
  size_z size, /* number of digits to be converted (shall not be > strlen(s)) */
  int * result /* optional reference to an int to place the conversion result in */
);

并且,作为一个值得注意的副作用,通过传递NULL作为最后一个参数,能够简单地测试转换是否有效,并且另外一个人可以接收结果整数所需的位数。 / p>


然后仍然可以使用这个转换函数,就像它将结果作为函数值返回一样,在某些情况下可能会很方便,可能会使用以下宏:

GETINT(str, size, result, rc) \
  (rc = getInt(str, size, &result), result)

用法:

char s[] = "42";
int rc = 0;
int i = GETINT(s, 2, i, rc);
if (rc)
  /* some error */
else
  /* use i */

答案 3 :(得分:0)

一种简单的方法是将它们作为字符串进行比较。首先,请注意32位整数不能超过10位(和符号)。

int32_t get_int32()
{
    char input[13];
    char check[12];
    int32_t result;

    if (scanf("%12s", input) != 1)
        /* handle error */
    /* ignore rest of number if any */
    ungetc('x', stdin);
    scanf("%*s");

    /* if length is bigger than 11, error */
    if (strlen(input) > 11)
        /* handle error */

    if (sscanf(input, "%"SCNd32, &result) != 1)
        /* handle error */
    sprintf(check, "%"PRId32, result);

    if (strcmp(input, check) != 0)
        /* handle error */

    return result;
}

请注意strlen检查可以忽略,strcmp会处理这个问题。另请注意,如果您inputcheck足够大(例如25),则可以安全地使用int代替int32_t,因为您知道它不能超过64位(至少多年)。

答案 4 :(得分:0)

以下是工作代码:请注意这一点,我在没有strtol的情况下执行了此操作,并且它满足所有条件且仅采用int

    #include<stdio.h>
    #include<limits.h>
    #include<string.h>

    int main()
    {
            int num;
            char str[500],c;
            int check;
            char max[12];
            char min[12];
            sprintf(max,"%d",INT_MAX);
            sprintf(min,"%d",INT_MIN);
     do
     {
            int flag=1,i=0,j=0;
            num=0;
            check=0;
            printf("Enter an Integer : ");
            while((c=getchar())!='\n')
                    str[i++]=c;
            str[i]='\0';
            if(str[0] == '-')
            {
                    flag = -1;
                    j++;
            }
            for(;j<i;j++)
            {
                    if(str[j] >= '0' && str[j] <= '9')
                            check = 1;               
                else
                {
                        check = 0;
                        break;
                }

        }
        if(check == 0)
        {
                printf("Not an Integer, Please input an integer \n");
        }
        /************Start of checking integer range **************/
        else
        {
                if( (flag == -1 && (strlen(str) > strlen(min))) || 
                    (flag == 1 && (strlen(str) > strlen(max))) )
                {
                        check = 0;
                        printf("Integer is out of range, \n");
                }
                else if(flag == -1 && (strlen(str) == strlen(min)) )
                {
                        i=0;
                        while(min[i]!='\0')
                        {
                                if (str[i] > min[i])
                                {
                                        check = 0;
                                        printf("Integer is out of range \n");
                                        break;
                                }
                                i++;                        }
                        if(check == 1)
                        {
                                for(j=1;j<strlen(str);j++)
                                        num=(str[j]-'0')+num*10;
                                num *=flag;
                                printf("The given number is : %d\n",num);
                        }
                }

                else if(flag == 1 && (strlen(str) == strlen(max)) )
                {
                        i=0;
                        while(max[i]!='\0')
                        {
                                if (str[i] > max[i])
                                {
                                        check = 0;
                                        printf("Integer is out of range\n");
                                        break;
                                }
                                i++;
                        }
                        if(check == 1)
                        {
                                for(j=0;j<strlen(str);j++)
                                        num=(str[j]-'0')+num*10;
                                num *=flag;
                                printf("The given number is : %d\n",num);
                        }
                }
                else
                {
                for(j=0;j<strlen(str);j++)
                        num=(str[j]-'0')+num*10;
                num *=flag;
                printf("The given number is : %d\n",num);
                }
        }
        /************End of checking integer range ****************/
 }while(check == 0);

return 0;