最近写了一个小工具需要从文件中读出数字以double类型显示并计算(文件中包含空格换行逗号作为完整数字标记 ,并且运行负数),由于需要从读取到的字符串中截取数字稍微麻烦,便动手封装个方法截取转换一次完成。
设计函数的过程中也遇到一些小问题,比如整数部分和小数部分的计算方式不一样,只能通过分开计算然后相加完成转换, 整数部分需要乘以10相加 ,小数部分需要除以10相加 ,并且小数部分遇到0不相加选择跳过。
每一次得到一个完整的数后变量清零,进行下一个数的计算,double类型整数位加小数位一共是18位数字(包括小数点、负号在内最多19个),如果一个完整的数(整数位加小数位)等于19将会强制相加组成一个double数字 后面多余的数字舍去 ,在遇到一个空格、换行或者逗号后进行下一个数的计算。
函数定义:
int charTodouble(double *ndst,int Num,void* src,int len);
代码实现:
//第一个参数: double类型目标地址 比如定义一个double数组用来接收转换后的数据
//第二个参数: 需要接收的数量 比如1,只接收一个double类型数据
//第三个参数: 字符串地址 比如从文本中读取出来的一串char类型数字(Ascll码称为数字)
//第四个参数: 字符串的长度
int charTodouble(double *ndst,int Num,void* src,int len)
{
if (0 >= Num || 0 == src || 0 >= len)
{
return -1;
}
char* psrc = (char*)src;
double nVal = 0;//整数
int nNum = 0;//记录数据长度
int neg = 0;//负数标志位1
double ndec = 0;//小数
bool dec = false;//小数位计算标志
int nZero = 0;//小数位计算
int nvalNum = 0;//返回转换到double类型的实际数据数量
bool stop = false;//如果记录的整数位与小数位超过了18位那么后面的数字舍弃,等待下一次记录数据
for (int i = 0;i < len;i++)
{
if (32 != *(psrc + i) && 10 != *(psrc + i) && ',' != *(psrc + i) && 13 != *(psrc + i))
{
if (stop)
{
continue;
}
if ('-' == *(psrc + i))
{
neg = 1;
continue;
}
if (18 < nNum)
{
nVal += ndec;
if (1 == neg)
{
nval[nvalNum] += -nVal;
}
else
nval[nvalNum] += nVal;
if (nvalNum == nNum - 1)
return nNum;
nvalNum++;
nNum = 0;
neg = 0;
nVal = 0;
nZero = 0;
ndec = 0;
dec = false;
stop = true;
continue;
}
if ('.' == *(psrc + i))
{
dec = true;
}
if (!dec)
{
nVal = nVal * 10 + (*(psrc + i) - '0');
nNum++;
continue;
}
nZero++;
if ('0' == *(psrc + i) || '.' == *(psrc + i))
{
if ('.' == *(psrc + i))
{
nZero--;
}
continue;
}
ndec += (double)(*(psrc + i)- '0') / pow((double)10,nZero);//这里用到了计算平方函数pow 需要#include <math.h>
nNum++;
}
else
{
stop = false;
if (0 == nVal && 0 == nNum)
{
continue;
}
nVal += ndec;
if (1 == neg)
{
nval[nvalNum] = -nVal;
}
else
nval[nvalNum] = nVal;
if (nvalNum == nNum - 1)
return nNum;
nvalNum++;
nNum = 0;
neg = 0;
nVal = 0;
nZero = 0;
ndec = 0;
dec = false;
}
}
if (0 != nVal || 0 != nNum)//循环结束后,检查下最后一个数字是否需要保存
{
nVal += ndec;
if (1 == neg)
{
nval[nvalNum] += -nVal;
}
else
nval[nvalNum] += nVal;
nvalNum++;
}
return nvalNum;
}
下面贴上测试代码:
double dval[100] = {0};
char valStr[1024] = "1023.1234567890123123213213213, -987654321.98765123451321321321321321321 ,0102030405.102030405321321321321321060 "
"\r\n,192301939.000001013213213212222322\0";
int nLen = charTodouble(dval,1024,valStr,strlen(valStr));