字符串处理常用函数

截取字符串的一定的长度在解各种数据包中是非常常用的,怎么实现截取取决于数据包的数据类型。
1、截取两个字节长度:
定义为宏:

#define pntoh16(p)  ((uint16_t)                       \
                     ((uint16_t)*((const uint8_t *)(p)+0)<<8|  \
                      (uint16_t)*((const uint8_t *)(p)+1)<<0))

定义为函数:
uint16_t pntoh16(uint8_t* p)
{
return (uint16_t)|(uint16_t)(p+0)<<8|(uint16_t)(p+1)<<0);
}
2、截取三个字节长度:
定义为宏:

#define pntoh24(p)  ((uint32_t)*((const uint8_t *)(p)+0)<<16|  \
                     (uint32_t)*((const uint8_t *)(p)+1)<<8|   \
                     (uint32_t)*((const uint8_t *)(p)+2)<<0)

定义为函数:
uint32_t pntoh24(uint8_t* p)
{
return (uint32_t)((uint32_t)(p)<<16|(uint32_t)(p+1)<<8|(uint32_t)*(p+2)<<0);
}
3、截取四个字节长度:
定义为宏:

#define pntoh32(p)  ((uint32_t)*((const uint8_t *)(p)+0)<<24|  \
                     (uint32_t)*((const uint8_t *)(p)+1)<<16|  \
                     (uint32_t)*((const uint8_t *)(p)+2)<<8|   \
                     (uint32_t)*((const uint8_t *)(p)+3)<<0)

定义为函数:
uint32_t pntoh32(uint8_t* p)
{
return (uint32_t)((uint32_t)(p)<<24|(uint32_t)(p+1)<<16|(uint32_t)(p+2)<<8|(uint32_t)(p+3)<<0);
}
以下类似函数省略:

#define pntoh40(p)  ((uint64_t)*((const uint8_t *)(p)+0)<<32|  \
                     (uint64_t)*((const uint8_t *)(p)+1)<<24|  \
                     (uint64_t)*((const uint8_t *)(p)+2)<<16|  \
                     (uint64_t)*((const uint8_t *)(p)+3)<<8|   \
                     (uint64_t)*((const uint8_t *)(p)+4)<<0)

#define pntoh48(p)  ((uint64_t)*((const uint8_t *)(p)+0)<<40|  \
                     (uint64_t)*((const uint8_t *)(p)+1)<<32|  \
                     (uint64_t)*((const uint8_t *)(p)+2)<<24|  \
                     (uint64_t)*((const uint8_t *)(p)+3)<<16|  \
                     (uint64_t)*((const uint8_t *)(p)+4)<<8|   \
                     (uint64_t)*((const uint8_t *)(p)+5)<<0)

#define pntoh56(p)  ((uint64_t)*((const uint8_t *)(p)+0)<<48|  \
                     (uint64_t)*((const uint8_t *)(p)+1)<<40|  \
                     (uint64_t)*((const uint8_t *)(p)+2)<<32|  \
                     (uint64_t)*((const uint8_t *)(p)+3)<<24|  \
                     (uint64_t)*((const uint8_t *)(p)+4)<<16|  \
                     (uint64_t)*((const uint8_t *)(p)+5)<<8|   \
                     (uint64_t)*((const uint8_t *)(p)+6)<<0)

#define pntoh64(p)  ((uint64_t)*((const uint8_t *)(p)+0)<<56|  \
                     (uint64_t)*((const uint8_t *)(p)+1)<<48|  \
                     (uint64_t)*((const uint8_t *)(p)+2)<<40|  \
                     (uint64_t)*((const uint8_t *)(p)+3)<<32|  \
                     (uint64_t)*((const uint8_t *)(p)+4)<<24|  \
                     (uint64_t)*((const uint8_t *)(p)+5)<<16|  \
                     (uint64_t)*((const uint8_t *)(p)+6)<<8|   \
                     (uint64_t)*((const uint8_t *)(p)+7)<<0)

有时候我们数据是网络字节序(大端字节序:把值的低位存在高地址)的需要截取并转化成主机字节序(小端字节序:把值得低位存在地地址)。
附加一个判断本机大小端的简单程序
void litterorbig ()
{
unsigned int x = 0x12345678;
char c = (char)&x;
if (*c == 0x78) {
printf(“Little endian”);
} else {
printf(“Big endian”);
}
}
下面分别是截取两、三、四、五、六、七、八字节长度并转换的定义的宏,函数省略:

#define pletoh16(p) ((uint16_t)                       \
                     ((uint16_t)*((const uint8_t *)(p)+1)<<8|  \
                      (uint16_t)*((const uint8_t *)(p)+0)<<0))

#define pletoh24(p) ((uint32_t)*((const uint8_t *)(p)+2)<<16|  \
                     (uint32_t)*((const uint8_t *)(p)+1)<<8|   \
                     (uint32_t)*((const uint8_t *)(p)+0)<<0)

#define pletoh32(p) ((uint32_t)*((const uint8_t *)(p)+3)<<24|  \
                     (uint32_t)*((const uint8_t *)(p)+2)<<16|  \
                     (uint32_t)*((const uint8_t *)(p)+1)<<8|   \
                     (uint32_t)*((const uint8_t *)(p)+0)<<0)

#define pletoh40(p) ((uint64_t)*((const uint8_t *)(p)+4)<<32|  \
                     (uint64_t)*((const uint8_t *)(p)+3)<<24|  \
                     (uint64_t)*((const uint8_t *)(p)+2)<<16|  \
                     (uint64_t)*((const uint8_t *)(p)+1)<<8|   \
                     (uint64_t)*((const uint8_t *)(p)+0)<<0)

#define pletoh48(p) ((uint64_t)*((const uint8_t *)(p)+5)<<40|  \
                     (uint64_t)*((const uint8_t *)(p)+4)<<32|  \
                     (uint64_t)*((const uint8_t *)(p)+3)<<24|  \
                     (uint64_t)*((const uint8_t *)(p)+2)<<16|  \
                     (uint64_t)*((const uint8_t *)(p)+1)<<8|   \
                     (uint64_t)*((const uint8_t *)(p)+0)<<0)

#define pletoh56(p) ((uint64_t)*((const uint8_t *)(p)+6)<<48|  \
                     (uint64_t)*((const uint8_t *)(p)+5)<<40|  \
                     (uint64_t)*((const uint8_t *)(p)+4)<<32|  \
                     (uint64_t)*((const uint8_t *)(p)+3)<<24|  \
                     (uint64_t)*((const uint8_t *)(p)+2)<<16|  \
                     (uint64_t)*((const uint8_t *)(p)+1)<<8|   \
                     (uint64_t)*((const uint8_t *)(p)+0)<<0)

#define pletoh64(p) ((uint64_t)*((const uint8_t *)(p)+7)<<56|  \
                     (uint64_t)*((const uint8_t *)(p)+6)<<48|  \
                     (uint64_t)*((const uint8_t *)(p)+5)<<40|  \
                     (uint64_t)*((const uint8_t *)(p)+4)<<32|  \
                     (uint64_t)*((const uint8_t *)(p)+3)<<24|  \
                     (uint64_t)*((const uint8_t *)(p)+2)<<16|  \
                     (uint64_t)*((const uint8_t *)(p)+1)<<8|   \
                     (uint64_t)*((const uint8_t *)(p)+0)<<0)

将十六进制转化为字符串

int strtohex(unsigned char *str, int len, char *hexstr)
{
    int i, j;
    unsigned char c;

    static char binhex[16] = {
           '0', '1', '2', '3', '4', '5', '6', '7',
           '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    for(i = 0, j = 0; i < len; i++)
    {
        c = *str++;
        hexstr[j++] = binhex[c>>4];
        hexstr[j++] = binhex[c&0xf];
    }
    hexstr[j]= '\0';
    return j;
}

或者

void strtohex(unsigned char*str, int len, char*hexstr)
{
    int i;
    char cTemp;
    for (i = 0; i < len; i++)
    {
        cTemp = (str[i] & 0xf0) >> 4;
        hexstr[i * 2] = (cTemp > 9) ? cTemp + 0x41 - 10 : cTemp + 0x30;
        cTemp = str[i] & 0xf;
        hexstr[i * 2 + 1] = (cTemp > 9) ? cTemp + 0x41 - 10 : cTemp + 0x30;
    }
}

或者

void strtohex(unsigned char *str, int len, char *hexstr)
{
    int i, j = 0;
    for(i =0 ; i < len; i++)
    {
        sprintf(hexstr + 2 * i,"%02X", str[i]);
    }

}

将字符串转化为十六进制

void hextostr(char*hexstr, int len, unsigned char*str)
{
    int i;
    char cTemp;
    for (i = 0; i < len; i++)
    {
        cTemp = hexstr[i * 2];
        if (cTemp >= 'A' && cTemp <= 'F')
            cTemp = cTemp - 'A' + 10;
        else if (cTemp >= 'a' && cTemp <= 'f')
            cTemp = cTemp - 'a' + 10;
        else
            cTemp &= 0x0f;

        str[i] = cTemp << 4;
        cTemp = hexstr[i * 2 + 1];
        if (cTemp >= 'A' && cTemp <= 'F')
            cTemp = cTemp - 'A' + 10;
        else if (cTemp >= 'a' && cTemp <= 'f')
            cTemp = cTemp - 'a' + 10;
        else
            cTemp &= 0x0f;
        str[i] += cTemp;
    }
    return;
}

或者

int  hextostr(char *hexstr, int len, unsigned char *str)
{
    int i, j = 0;
    char temp[2] = {0};
    for(i =0 ; i < len; i+=2)
    {
        memcpy(temp, hexstr + i, 2);
        sscanf(temp, "%02X", &str[j]);
        j++;
    }
    return j;
}

注意以上函数没有检查数组的长度,需提前检查长度以防溢出。

如果要截取的长度超过4个字节,用memcpy()函数来实现比较好,如果数据包的是字符串形式的也可以用strcpy(),strncpy(),sprintf(),strlen()等函数实现,建议用memcpy函数
进行各种拷贝。


因最近需要处理IP地址,IP地址在数据包中的形式是32位数字,我们用long int 类型进行存储,点分十进制IP地址用字符串存储,下面是两种形式的转换函数。
长整型转换为字符串

void *long2str(long int num, char *str)
{
    sprintf(str, "%u.%u.%u.%u", num >>24 & 0xFF, num >>16 & 0xFF, num >>8 & 0xFF, num >>0 & 0xFF);
}

字符串转换为长整型

long int str2long(char *str)
{
    return ntohl(inet_addr(str));
}

说明:inet_addr()和ntohl ()函数需要包含

猜你喜欢

转载自blog.csdn.net/u014608280/article/details/80521071