0 前言
本文介绍使用C库自带的函数实现字符串转64位无符号数的方法,简单好用!
1 函数实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* @brief 计算数x的y次幂
*
* @param x 数x
* @param y y次幂
* @return 结果
*/
unsigned long long int pow_u64(unsigned long long int x, unsigned long long y)
{
unsigned long long i;
unsigned long long ret = 1;
if (y == 0)
{
return 1;
}
for (i = 0; i < y; i++)
{
ret *= x;
}
return ret;
}
/**
* @brief 字符串转64位无符号数
*
* @param str 字符串
* @param binary 进制选择:10/16
* @return unsigned long long int 结果
*/
unsigned long long int str_to_u64_bin(char *str, int binary)
{
char *ptr;
unsigned long long int ret;
unsigned long long int ret1;
unsigned long long int ret2;
unsigned long long int ret3;
int p1, p2, p3;
int len1, len2, len3;
/* 用10进制表示s64最大的数长度为20 */
char str1[15] = {0};
char str2[15] = {0};
char str3[15] = {0};
int len = strlen(str);
if (len > 20)
{
return 0;
}
len1 = (float)len / 3;
len2 = (float)len / 3;
len3 = len - len2 - len1;
p1 = 0;
p2 = len1;
p3 = len1 + len2;
/* 将字符串分3块处理 */
strncpy(str1, &str[p1], len1);
strncpy(str2, &str[p2], len2);
strncpy(str3, &str[p3], len3);
ret1 = strtoul(str1, &ptr, binary);
ret2 = strtoul(str2, &ptr, binary);
ret3 = strtoul(str3, &ptr, binary);
ret = ret1 * pow_u64(binary, len2 + len3)
+ ret2 * pow_u64(binary, len3)
+ ret3;
return ret;
}
/**
* @brief 字符串转64位无符号数
*
* @param str 10/16进制字符串
* @return unsigned long long int 结果
*/
unsigned long long int str_to_u64(char *str)
{
if ((strstr(str, "0x") != NULL) || (strstr(str, "0X") != NULL))
{
/* 16进制转u64 */
return str_to_u64_bin(str, 16);
}
/* 10进制转字符串 */
return str_to_u64_bin(str, 10);
}
函数说明:
(1)对外的接口是str_to_u64函数,支持10/16进制字符串转64位无符号数。如果有需要可以通过修改str_to_u64_bin函数支持更多进制
(2)strncpy、strtoul是C库自带函数
(3)pow_u64是自己实现的一个计算数x的y次幂的函数
实现思路:
C库自带的字符串转数字函数最多支持32位,我们将传入的字符串拆解成3份,使用C库自带的字符串转数字函数将3份字符串对应的数字转换出来,然后按照每个字符串在源字符串中的位置,将实际的数字大小还原出来。
2 功能测试验证
2.1 10进制字符串转64位无符号数测试
构造从0到64位无符号数上限的字符串去测试字符串转64位无符号数函数显然是不现实的,64位无符号数能表示的最大大小是:18446744073709551615,对应字符串长度为20。我们构造长度为1-20的字符串,传入我们设计好的str_to_u64函数,查看是否都能正确转换。函数设计:
void check_u64_value(void)
{
int i;
unsigned long long int val;
char str[25] = {0};
for (i = 0; i <= 19; i++)
{
val = pow_u64(10, i);
sprintf(str, "%llu", val);
if (str_to_u64(str) == val)
{
printf("[ OK ] Val : %llu\r\n", val);
printf(" Ret : %llu\r\n", str_to_u64(str));
}
else
{
printf("[FAIL] Val : %llu\r\n", val);
printf(" Ret : %llu\r\n", str_to_u64(str));
}
}
}
执行结果:
[ OK ] Val : 1
Ret : 1
[ OK ] Val : 10
Ret : 10
[ OK ] Val : 100
Ret : 100
[ OK ] Val : 1000
Ret : 1000
[ OK ] Val : 10000
Ret : 10000
[ OK ] Val : 100000
Ret : 100000
[ OK ] Val : 1000000
Ret : 1000000
[ OK ] Val : 10000000
Ret : 10000000
[ OK ] Val : 100000000
Ret : 100000000
[ OK ] Val : 1000000000
Ret : 1000000000
[ OK ] Val : 10000000000
Ret : 10000000000
[ OK ] Val : 100000000000
Ret : 100000000000
[ OK ] Val : 1000000000000
Ret : 1000000000000
[ OK ] Val : 10000000000000
Ret : 10000000000000
[ OK ] Val : 100000000000000
Ret : 100000000000000
[ OK ] Val : 1000000000000000
Ret : 1000000000000000
[ OK ] Val : 10000000000000000
Ret : 10000000000000000
[ OK ] Val : 100000000000000000
Ret : 100000000000000000
[ OK ] Val : 1000000000000000000
Ret : 1000000000000000000
[ OK ] Val : 10000000000000000000
Ret : 10000000000000000000
可以看到1-20长度的字符串都被正确转换。
2.2 16进制字符串转64位无符号数测试
构造从0到64位无符号数上限的字符串去测试字符串转64位无符号数函数显然是不现实的,使用16进制表示64位无符号数最大值对应字符串是:0xffffffffffffffffffffffffffffffff,对应字符串长度为18。我们构造长度为3-18的字符串,传入我们设计好的str_to_u64函数,查看是否都能正确转换。函数设计:
void check_u64_value(void)
{
int i;
unsigned long long int val;
char str[25] = {0};
val = 0;
for (i = 0; i < 16; i++)
{
val = (val << 4) | 0xf;
sprintf(str, "0x%llx", val);
if (str_to_u64(str) == val)
{
printf("[ OK ] Val : 0x%llx\r\n", val);
printf(" Ret : 0x%llx\r\n", str_to_u64(str));
}
else
{
printf("[FAIL] Val : 0x%llx\r\n", val);
printf(" Ret : 0x%llx\r\n", str_to_u64(str));
}
}
}
执行结果:
[ OK ] Val : 0xf
Ret : 0xf
[ OK ] Val : 0xff
Ret : 0xff
[ OK ] Val : 0xfff
Ret : 0xfff
[ OK ] Val : 0xffff
Ret : 0xffff
[ OK ] Val : 0xfffff
Ret : 0xfffff
[ OK ] Val : 0xffffff
Ret : 0xffffff
[ OK ] Val : 0xfffffff
Ret : 0xfffffff
[ OK ] Val : 0xffffffff
Ret : 0xffffffff
[ OK ] Val : 0xfffffffff
Ret : 0xfffffffff
[ OK ] Val : 0xffffffffff
Ret : 0xffffffffff
[ OK ] Val : 0xfffffffffff
Ret : 0xfffffffffff
[ OK ] Val : 0xffffffffffff
Ret : 0xffffffffffff
[ OK ] Val : 0xfffffffffffff
Ret : 0xfffffffffffff
[ OK ] Val : 0xffffffffffffff
Ret : 0xffffffffffffff
[ OK ] Val : 0xfffffffffffffff
Ret : 0xfffffffffffffff
[ OK ] Val : 0xffffffffffffffff
Ret : 0xffffffffffffffff
可以看到3-18长度的字符串都被正确转换。