如何用C语言写一个栈计算器?要求能实现带小数带括号的四则运算,以及幂运算
下面是一个用C语言编写的栈计算器的示例代码,可以实现带小数、带括号的四则运算和幂运算:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
// 定义栈结构
typedef struct {
double* stack;
int top;
int capacity;
} Stack;
// 初始化栈
void initStack(Stack* s, int capacity) {
s->stack = (double*)malloc(capacity * sizeof(double));
s->top = -1;
s->capacity = capacity;
}
// 判断栈是否为空
int isEmpty(Stack* s) {
return s->top == -1;
}
// 判断栈是否已满
int isFull(Stack* s) {
return s->top == s->capacity - 1;
}
// 入栈操作
void push(Stack* s, double value) {
if (isFull(s)) {
printf("Stack is full.\n");
return;
}
s->stack[++s->top] = value;
}
// 出栈操作
double pop(Stack* s) {
if (isEmpty(s)) {
printf("Stack is empty.\n");
return 0;
}
return s->stack[s->top--];
}
// 获取栈顶元素
double top(Stack* s) {
if (isEmpty(s)) {
printf("Stack is empty.\n");
return 0;
}
return s->stack[s->top];
}
// 判断运算符的优先级
int getPriority(char op) {
if (op == '+' || op == '-')
return 1;
if (op == '*' || op == '/')
return 2;
if (op == '^')
return 3;
return 0;
}
// 执行计算
double calculate(double a, double b, char op) {
switch (op) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
case '^':
return pow(a, b);
}
return 0;
}
// 栈计算器函数
double stackCalculator(char* expression) {
Stack numStack; // 数字栈
Stack opStack; // 运算符栈
initStack(&numStack, 100);
initStack(&opStack, 100);
int i = 0;
while (expression[i] != '\0') {
if (isdigit(expression[i])) {
double num = 0;
while (isdigit(expression[i])) {
num = num * 10 + (expression[i] - '0');
i++;
}
if (expression[i] == '.') {
i++;
double decimal = 0.1;
while (isdigit(expression[i])) {
num = num + (expression[i] - '0') * decimal;
decimal /= 10;
i++;
}
}
push(&numStack, num);
} else if (expression[i] == '(') {
push(&opStack, expression[i]);
i++;
} else if (expression[i] == ')') {
while (top(&opStack) != '(') {
char op = pop(&opStack);
double b = pop(&numStack);
double a = pop(&numStack);
double result = calculate(a, b, op);
push(&numStack, result);
}
pop(&opStack); // 弹出左括号
i++;
} else if (expression[i] == '+' || expression[i] == '-' || expression[i] == '*' ||
expression[i] == '/' || expression[i] == '^') {
while (!isEmpty(&opStack) && getPriority(top(&opStack)) >= getPriority(expression[i])) {
char op = pop(&opStack);
double b = pop(&numStack);
double a = pop(&numStack);
double result = calculate(a, b, op);
push(&numStack, result);
}
push(&opStack, expression[i]);
i++;
} else {
i++;
}
}
while (!isEmpty(&opStack)) {
char op = pop(&opStack);
double b = pop(&numStack);
double a = pop(&numStack);
double result = calculate(a, b, op);
push(&numStack, result);
}
double finalResult = pop(&numStack);
free(numStack.stack);
free(opStack.stack);
return finalResult;
}
int main() {
char expression[100];
printf("请输入表达式:");
fgets(expression, sizeof(expression), stdin);
double result = stackCalculator(expression);
printf("计算结果:%lf\n", result);
return 0;
}
上述代码中使用两个栈,一个用于存储数字,另一个用于存储运算符。通过遍历表达式字符串,将数字和运算符依次入栈,并进行相应的计算操作,最后得到最终的计算结果。请注意,代码中对于错误情况的处理比较简单,可以根据实际需求进行适当修改和完善。
使用C语言实现栈计算器的示例代码。该代码支持带小数、带括号的四则运算和幂运算。该代码使用栈数据结构来实现计算器功能。
```c
c
Copy
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define MAX_STACK_SIZE 100 /* 栈的最大容量 */
/* 定义栈结构体 */
typedef struct {
double items[MAX_STACK_SIZE];
int top;
} Stack;
/* 初始化栈 */
void init_stack(Stack *s) {
s->top = -1;
}
/* 判断栈是否为空 */
int is_empty(Stack *s) {
return s->top == -1;
}
/* 判断栈是否已满 */
int is_full(Stack *s) {
return s->top == MAX_STACK_SIZE - 1;
}
/* 将元素压入栈 */
void push(Stack *s, double value) {
if (is_full(s)) {
printf("Stack Overflow\n");
exit(1);
}
s->top++;
s->items[s->top] = value;
}
/* 从栈中弹出元素 */
double pop(Stack *s) {
if (is_empty(s)) {
printf("Stack Underflow\n");
exit(1);
}
double value = s->items[s->top];
s->top--;
return value;
}
/* 获取栈顶元素 */
double peek(Stack *s) {
if (is_empty(s)) {
printf("Stack Underflow\n");
exit(1);
}
return s->items[s->top];
}
/* 判断字符是否为运算符 */
int is_operator(char ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^';
}
/* 获取运算符的优先级 */
int get_precedence(char ch) {
switch (ch) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
default:
return 0;
}
}
/* 执行二元运算 */
double perform_operation(double num1, double num2, char operator) {
switch (operator) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return num1 / num2;
case '^':
return pow(num1, num2);
default:
return 0.0;
}
}
/* 计算表达式 */
double evaluate_expression(const char *expr) {
Stack operand_stack; /* 操作数栈 */
Stack operator_stack; /* 运算符栈 */
init_stack(&operand_stack);
init_stack(&operator_stack);
int i = 0;
while (expr[i] != '\0') {
/* 如果当前字符是空格,忽略它 */
if (expr[i] == ' ') {
i++;
continue;
}
/* 如果当前字符是数字或小数点,获取完整的数值并将其推入操作数栈 */
if (isdigit(expr[i]) || expr[i] == '.') {
double value = 0.0;
int decimal_places = 0;
while (isdigit(expr[i]) || expr[i] == '.') {
if (expr[i] == '.') {
decimal_places = 1;
} else {
value = value * 10 + (expr[i] - '0');
if (decimal_places > 0) {
decimal_places++;
}
}
i++;
}
if (decimal_places > 0) {
value = value / pow(10, decimal_places - 1);
}
push(&operand_stack, value);
continue;
}
/* 如果当前字符是左括号,将其推入运算符栈 */
if (expr[i] == '(') {
push(&operator_stack, expr[i]);
i++;
continue;
}
/* 如果当前字符是右括号,从运算符栈中弹出运算符和操作数,执行相应的操作直到遇到左括号 */
if (expr[i] == ')') {
while (peek(&operator_stack) != '(') {
char operator = (char)pop(&operator_stack);
double num2 = pop(&operand_stack);
double num1 = pop(&operand_stack);
double result = perform_operation(double)num1, (double)num2, operator);
push(&operand_stack, result);
}
pop(&operator_stack);
i++;
continue;
}
/* 如果当前字符是运算符,将其推入运算符栈。如果当前运算符的优先级低于或等于栈顶运算符的优先级,则从运算符栈中弹出运算符和操作数,执行相应的操作 */
if (is_operator(expr[i])) {
while (!is_empty(&operator_stack) && get_precedence(expr[i]) <= get_precedence(peek(&operator_stack))) {
char operator = (char)pop(&operator_stack);
double num2 = pop(&operand_stack);
double num1 = pop(&operand_stack);
double result = perform_operation((double)num1, (double)num2, operator);
push(&operand_stack, result);
}
push(&operator_stack, expr[i]);
i++;
continue;
}
/* 如果表达式中存在未知字符,则无法计算 */
printf("Invalid Character Found: %c\n", expr[i]);
exit(1);
}
/* 如果表达式已经扫描完但是运算符栈不为空,则从运算符栈中弹出运算符和操作数,执行相应的操作 */
while (!is_empty(&operator_stack)) {
char operator = (char)pop(&operator_stack);
double num2 = pop(&operand_stack);
double num1 = pop(&operand_stack);
double result = perform_operation((double)num1, (double)num2, operator);
push(&operand_stack, result);
}
/* 最后,操作数栈中的唯一元素即为结果 */
return pop(&operand_stack);
}
int main() {
char expr[MAX_STACK_SIZE];
printf("Enter an expression: ");
fgets(expr, MAX_STACK_SIZE, stdin);
double result = evaluate_expression(expr);
printf("Result: %.2lf\n", result);
return 0;
}
```
代码中的主要思路是将表达式中的数字和运算符分别推入操作数栈和运算符栈,并在需要时从栈中弹出元素进行计算。该代码可以读入带括号、带小数的四则运算表达式,支持幂运算,能输出结果精确到小数点后两位。
有时候会遇到这样一种情况,当上层人员将一个功能交给下层程序员完成时,上层程序员和下层程序员同步工作,这个时候该功能函数并未完成,这个时候上层程序员可以定义一个API来交给下层程序员,而上层程序员只要关心该API就可以了而无需关心具体实现,具体实现交给下层程序员完成即可(这里的上层和下层程序员不指等级关系,而是项目的分工关系)。这种情况下就会用到回调函数(Callback Function),现在假设程序员A需要一个FFT算法,这个时候程序员A将FFT算法交给程序员B来完成,现在来让实现这个过程:
#include <stdio.h>
int InputData[100]={0};
int OutputData[100]={0};
/*定义回调函数*/
void CallBack_FFT_Function(int *inputData,int *outputData,int num)
{
while(num--)
{
printf("www.zhiguoxin.cn\r\n");
}
}
/*用来注册回调函数的功能函数*/
void TaskA(void (*fft)(int*,int*,int))
{
fft(InputData,OutputData,5);
}
int main(void)
{
/*注册FFT_Function作为回调*/
TaskA(CallBack_FFT_Function);
return 0;
}
这个例子是不是跟上面的那个例子是相同的,只是我们在这里换了一种说法而已。也就是我们硬件层实现的某个功能,当然可以在应用层直接调用,但是这种做法太low了,一看就是小学生的水平,或者说硬件层的东西应用层根本不需要关心,这就是分层的思想。硬件的东西就给硬件工程师做,应用工程师只关心自己的需要实现的任务。这也就是驱动工程师和应用工程师的区别,我硬件工程师只需要写好对应的API函数,你应用层直接调用就好了,你不需要关心这个API函数的内部是怎么实现的。而这两者之间的桥梁就是回调函数。而回调函数的形参就是函数指针,所以本篇最开始讲的是函数指针,只要你函数指针明白了,你就会写回调函数,也就理解了这其中到底只一个什么原理。
上面的代码中CallBack_FFT_Function
是回调函数,该函数的形参为一个函数指针,TaskA
是用来注册回调函数的功能函数。可以看到用来注册回调函数的功能函数中申明的函数指针必须和回调函数的类型完全相同。
#include<stdio.h>
#include<stdlib.h>
// 定义栈的数据结构
typedef struct{
int top; // 栈顶
double *data; // 存储数据的数组
int capacity; // 栈的容量
} Stack;
// 初始化栈
Stack* initStack(int capacity){
Stack *stack = (Stack*)malloc(sizeof(Stack));
stack->top = -1;
stack->data = (double*)malloc(capacity*sizeof(double));
stack->capacity = capacity;
return stack;
}
// 判断栈是否为空
int isEmpty(Stack *stack){
return stack->top == -1;
}
// 判断栈是否已满
int isFull(Stack *stack){
return stack->top == stack->capacity - 1;
}
// 入栈
void push(Stack *stack, double value){
if(isFull(stack)){
printf("Stack Overflow!\n");
return;
}
stack->data[++stack->top] = value;
}
// 出栈
double pop(Stack *stack){
if(isEmpty(stack)){
printf("Stack Underflow!\n");
return -1;
}
return stack->data[stack->top--];
}
// 获取栈顶元素
double top(Stack *stack){
if(isEmpty(stack)){
printf("Stack Underflow!\n");
return -1;
}
return stack->data[stack->top];
}
// 释放栈的内存空间
void freeStack(Stack *stack){
free(stack->data);
free(stack);
}
// 判断运算符的优先级
int getPriority(char operator){
if(operator == '+' || operator == '-'){
return 1;
}else if(operator == '*' || operator == '/'){
return 2;
}else if(operator == '^'){
return 3;
}
return 0;
}
// 执行运算
double performOperation(double operand1, double operand2, char operator){
switch(operator){
case '+':
return operand1 + operand2;
case '-':
return operand1 - operand2;
case '*':
return operand1 * operand2;
case '/':
return operand1 / operand2;
case '^':
return pow(operand1, operand2);
}
return 0;
}
// 判断是否是操作符
int isOperator(char c){
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
}
// 计算表达式的值
double evaluateExpression(char *expression){
Stack *operandStack = initStack(strlen(expression));
Stack *operatorStack = initStack(strlen(expression));
for(int i=0; expression[i]!='\0'; i++){
if(expression[i] == ' '){
continue;
}else if(isdigit(expression[i])){
// 处理数字,先找到完整的数字
double operand = 0;
while(i<strlen(expression) && (isdigit(expression[i]) || expression[i] == '.')){
if(expression[i] == '.'){
double fraction = 1;
i++;
while(i<strlen(expression) && isdigit(expression[i])){
fraction /= 10.0;
operand = operand + fraction * (expression[i] - '0');
i++;
}
}else{
operand = operand * 10 + (expression[i] - '0');
i++;
}
}
i--;
push(operandStack, operand);
}else if(expression[i] == '('){
// 处理左括号,直接入栈
push(operatorStack, expression[i]);
}else if(expression[i] == ')'){
// 处理右括号,从操作数栈和运算符栈中弹出元素,进行计算直到遇到左括号
while(!isEmpty(operatorStack) && top(operatorStack) != '('){
double operand2 = pop(operandStack);
double operand1 = pop(operandStack);
char operator = pop(operatorStack);
double result = performOperation(operand1, operand2, operator);
push(operandStack, result);
}
pop(operatorStack); // 弹出左括号
}else if(isOperator(expression[i])){
// 处理运算符,弹出运算符栈中优先级更高或相等的运算符进行计算,再将当前运算符入栈
while(!isEmpty(operatorStack) && top(operatorStack) != '(' && getPriority(expression[i]) <= getPriority(top(operatorStack))){
double operand2 = pop(operandStack);
double operand1 = pop(operandStack);
char operator = pop(operatorStack);
double result = performOperation(operand1, operand2, operator);
push(operandStack, result);
}
push(operatorStack, expression[i]);
}else{
printf("Invalid Character: %c\n", expression[i]);
freeStack(operandStack);
freeStack(operatorStack);
return 0;
}
}
// 将运算符栈中剩余的运算符进行计算
while(!isEmpty(operatorStack)){
double operand2 = pop(operandStack);
double operand1 = pop(operandStack);
char operator = pop(operatorStack);
double result = performOperation(operand1, operand2, operator);
push(operandStack, result);
}
double finalResult = pop(operandStack);
freeStack(operandStack);
freeStack(operatorStack);
return finalResult;
}
int main(){
char expression[100];
printf("请输入四则运算表达式(带小数和括号):");
fgets(expression, sizeof(expression), stdin);
double result = evaluateExpression(expression);
printf("结果为:%f\n", result);
return 0;
}
这是一个使用C语言编写的栈计算器,它可以实现带小数和括号的四则运算,以及幂运算。输入一个四则运算表达式,它会输出计算后的结果。
算法的基本思路是: 1. 定义一个栈的数据结构,包含栈顶指针和存储数据的数组。 2. 初始化两个栈,一个用于存储操作数,一个用于存储运算符。 3. 从左到右遍历表达式的每个字符: - 如果是数字,将完整的数字解析出来,然后入操作数栈。 - 如果是左括号,直接入运算符栈。 - 如果是右括号,从操作数栈和运算符栈中弹出元素,进行计算直到遇到左括号。 - 如果是运算符,弹出运算符栈中优先级更高或相等的运算符进行计算,再将当前运算符入运算符栈。 - 如果是其他字符,输出错误信息,退出计算。 4. 将运算符栈中剩余的运算符进行计算。 5. 弹出操作数栈中的结果,输出最终的计算结果。
代码中的evaluateExpression函数就是进行表达式计算的核心函数,它利用两个栈实现了计算器的功能。通过这个函数,可以实现简单的四则运算、幂运算,支持小数和括号。
请注意,这个代码中没有处理负号作为运算符的情况。如果有需要,可以在代码中添加相关处理逻辑。
希望这个代码对你有帮助!