查看数字是否小于2 ^ 32

DOR*_*pst 2 c long-integer

我正在通过stdin读取大量数字,我需要找到它,如果数字在[0,2 ^ 32]范围内(可能是2 ^ 32-1,我不确定那个),所以它是也不接受负数.还有一些情况下,有一个以数百个空值开头的数字,我需要忽略它.我确定如果我对数据类型做错了,目前我使用"long"作为数据类型,因为我认为这总是最多2 ^ 32.所以,如果有溢出,我得到一个负数,我可以证明长度是否小于0.但现在我意识到长的大小也取决于计算机的系统.

是否有人可以告诉我应该选择哪种数据类型和操作来证明这一点?开始的数据类型只是一个char指针.

Ste*_*ner 5

这比初看起来有点棘手.原因是当您允许任意长的输入序列时,您甚至可能超过可用的最大数据类型,例如,甚至64位可能太少.

根据您用于读取数字的方法,检测到数据类型是否溢出.例如,scanf("%lu",...)如果处理的整数值不符合unsigned long(例如,这个关于scanf的在线c11草案),可能会导致未定义的行为:

10 ...如果此对象没有合适的类型,或者无法在对象中表示转换结果,则行为未定义.

所以不要scanf用于任意输入.

strtoul相反,函数具有已定义的溢出行为(同样来自在线c11草案,关于strtol):

8)strtol,strtoll,strtoul和strtoull函数返回转换后的值(如果有的话).如果无法执行转换,则返回零.如果正确的值超出可表示值的范围,则返回LONG_MIN,LONG_MAX,LLONG_MIN,LLONG_MAX,ULONG_MAX或ULLONG_MAX(根据值的返回类型和符号,如果有),并且宏ERANGE的值为存储在errno中.

你可以使用,strtol因为它会给你一个至少32位的数字,它会告诉你溢出.如果long是64位,则可以/需要区分一般溢出或32位溢出.请参阅以下代码说明:

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

void convert(const char* numStr) {

    errno=0;
    long num = strtol(numStr,NULL,10);

    if (errno == ERANGE){
        printf("numstr %s is out of long's range, which is %ld..%ld\n", numStr, LONG_MIN,LONG_MAX);
    } else if (num < 0) {
        printf("numstr %s is negative.\n", numStr);
    } else if (num > UINT32_MAX) {
        printf("numstr %s is out of 32 bit range, which is 0..%u\n", numStr, UINT32_MAX);
    } else {
        printf("OK; numstr %s is in 32 bit range, which is 0..%u\n", numStr, UINT32_MAX);
    }

}


int main() {

    convert("123456789012345678901234567890");
    convert("-123");
    convert("1234567890123567");
    convert("32452345");
    convert("0000000000000000000000032452345");
}
Run Code Online (Sandbox Code Playgroud)

输出:

numstr 123456789012345678901234567890 is out of long's range, which is -9223372036854775808..9223372036854775807
numstr -123 is negative.
numstr 1234567890123567 is out of 32 bit range, which is 0..4294967295
OK; numstr 32452345 is in 32 bit range, which is 0..4294967295
OK; numstr 0000000000000000000000032452345 is in 32 bit range, which is 0..4294967295
Run Code Online (Sandbox Code Playgroud)