识别运算表达式,当识别到=号后计算结果,如果识别不到=输入,则报错。同时,对错误输入进行处理,包含处理:输入括号数量错误、输入非数字错误、非运算符错误。
通过使用动态栈,主要练习C语言栈相关操作。
1 栈操作头文件
/***********************************************************
@File name: stack.h
@Author: xueya /DreCoder
@Date: 2022/8/5 17:04
@Version:1.0
@Description: 栈相关操作头文件
@other:
@Copyright (c) 2022 , All rights reserved.
***********************************************************/
#ifndef XUEYA_CTEST_STACK_H
#define XUEYA_CTEST_STACK_H
#include <malloc.h>
typedef enum BOOL{
false,true
}bool;
typedef struct Node{
char data;
struct Node * pNext;
}NODE,*pNODE;
typedef struct NodeInt{
int data;
struct NodeInt * pNext;
}NODEINT,*pNODEINT;
typedef struct Stack{
pNODE pTop;
pNODE pBottom;
}STACK,*pSTACK;
typedef struct StackInt{
pNODEINT pTop;
pNODEINT pBottom;
}STACKINT,*pSTACKINT;
void initStack(pSTACK pS);
void initStackInt(pSTACKINT pS);
void pushStackInt(pSTACKINT pS,int value);
void pushStack(pSTACK pS,char value);
char stack_pop(pSTACK p_stack);
int stack_popInt(pSTACKINT p_stack);
bool stack_is_empty(pSTACK p_stack);
bool stack_is_emptyInt(pSTACKINT p_stack);
#endif //XUEYA_CTEST_STACK_H
2 栈操作相关函数实现
使用两个栈,一个栈为保存数据的栈,一个栈为保存运算符的栈.
/***********************************************************
@File name: stack.c
@Author: xueya /DreCoder
@Date: 2022/8/5 17:04
@Version:1.0
@Description: 栈操作相关函数操作
@other:
@Copyright (c) 2022 , All rights reserved.
***********************************************************/
#include "stack.h"
#include <stdio.h>
void initStack(pSTACK pS)
{
pS->pTop=(pNODE) malloc(sizeof (NODE));
if( pS->pTop==NULL ){
printf("memory malloc failed\n");
return;
}else {
pS->pBottom=pS->pTop;
pS->pBottom->pNext=NULL;
}
}
void initStackInt(pSTACKINT pS)
{
pS->pTop=(pNODEINT) malloc(sizeof (NODEINT));
if( pS->pTop==NULL ){
printf("memory malloc failed\n");
return;
}else {
pS->pBottom=pS->pTop;
pS->pBottom->pNext=NULL;
}
}
void pushStack(pSTACK pS,char value)
{
pNODE pNew=(pNODE) malloc(sizeof (NODE));
pNew->data=value;
pNew->pNext=pS->pTop;
pS->pTop=pNew;
}
void pushStackInt(pSTACKINT pS,int value)
{
pNODEINT pNew=(pNODEINT) malloc(sizeof (NODEINT));
pNew->data=value;
pNew->pNext=pS->pTop;
pS->pTop=pNew;
}
//把p_stack所指向的栈出栈一次
//返回出栈成功还是失败
//
char stack_pop(pSTACK p_stack)
{
char ret;
if (stack_is_empty(p_stack))
{
return ret=16;
}
pNODE temp=p_stack->pTop;//保存栈顶指针,用于释放
ret=p_stack->pTop->data;
p_stack->pTop=temp->pNext;
free(temp);
temp=NULL;
return ret;
}
int stack_popInt(pSTACKINT p_stack)
{
pNODEINT temp=p_stack->pTop;//保存栈顶指针,用于释放
int val=p_stack->pTop->data;
p_stack->pTop=temp->pNext;
free(temp);
temp=NULL;
return val;
}
bool stack_is_empty(pSTACK p_stack)
{
if( p_stack->pTop==p_stack->pBottom ) {
return true;
}else {
return false;
}
}
bool stack_is_emptyInt(pSTACKINT p_stack)
{
if( p_stack->pTop==p_stack->pBottom ) {
return true;
}else {
return false;
}
}
3 计算相关操作实现
/***********************************************************
@File name: xueya_Ctest05.c
@Author: xueya /DreCoder
@Date: 2022/8/1 11:57
@Version:1.0
@Description: 计算器程序,能接收用户输入的四则运算计算式,
直到用户输入等号=,把结果打印出来
要求:对输入做验证,非法的输入需要提示,支持的运算符包含+-*\/(/)
@other:
@Copyright (c) 2022 , All rights reserved.
***********************************************************/
#include <stdio.h>
#include "stack.h"
#include <string.h>
#include <stdlib.h>
void str_append_char(char * str,char ch);
char * str_to_postfix(char * str);
int calValue(char * str);
bool JudgeDataByUser(char * str);
int main()
{
char user_str[100];//转换后的输入字符串
char user_strAfter[100];
memset(user_strAfter,0,100);
char * postfix=(char *) malloc(sizeof (char)*200);
int length=0,result=0;
system("clear");
printf("\n");
printf("============================================================\n");
printf("| Please enter a numeric expression after >> |\n");
printf("| Enter the equal sign and press enter to |\n");
printf("| calculate the result. |\n");
printf("| This calculation program only supports |\n");
printf("| integer calculation. |\n");
printf("| eg.12*(5+9-10/2)-5= |\n");
printf("=============================================================\n");
printf("\n");
printf("Please enter a numeric expression:\n");
printf(">>");
scanf("%s",user_str);
if( !JudgeDataByUser(user_str )){
printf("Input error, please try again!\n");
return -1;
}
length=strlen(user_str);
strncpy(user_strAfter,user_str, length-1);
str_append_char(user_strAfter,'\0');
//printf("Afterlen=%d\n", strlen(user_strAfter));
postfix=str_to_postfix(user_strAfter);
result=calValue(postfix);
printf("=============================================================\n");
printf("\n");
printf(">> %s%d\n\n",user_str,result);
printf("End of calculation, thank you for using! \n");
printf("=============================================================\n");
return 0;
}
void str_append_char(char * str,char ch)
{
// printf("append_char=%s\n",str);
while (*str) str++;
*str++=ch;
*str='\0';
}
bool JudgeDataByUser(char * str)
{
int length=strlen(str),char_sum=0,brackets=0;
if( *(str+length-1)!='=' ){
return false;
}
while (*str) {
if ((*str >='(' && *str <='+' )||(*str>='/' && *str<='9')||(*str=='-')||(*str=='=')){
if( *str =='(')
brackets=1;
if( *str ==')')
brackets=2;
char_sum++;
if (length == char_sum) {
if (brackets == 0) {
return true;
} else {
if (brackets == 2) {
return true;
}
}
}
}
str++;
}
return false;
}
char * str_to_postfix(char * str)
{
STACK S;
initStack(&S);//初始化栈
char postfix[200]={0};
char * ret_str=(char *) malloc(sizeof (char)*200);
int i=0;
int length= strlen(str);
char pop_char;
while (i<length)
{
char ch =str[i];
switch (ch) {
case '+':
case '-':
{
while ((stack_is_empty(&S)==false)&&((S.pTop->data!='(')))
str_append_char(postfix, stack_pop(&S));
pushStack(&S,ch);
i++;
break;
}
case '*':
case '/':
{
while ((stack_is_empty==false)&&((S.pTop->data=='*')||(S.pTop->data=='/')))
str_append_char(postfix, stack_pop(&S));
pushStack(&S,ch);
i++;
break;
}
case '(':
{
pushStack(&S,ch);
i++;
break;
}
case ')': //遇到右括号进行出栈,若为空,返回null
{
pop_char=stack_pop(&S);
while ((pop_char!=16) && (pop_char!='('))
{
str_append_char(postfix,pop_char);
pop_char=stack_pop(&S);
}
i++;
break;
}
default:
{
while (i<length&&(ch>='0'&&ch<='9'))//处理数字
{
str_append_char(postfix,(char)ch);
i++;
if( i<length ){
ch=str[i];
}
}
str_append_char(postfix,' ');
}
}
}
while (stack_is_empty(&S)==false)
str_append_char(postfix,stack_pop(&S));
//str_append_char(postfix,'\0');
strcpy(ret_str,postfix);
return ret_str;
}
int calValue(char * str)
{
STACKINT S;
initStackInt(&S);//初始化栈
//printf("strlen=%d\n", strlen(str));
int value=0,length= strlen(str);
char nums[10];
for (int i = 0; i <length ; i++) {
int index=0;
char ch=str[i];
if( ch>='0' && ch <='9'){
while (ch!=' ')
{
nums[index]=ch;
index++;
i++;
ch=str[i];
}
nums[index]='\0';
int re= atoi(nums);
pushStackInt(&S, re);
}else if( ch!=' ' ){
int num2=stack_popInt(&S);
int num1=stack_popInt(&S);
switch (ch) {
case '+':
value=num1+num2;
break;
case '-':
value=num1-num2;
break;
case '*':
value=num1*num2;
break;
case '/':
if(!num2){
value=0;
printf("除数不能为0\n");
break;
}else{
value=num1/num2;
}
break;
}
pushStackInt(&S,value);
}
}
return stack_popInt(&S);
}