C语言实现简单计算器功能(2)

当我们实现一个简单的计算器功能时,需要考虑以下几个方面:

  1. 用户输入的合法性检查
  2. 进行算术运算的函数实现
  3. 错误处理和提示信息输出

第一步,我们需要先获取用户输入的表达式,并对其进行合法性检查。用户输入的表达式应该是一个合法的算术表达式,不能含有非法字符,比如字母等。我们可以使用正则表达式来判断用户输入的内容是否合法。

示例1:

#include <regex.h>

bool is_valid_input(char *input) {
    regex_t reg;
    int reti = regcomp(&reg, "[0-9+/*%-]+", REG_EXTENDED);
    if (reti) return false;
    int match = regexec(&reg, input, 0, NULL, 0);
    regfree(&reg);
    if (match != 0) return false;
    return true;
}

在上面的示例中,我们使用了POSIX的正则表达式库(regex.h)来编写正则表达式判断用户输入的内容是否是合法的算术表达式。如果不是,我们会返回false,表示用户的输入有误。

第二步,我们需要实现进行算术运算的函数。我们需要把用户输入的表达式转换成可计算的形式,再进行运算。在这里,我们可以使用栈来对表达式求解。

示例2:

#include<stdlib.h>
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define size 50
double s[size];
int top1=-1,top2=-1;
char op[size];
void error(char* s,int l) {
    printf("\n%s",s);
    for(int i=0;i<=l;i++) printf("%c",op[i]);
    exit(0);
}
void push_num(double x) {
    if(top1==size)error("plan1 stack is full",top1);
    s[++top1]=x;
}
void push_op(char ch) {
    if (top2 == size)error("plan2 stack is full",top1);
    if (ch == ')') { 
        while (op[top2] != '(') { 
            double b = s[top1];
            top1--;
            double a = s[top1];
            top1--;
            char c = op[top2];
            top2--;
            if (a >= -1e-8 && a <= 1e-8 && c == '/') error("divided by zero",top1);
            switch (c) {
                case '+':push_num(a + b); break;
                case '-':push_num(a - b); break;
                case '*':push_num(a * b); break;
                case '/':push_num(a / b); break;
                case '%':push_num((int)a % (int)b); break;
                default: error("illegal character in stack", top1);
            }
        }
        top2--;
        return;
    }
    if (ch == '+' || ch == '-') { 
        while (top2 >= 0 && op[top2] != '(') { 
            char c = op[top2]; 
            double b = s[top1]; 
            top1--; 
            double a = s[top1]; 
            top1--; 
            top2--; 
            if (a >= -1e-8 && a <= 1e-8 && c == '/') error("divided by zero",top1);
            switch (c) {
                case '+':push_num(a + b); break;
                case '-':push_num(a - b); break;
                case '*':push_num(a * b); break;
                case '/':push_num(a / b); break;
                case '%':push_num((int)a % (int)b); break;
                default: error("illegal character in stack", top1);
            }
        } 
        op[++top2] = ch; 
        return; 
    }
    if (ch == '*' || ch == '/' || ch == '%') {
        while (top2 >= 0 && op[top2] != ')' && op[top2] != '+' && op[top2] != '-') { 
            char c = op[top2]; 
            double b = s[top1]; 
            top1--; 
            double a = s[top1]; 
            top1--; 
            top2--; 
            if (a >= -1e-8 && a <= 1e-8 && c == '/') error("divided by zero",top1);
            switch (c) {
                case '+':push_num(a + b); break;
                case '-':push_num(a - b); break;
                case '*':push_num(a * b); break;
                case '/':push_num(a / b); break;
                case '%':push_num((int)a % (int)b); break;
                default: error("illegal character in stack", top1);
            }
        } 
        op[++top2] = ch;
        return;
    }
    if (ch == '(') { op[++top2] = '('; return; }
    error("illegal character", top1);
}
double calculate(char* input) {
    int l = strlen(input);
    input[l] = ')';
    for (int i = 0; i < l; i++) {
        if (input[i] == ' ')continue;
        if (isdigit(input[i])) {
            char num[20] = { '\0' };
            int k = 0;
            while (isdigit(input[i]) || input[i] == '.') {
                num[k++] = input[i++];
            }
            i--;
            push_num(atof(num));
        }
        else push_op(input[i]);
    }
    while (top2 >= 0) {
        double b = s[top1];
        top1--;
        double a = s[top1];
        top1--;
        char c = op[top2];
        top2--;
        if (a >= -1e-8 && a <= 1e-8 && c == '/') error("divided by zero", top1);
        switch (c) {
            case '+':push_num(a + b); break;
            case '-':push_num(a - b); break;
            case '*':push_num(a * b); break;
            case '/':push_num(a / b); break;
            case '%':push_num((int)a % (int)b); break;
            default: error("illegal character in stack", top1);
        }
    }
    return s[top1];
}

上面的示例是一个迭代版的栈计算器,它使用两个栈来处理数字和操作符,并在处理好操作符后返回计算结果。需要注意的是,在实现中,我们还需要考虑一些特殊情况,比如除数为0等异常情况。

第三步,我们需要考虑如何处理错误和输出提示信息。当用户输入有误或者计算过程中发生了异常情况,我们需要及时返回错误信息给用户,让用户重新输入或者纠正错误。同时,我们还需要在计算完成之后,通过合适的方式将结果输出给用户。

以上三个步骤完成后,我们就可以得到一个完整的简单计算器。除此之外,我们还可以加入一些额外的特性,比如表达式的优先级处理等。这样,我们就可以得到一个更加完备的计算器。

示例3:

int main() {
    char input[100];
    printf("输入表达式:");
    scanf_s("%[^\n]",input,99);
    if (!is_valid_input(input)) {
        printf("输入有误\n");
        return 0;
    }
    printf("结果是:%.2f\n", calculate(input));
    return 0;
}

在上面的示例中,我们通过获取用户输入,并对其进行合法性检查和计算,最后输出计算结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言实现简单计算器功能(2) - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C++工厂方法之对象创建型模式详解

    C++工厂方法之对象创建型模式详解 什么是对象创建型模式 对象创建型模式是指通过专门定义的工厂方法来创建对象,并且将对象的创建延迟到子类中去实现。 对象创建型模式实现了解耦,即将构造运算与对象的使用分离开来,使得相同的构造过程可以创建不同的产品。 工厂方法模式 工厂方法模式(Factory Method)是对象创建型模式的一种,通过定义工厂接口和工厂的具体实…

    C 2023年5月22日
    00
  • C语言科学计算入门之矩阵乘法的相关计算

    C语言科学计算入门之矩阵乘法的相关计算 什么是矩阵乘法? 矩阵乘法是一种常见的矩阵计算方式,它可以用来解决多个线性方程组的问题。 假设有两个矩阵 $A$ 和 $B$,它们的维度分别为 $m \times n$ 和 $n \times k$,则它们的乘积是一个 $m \times k$ 的矩阵 $C$,公式为: $$C_{i,j} = \sum_{r=1}^{…

    C 2023年5月22日
    00
  • C++实现通讯录管理系统设计

    C++实现通讯录管理系统设计 通讯录管理系统是一个简单的应用程序,它允许用户存储和管理联系人的信息。该应用程序以简单的控制台界面为用户提供了添加、删除、修改和搜索联系人的功能。 设计思路 设计一个通讯录管理系统,我们需要考虑以下三个关键点: 数据结构:我们需要选择合适的数据结构来存储联系人的信息,并提供相应的操作,例如添加、删除和搜索。 用户界面:我们需要为…

    C 2023年5月23日
    00
  • C语言解读数组循环右移问题

    C语言解读数组循环右移问题攻略 1. 问题描述 在数组中,循环右移操作是将数组中的元素向右移动k个位置,其中k为移动的步数,当移动到最后一个元素时,需要将最后一个元素的值作为第一个元素的值。如:[1, 2, 3, 4, 5],循环右移3个位置后变为[3, 4, 5, 1, 2]。 2. 解题思路 循环右移的本质是将原数组分为两部分:左边为需要右移的部分,右边…

    C 2023年5月23日
    00
  • C语言实现电脑关机程序

    下面是完整的攻略。 C语言实现电脑关机程序 介绍 电脑关机程序是一种可以让计算机系统自动关机的软件程序。在 C 语言中,我们可以使用系统函数来实现这个功能。本文将介绍 C 语言实现电脑关机程序的步骤。 步骤 第一步:引入头文件 在 C 语言中,我们需要引入头文件 windows.h 来使用系统函数。 #include <windows.h> 第二…

    C 2023年5月23日
    00
  • C++设计模式之单例模式详解

    下面是详细讲解“C++设计模式之单例模式详解”的完整攻略。 什么是单例模式? 单例模式是一种创建型设计模式,用于确保类只有一个实例,并提供全局访问点。 为什么使用单例模式? 在某些情况下,我们需要确保在整个应用程序中只有一个实例化对象。单例模式使我们能够确保这一点。此外,单例模式还可以提供全局访问点,以便在应用程序中的任何地方都可以轻松访问单例对象。 实现单…

    C 2023年5月22日
    00
  • 用C++实现队列的程序代码

    实现队列的程序代码主要涉及以下内容:数据结构、队列的操作、C++语法等。下面我们一步步来进行讲解。 数据结构 队列可以看成是一种特殊的线性表,它具有先进先出(FIFO)的特点,即先进队列的元素将先输出,后进队列的元素将后输出。 队列通常包含以下几个基本操作:入队、出队、判空和求队列长度等。入队就是将新元素插入到队列的末尾,出队就是将队头元素删除并返回,判空就…

    C 2023年5月23日
    00
  • C++中new和delete匹配使用过程详解

    C++中new和delete匹配使用过程详解 什么是new和delete 在C++中使用new和delete可以动态地分配和释放内存。 new运算符从堆中分配一块大小的内存,而delete运算符则将分配的内存释放。 new的使用 我们可以使用new运算符动态地分配堆内存。其中,new会在堆中分配指定大小的内存,并返回该内存的地址,方便我们进行后续的使用。 以…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部