基本想法:
例:123.456E1234,其中小数点前面算整数部分,小数点到E是小数部分,E后面的是有效数部分。
#include <iostream>
#include <string>
#include <fstream>
#include <cctype>
using std::string;
using std::ifstream;
#define INTEGER 0
#define FRACTION 1
#define SIGNIF 2
float fractorial(int value)
{
float num = 1;
if(value < 0)
for(int i = -value; i > 0; --i)
num *= 0.1;
else if(value > 0)
for(int i = value; i > 0; --i)
num *= 10;
return num;
}
float atof(const string &expr)
{
string::const_iterator begin = expr.begin();
string::const_iterator end = expr.end();
float value = 0;
float integer = 0;
float fraction = 0;
int signif = 0;
float minus = 1;
int flag = INTEGER;
int sign1 = 1;
int sign2 = 1;
for(; begin != end; ++begin){
while(*begin == ' ') continue; //delete the lead space
if(*begin == '-')
if(flag == INTEGER)
sign1 = -1;
else if(flag == SIGNIF)
sign2 = -1;
if(*begin == '-' || *begin == '+' )
continue;
if(isdigit(*begin)){
if(INTEGER == flag){ //caculate the interger
integer = integer * 10 + *begin - '0';
}else if(FRACTION == flag){ //caculate the float
fraction = fraction * 10 + *begin - '0';
minus *= 0.1;
}else{ //caculate the effective number
signif = signif * 10 + *begin - '0';
}
}else if(*begin == '.'){
flag = FRACTION;
}else if(*begin == 'e' || *begin == 'E'){
flag = SIGNIF;
}
}
return sign1*(integer + fraction * minus) *fractorial(sign2 * signif);
}
int main()
{
ifstream ifs("data.txt");
string expr;
while(std::getline(ifs, expr)){
std::cout << atof(expr) << std::endl;
}
ifs.close();
return 0;
}
测试文件data.txt:
+12.23
0.34e3
.4E3
-1.345E-3
345
+23e-5
测试结果:
[root@localhost atof]# ./atof
12.23
340
400
-0.001345
345
0.00023
基本测试能过,其中有一些异常情况没考虑(空串,非数字字符)。