Concat 4整数成一个整数

时间:2013-08-17 16:34:35

标签: c

您好我正在尝试将4个整数合并为一个整数。我使用了这里找到的c​​oncatinate函数:

https://stackoverflow.com/a/12700533/2016977

我的代码:

unsigned concatenate(unsigned x, unsigned y) {
    unsigned pow = 10;
    while(y >= pow)
        pow *= 10;
    return x * pow + y;        
}

void stringtoint(){
    struct router *ptr;
    ptr=start;

    while(ptr!=NULL){
        int a;
        int b;
        int c;
        int d;

        sscanf(ptr->ip, "%d.%d.%d.%d", &a, &b, &c, &d);
        int num1 = concatenate(a,b);
        int num2 = concatenate(c,d);
        int num3 = concatenate(num1,num2);
        printf("%d\n",num3);
        ptr=ptr->next;
    };

}

问题:

我正在处理IP地址编号,例如198.32.141.140我将它们分解为4个整数并将它们连接起来形成19832141140,但我的连接函数正在对较大的数字进行数学运算,如198.32.141.140(变为) - > {{1 }}    但它是连接小数的IP,例如-1642695340变为164.78.104.1(这是正确的)

我该如何解决这个问题,基本上我正在尝试制作一串IP,例如164781041整数数字198.32.141.140

3 个答案:

答案 0 :(得分:12)

您提出的方法可能是一个非常大的错误。您如何区分127.0.1.1127.0.0.11

将IP地址视为它们的确切方式要好得多。即,a.b.c.d表示

a * 256^3 + b * 256^2 + c * 256^1 + d * 256^0

以这种方式完成你不可能遇到我刚才描述的问题。此外,实施是微不足道的:

unsigned int number;
number = (a << 24) + (b << 16) + (c << 8) + d

答案 1 :(得分:3)

您可以阅读一行,然后使用inet_aton()。否则,您可以像Jason所说的那样做,但是您需要检查每个整数值是否在0 ... 255之内(那些4 x 8位表示包含IPv4地址的32位整数)。 inet_aton()将支持IPv4地址的十六进制,十进制和八进制表示法。

答案 2 :(得分:1)

/**
 ** You DO NOT want to do this usually...
 **/
#include <stdint.h>

uint_fast64_t
concatIPv4Addr(uint_fast16_t parts[])
{
    uint_fast64_t n = 0;

    for (int i = 0; i < 3; ++i) {
        n += parts[i];
        n *= 1000;
    }

    return (n += parts[3]);
}

我使用“快速”整数类型来提高速度,但如果您有存储要求,请使用相应的“最少”类型。当然,这假设你有一个C99编译器或带有扩展的C89编译器。否则,你会遇到根据C标准char甚至可能是32位的原始类型。由于我不知道你的目标环境,我没有做出任何假设。您可以根据需要随意更改为适当的原始类型。

我使用了16位值(最小值),因为8位数字只能表示0-255,这意味着如果意外输入了358,它将被解释为102,这仍然有效。如果你的类型能够存储超过8位且少于16位,你显然可以使用它,但是类型必须能够存储超过8位。

除此之外,您至少需要一个38位类型:

4294967295 (32-bit unsigned max)
255255255255 (255.255.255.255 converted to the integer you want)
274877906944 (38-bit unsigned max)

上述功能将分别将127.0.1.1和127.0.0.11转换为127000001001和127000000011:

127.0.1.1 ->
127.000.001.001 ->
127000001001

127.0.0.11 ->
127.000.000.011 ->
127000000011

为什么这么多零?因为否则你无法区分它们之间的区别!正如其他人所说,你可能会混淆127.0.1.1和127.0.0.11。使用上面的函数或实际将IPv4地址转换为实际十进制表示的更合适的函数,您将不会遇到这样的问题。

最后,我没有对传递给该函数的IPv4地址进行验证。我假设您在调用保存或使用IPv4地址的任何功能之前已经确保地址有效。顺便说一下,如果你想为IPv6做同样的事情,你就不能那么容易了,因为这需要一个字符串或转换成8个部分中的每个部分的十进制,每个部分最多16位,产生5个十进制数字每个部分,或40位数。要存储它,您需要至少133位,而不是IPv6地址所需的128位,就像您需要38位来存储IPv4地址而不是所需的32位。

还是不错,对吧?理论上的IPv8如何有16个部分,每个部分的大小是32位?与上述相同的函数需要580位,而不是正确的数学要求:512位。虽然今天不是问题,但我只是指出用连接每个部分的十进制值表示的IPv4地址做任何事情的错误。它非常严重。