封装了一些C语言中常用的操作,在此记录一下,避免以后重复造轮子,所有的函数都要用到<stdint.h>头文件。
持续更新...
lugItoa
将整形变量转为C风格字符串。itoa不是标准C库函数,因此自己实现一个,需要<stdint.h>头文件。代码如下
const static char s_system_symbol32[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X',
'Y', 'Z'
};
/**
* @brief 将十进制的整形数字转为任意进制的字符串,需要手动释放字符串的内存
* @param number 数字
* @param radio 进制
* @param symbols 自定义的进制符号表,如果为空,使用默认的符号表,即 1-16 与 0-F对应,默认
* 可以转化2-32间的任意进制(进制符号不包含数字的26进制需要自定义符号表实现)。如果需要使用自定义*
* 的进制符号或支持更高的进制(如64进制),可传入一个进制符号数组,数组下标与进制符号相对应。
* @return 转化后的字符串
*/
char* lugItoa(int64_t number, int32_t radio, const char* symbols){
int32_t i, is_minus = 0, len = 1;
char *ret = NULL;
int64_t tmp = number;
//使用符号表避免与进制相关的逻辑运算,空间换时间
if(radix < 2) return NULL;//进制小于2,不允许操作
if(radix > 32 && symbols == NULL) return NULL;//有自定的符号表时,允许进制大于32
if(symbols == NULL) symbols = s_system_symbol32;
if(number < 0){
is_minus = 1;
number = -number;
len = 2;//如果给出的数字为负数,需要预留一个负号的位置
}
while(tmp /= radix) ++len; //计算转化后字符串的长度
ret = malloc(len + 1);
if(ret == NULL) return NULL;
ret[len] = 0;
//从后往前赋值,避免之后的反转数组操作
for(i = len - 1; i >= 0; --i){
ret[i] = symbols[number % radix];
number /= radix;
}
if(is_minus == 1) ret[0] = '-';
return ret;
}
lugMergeStrings
将若干个C风格字符串合并为一个新的字符串,使用了可变参数,代码如下
/**
* @brief 按照顺序拼接参数给出的字符串, 最后一个参数必须要是空, 需要手动释放新字符串
* @param 需要拼接的所有字符串
* @return 拼接后的新字符串
*/
extern char* lugMergeStrings(const char* str, ...){
const char* rp;
char* ret, *wp;
int32_t len = 0;
va_list calc, args;
va_start(calc, str);
va_copy(args, calc);
//计算拼接后字符串总长度
for(rp = str; rp != NULL; rp = va_arg(calc, const char*)){
len += strlen(rp);
}
va_end(calc);
wp = ret = malloc(len + 1);
if(ret == NULL) return NULL;
ret[len] = 0;
//复制所有要拼接的字符串到新的字符串
for(rp = str; rp != NULL; rp = va_arg(args, const char*)){
while(*wp++ = *rp++);
--wp;//写入了一个前一个字符串结尾的'\0',回退一步
}
va_end(args);
return ret;
}
lugFtoa
将浮点数转化为C风格字符串,需要依赖上面的lugItoa和lugMergeStrings,代码如下
/**
* @brief 将浮点数转化为字符串,需要手动释放字符串的内存
* @param number 将要转化为浮点数的字符串
* @param precision 转化的精度,即转化后小数点的位数. 该值小于0,返回值为NULL,等于0时,自
* 动截取小数点后若干位(一般较长). 如果不想要小数点后面的内容,该函数无法做到,可以尝试将浮点
* 数强转为整形,调用lugItoa实现
* @return
*/
char* lugFtoa(double number, int32_t precision){
int64_t prefix; //小数点前面的整数
double suffix; //小数点后面的小数
char *istring = NULL, *fstring = NULL, *ret = NULL;
prefix = (int64_t)number;
suffix = number - prefix;
//精度处理
if(precision < 0)return NULL;//不允许精度小于0
if(precision == 0){//不指定精度时,获取合适的精度
while(suffix != (int64_t)suffix){
suffix *= 10;
precision += 1;
}
suffix = number - prefix;
}
//处理整数部分
istring = lugItoa(prefix, 10, NULL);
//处理小数部分
while(precision--)suffix *= 10;
fstring = lugItoa((int64_t)suffix, 10, NULL);
if(istring == NULL || fstring == NULL) goto failed;
//合并整数部分、小数点、小数部分
ret = lugMergeStrings(istring, ".", fstring, NULL);
if(ret == NULL)goto failed;
free(istring);
free(fstring);
return ret;
failed:
free(istring);
free(fstring);
free(ret);
return NULL;
}
|