题解 | 简单计算器

简单计算器

https://www.nowcoder.com/practice/b8f770674ba7468bb0a0efcc2aa3a239

#include <stdio.h>
#include <math.h>   // fabs 函数需要 math.h

// 将 sentence[n..j] 这一段字符串转换成数字数组 num 中的各位数字
// 同时返回小数点在原始字符串中的下标;如果没有小数点,则默认在 j+1(即“小数点在最后一位数字之后”)
int convert(int n, int j, char sentence[51], int num[50])
{
    // 默认认为小数点在 j+1(代表“没有小数部分”)
    int num_of_point = j + 1;

    // 遍历 [n, j] 区间,把数字字符存成对应的数值
    for (int i = n; i <= j; i++)
    {
        if (sentence[i] != '.')
        {
            // '0' 的 ASCII 是 48,这里把字符 '0'~'9' 转成 0~9
            num[i] = sentence[i] - '0';
        }
        else
        {
            // 记录小数点位置,后面按它把整数部分和小数部分分开
            num_of_point = i;
        }
    }

    return num_of_point;
}

// 计算整数部分的值:
// 已知小数点位置 num_of_point,整数部分是 [n .. num_of_point-1] 这一段
// 从右往左累加:个位 *1,十位 *10,百位 *100 ...
double value_bigger(int num_of_point, int num[50], int n)
{
    int status = 1;     // 当前位对应的权值(1, 10, 100, ...)
    double value = 0;

    for (int i = num_of_point - 1; i >= n; i--)
    {
        value += num[i] * status;
        status *= 10;
    }

    return value;
}

// 计算小数部分的值:
// 已知小数点位置 num_of_point,小数部分是 [num_of_point+1 .. n] 这一段
// 从左往右累加:第一位 *0.1,第二位 *0.01,第三位 *0.001 ...
double value_smaller(int num_of_point, int num[50], int n)
{
    double status = 0.1;    // 当前位对应的权值(0.1, 0.01, 0.001, ...)
    double value = 0;

    for (int i = num_of_point + 1; i <= n; i++)
    {
        value += num[i] * status;
        status /= 10;
    }

    return value;
}

int main()
{
    // sentence 用来存放输入的整行表达式,比如 "12.34+56.78"
    char sentence[51] = {0};
    scanf("%s", sentence);   // 这里按题目要求用 %s,遇到空格会截断

    // num_1 复用来存放左右两个数的各位数字(按原始下标存)
    int num_1[50] = {0};

    char ch = '\0';    // 运算符 (+ - * /)
    int j = 0;         // 运算符在字符串中的下标
    int end = 0;       // 字符串长度(不包括 '\0')

    double value_of_big1, value_of_big2;        // 两个数的整数部分
    double value_of_small1, value_of_small2;    // 两个数的小数部分
    double value1, value2;                      // 两个完整的 double 数值

    // 先扫描整条字符串:
    // 1. 统计长度 end
    // 2. 找到运算符及其位置 j
    // 3. 检查是否有非法字符
    for (int i = 0; sentence[i] != '\0'; i++)
    {
        end++;

        // 判断是否是运算符
        if (sentence[i] == '+' || sentence[i] == '-' ||
            sentence[i] == '*' || sentence[i] == '/')
        {
            ch = sentence[i];
            j = i;
        }
        // 不是运算符的话,只允许数字和小数点
        else if (sentence[i] != '.' && (sentence[i] < '0' || sentence[i] > '9'))
        {
            printf("Invalid operation!");
            return 0;
        }
    }

    // 如果扫描完都没找到运算符,表达式不合法
    if (ch == '\0')
    {
        printf("Invalid operation!");
        return 0;
    }

    // 解析第一个数:在 [0 .. j-1] 这一段
    int num_of_point1 = convert(0, j - 1, sentence, num_1);
    // 解析第二个数:在 [j+1 .. end-1] 这一段
    int num_of_point2 = convert(j + 1, end - 1, sentence, num_1);

    // 分别计算两个数的整数部分
    value_of_big1 = value_bigger(num_of_point1, num_1, 0);
    value_of_big2 = value_bigger(num_of_point2, num_1, j + 1);

    // 分别计算两个数的小数部分
    value_of_small1 = value_smaller(num_of_point1, num_1, j - 1);
    value_of_small2 = value_smaller(num_of_point2, num_1, end - 1);

    // 合并整数和小数部分,得到真正的 double 值
    value1 = value_of_big1 + value_of_small1;
    value2 = value_of_big2 + value_of_small2;

    // 除法时需要判断除数是否为 0(这里用一个很小的阈值判断“接近 0”)
    if (ch == '/' && fabs(value2) < 1e-9)
    {
        printf("Wrong!Division by zero!");
        return 0;
    }

    double result = 0;

    // 根据运算符执行对应的四则运算
    switch (ch)
    {
        case '+':
            result = value1 + value2;
            break;
        case '-':
            result = value1 - value2;
            break;
        case '*':
            result = value1 * value2;
            break;
        case '/':
            result = value1 / value2;
            break;
        default:
            // 理论上不会走到这里,前面已经检查过运算符是否合法
            printf("Invalid operation!");
            return 0;
    }

    // 按题目要求输出:保留 4 位小数,格式为 a?b=result
    printf("%.4lf%c%.4lf=%.4lf", value1, ch, value2, result);

    return 0;
}

全部评论

相关推荐

2025-11-27 21:29
已编辑
武汉理工大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务