atof函数的自实现

atof函数,用于将字符串参数转化为浮点型

/*
 系统:linux
 自实现atof函数,主函数用于参数合法化的判断,若合法则调用子函数,否则退出
 此程序包含两种算法的atof实现,均有效
*/

#include <stdio.h>
#include <string.h>

float str_to_float(char *str);
float str_to_float1(char *str);
int main(int argc, char* argv[])
{
    /*
    i 用于字符串的遍历
    n 用于记录字符串的长度
    flag_point 用于标记小数点是否已出现 默认0 出现小数点后置为1
    flag_return 拥有标记字符串是否非法 默认为0 非法后置为1
    result 用于存储未带+/-的结果
    str 指向待转换字符串
    */
    int i, n, flag_point, flag_return;
    float result;
    char *str;
    
    if (argc == 1) {
        fprintf(stderr, "usage: %s string\n", argv[0]);
        return 1;
    }

    flag_point = 0;
    flag_return = 0;
    n = strlen(argv[1]);
    str = argv[1];
    result = 0.0;
    for (i = 0;i < n;i++) {
    //判断字符串中是否存在+/-,若在首位置则有效,否则则非法
        if (str[i] == '+' || str[i] == '-') {
            if (i == 0)
                continue;
            else {
                flag_return = 1;
                break;
            }
        }
      //判断小数点最多只能出现一次,否则则非法
        if (str[i] == '.') {
            if (flag_point == 0)
                if (i == 0) {
                    flag_return = 1;
                    break;
                } else {
                    flag_point = 1;
                    continue;
                }
            else {
                flag_return = 1;
                break;
            }
        }
        //其余字符必在0-9范围内 否则非法
        if (str[i] >= '0' && str[i] <= '9')
            continue;
        else {
            flag_return = 1;
            break;
        }
    }

    if (flag_return == 0) {
        result = str_to_float(argv[1]);
        printf("The %s transform float is %f\n", argv[1], result);
    
    } else 
        printf("The %s string is illegal\n", argv[1]);
    return 0;
    
}
/*
算法1
从左向右遍历字符串(由高位向低位)
例:
整数部分采取 123 = (((1*10)+2)*10)+3方法
小数部分采取0.123 = 1/10 + 2/100 + 3/1000方法
最后将整数与小数部分相加
*/
float str_to_float(char *str)
{
    /*
      m 保存结果的小数部分
      k 保存结果的整数部分
      o 保存每一位的小数部分
      flag 保存正负号
      flag_point 标准小数点已出现,更改转换方式
      p 保存当前在小数点后位数对应的值,如第一位 p 10 第二位 p 100
    */
    float m, o;
    int n, i, flag, flag_point, k, p;
    
    n = strlen(str);
    flag = 1;
    flag_point = 1;
    k = 0;
    m = 0;
    o = 0;
    for (i = 0;i < n;i++) {
        if (i == 0 && (str[i] == '+' || str[i] == '-')) {
            if (str[i] == '-')
                flag = -1;
            continue;
        }
        if (str[i] == '.') {
            flag_point = 0;
            p = 1;
            continue;
        }
        if (flag_point){
            k = k*10 + (str[i] - '0');
        }
        else {
            p *= 10;
            o = str[i] - '0';
            m += o/p;
        }    
    }
    return flag*(k+m);
}
/*
 方法2
 从右向左遍历字符串(由低位向高位)
 例:
 12.34 先得到1234 且记录小数点位置
 再用 1234/100 = 12.34
*/

float str_to_float1(char *str)
{
/*
   flag 用于标记小数点位置
   flag1 用于标记字符串的正负
   result拥有存储结果
   p 用于保存当前以访问多少位
   q 用于保存共有几位小数
*/
    int i, n, p, flag, q, flag1;
    float result;
    
    n = strlen(str);
    result = 0;
    p = 1;
    q = 1;
    flag = 0;
    flag1 = 1;
    for (i = n- 1;i >= 0;i--) {
    //用于跳过最右端多余的0
        if (i == (n -1))
            while (str[i] == '0')
                i--;
        if (str[i] == '.') {
            flag = 1;
            continue;
        }
        if (flag == 0)
            q *= 10;
        if (i == 0 && (str[i] == '+' || str[i] == '-'))    {
            if (str[i] == '-')
                flag1 = -1;
            continue;
        }
        result += p*(str[i] -'0');
        p *= 10;
    }
    return flag1*result/q;
}


总结:

看似小的功能,实现起来颇飞周折,勤加练习

1、变量在申请后,使用前一定要赋初始值

2、float类型变量在赋值过程中存在精度损失

3、边界的判断问题

你可能感兴趣的:(atof函数的自实现)