最近在尝试着写一个简单的C语言编译器,于是先写了一个四则运算表达式来练练手。
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
/**************************************************************************
int CheckNum(char *c)
输入参数:
char *c: 输入的字符串
返回参数:
0:字符串中有不符合规定的字符
1: 字符串字符符合规定,没有不符合规定的字符.
功能:
检查字符串中有否除了 0-9, +,-,*,/,(,),之外的其他字符,
如果有,则返回0, 表示出现错误。
若没有,则返回1,字符串内容合法。
**************************************************************************/
int CheckNum(char *c)
{
char *s=c;
while(*s!='\0'){
if((*s>='0' && *s<='9') || *s=='+' ||*s=='-' || *s=='*' || *s=='/' ||*s=='.' || *s=='(' || *s==')' ){
s++;
}else{
printf("错误:数字 %s 里面有不符合规范的字符。\n",c);
return ;
}
}
return ;
}
/**************************************************************************
double StrToNum(char *c)
输入参数:
char *c :由数字和小数点组成的字符,用以转换成double型的数值。
返回参数:
num:返回转换好的值。
功能:
将输入的字符串转化成Double型的浮点数
***************************************************************************/
double StrToNum(char *c)
{
if(CheckNum(c)==){
return -;
}
double num=;
int len=strlen(c);
int start=,fla=; //start是字符串的数字开始的位置,fla标记是否是负数
if(*c=='-'){
start=;
fla=-;
}
num=c[start]-'0';
int t=-; //小数部分计算过程中10的指数部分的值
bool hasPoint=false;
for(int i=start+;i<len;i++){
if(c[i]=='.'){
hasPoint=true;
continue;
}
if(hasPoint){
num=num+(c[i]-'0')*pow(,t);
t--;
}else{
num=num*+c[i]-'0';
}
}
return num*fla;
}
/**************************************************************************
int MyRemove(char *s,int len,int index){
输入参数:
char *s :输入的字符串
int len :字符串的长度
int index:需要移动的起始位置
功能:
将输入的字符串该位置的字符删掉,移动后面的字符位置
***************************************************************************/
int MyRemove(char *s,int len,int index){
int i;
for(i=index;i<len-;i++){
s[i]=s[i+];
}
s[i]='\0';
return len-;
}
/**************************************************************************
int MyRemove(double *s,int len,int index){
输入参数:
char *s :输入的数组
int len :数组的长度
int index:需要移动的起始位置
功能:
将输入的数组该位置的数字删掉,移动后面的数字位置
***************************************************************************/
int MyRemove(double *s,int len,int index){
for(int i=index;i<len-;i++){
s[i]=s[i+];
}
return len-;
}
/**************************************************************************
double MyCalculate(char *c)
输入参数:
char *c :即将进行运算的字符串型数学表达式。如3.5+(2*3/5)
返回参数:
s[0]:计算结果将放入s[0]中
功能:
将输入的字符串中的数字分别调用convnum(char *c)函数进行数值变换,再将其依
次存入doulbe s[i]中,将加减乘除运算符依次存入字符串符号数组 char f[i]中,
然后如果遇到括号,则将括号内的字符串存入另一字符数组中,然后用此
good(char *c) 递归函数进行递归运算。 然后根据先乘除,后加减的顺序对已
存入数组的数值根 据存入字符串符号数组的运算符进行运算。结果存入s[0]中。
返回最终结果。
***************************************************************************/
double MyCalculate(char *c)
{
//puts(c);
double digit[]; //四则运算的数字
char symbol[]; //四则运算的符号
int di=; //保存数字数组的序号
int si=; //保存字符数组的序号
int ni=; //记录需要转化成数字的字符串的序号
while(*c!='\0'){
char num[];
switch(*c){
case '+':
case '-':
case '*':
case '/':
symbol[si++]=*c;
if(*(c-)!=')'){
num[ni]='\0';
ni=;
digit[di++]=StrToNum(num);
}
break;
case '(':
{
int k=;
char str[];
int j=;
while(k>){
c++;
str[j++]=*c;
if(*c=='('){
k++;
}else if(*c==')'){
k--;
}
}
str[j-]='\0';
digit[di++]=MyCalculate(str);
break;
}
default:
num[ni++]=*c;
if(*(c+)=='\0'){
num[ni]='\0';
ni=;
digit[di++]=StrToNum(num);
}
break;
}
c++;
}
symbol[si]='\0';
for(int i=;i<si;i++){
if(symbol[i]=='*'){
digit[i+]=digit[i]*digit[i+];
di=MyRemove(digit,di,i);
si=MyRemove(symbol,si,i);
}else if(symbol[i]=='/'){
digit[i+]=digit[i]/digit[i+];
di=MyRemove(digit,di,i);
si=MyRemove(symbol,si,i);
}
}
for(int i=;i<si;i++){
if(symbol[i]=='+'){
digit[i+]=digit[i]+digit[i+];
di=MyRemove(digit,di,i);
si=MyRemove(symbol,si,i);
}else if(symbol[i]=='-'){
digit[i+]=digit[i]-digit[i+];
di=MyRemove(digit,di,i);
si=MyRemove(symbol,si,i);
}
}
return digit[];
}
int main()
{
char str[],s1[];
//2.3*((2+3)*3+1)+11
while(scanf("%s",s1)!=EOF){
//printf("-----%d\n",strlen(s1));
strcat(str,s1);
}
puts(str);
printf("%s = %lf\n",str,MyCalculate(str));
return ;
}