1 回答

TA贡献1853条经验 获得超9个赞
不知道怎么左对齐,//后面是英文注释///后面是中文注释 给采纳!!
// EX6_08.CPP
// A program to implement a calculator
#include <stdio.h> // For input/output
#include <stdlib.h> // For the exit() function
#include <ctype.h> // For the isdigit() function
#include <string.h> // For the strcpy() function
void eatspaces(char * str); // Function to eliminate blanks
double expr(char * str); // Function evaluating an expression
double term(char * str, int * pindex); // Function analyzing a term
double number(char * str, int * pindex); // Function to recognize a number
char * extract(char * str, int * index); // Function to extract a substring
const int MAX = 80; // Maximum expression length including '\0'
int main(void)
{
char buffer[MAX]; // Input area for expression to be evaluated
char c;
int j,i;
printf("Welcome to your friendly calculator.\n");
printf("Enter an expression, or an empty line to quit.\n");
for(;;)///无开始无终止只有过程,就是不停的循环,保证可以连续输入好几个式子,如先求1+2回车直接3+2再回车,可以多次求
{///式子是一步一步来的,就是说不进行完这个语句是不会进行下一个的
i=0;
scanf("%c",&c); ///捕捉第一个数是c// Read an input line
while(c!='\n')
{
buffer[i++]=c;///,i++是先运算后自加,++i是先自加后运算,所以第一个数放在buffer[0]处
scanf("%c",&c);
}///把式子放在这个数列中,while控制回车时式子结束,此时i是
buffer[i]='\0';///式子最后是一个\o作为标志"\0代表字符数串的结束标志,最后一个在i-1的位置
eatspaces(buffer);///对式子去空格处理 // Remove blanks from input
if(!buffer[0]) // Empty line ends calculator
return 0;///已经去过空格了,buffer[0]应该是有值的,但是没有的话就直接结束,返还0
printf( "\t= %f\n\n",expr(buffer)); ///结果是expr分函数return的结果 // Output value of expression
}
}
// Function to eliminate blanks from a string
void eatspaces(char * str)///预处理,把指向数组的指针设为*str,其中数组中数的地址都是相连的,char数组每个地址差1,int数组每个差2依次类推,其中char型的指针加1就是加一,int型的加一是加二
{
int i=0; // 'Copy to' index to string
int j=0; // 'Copy from' index to string
while((*(str+i) = *(str+j++)) != '\0')///这里是对*(str+i)的一个赋值,没有空格时每次i都加1式子有空格时(str+i)和(str+j++)是相等的,
/// 当有空格时i不加一,就让空格这个地址等于下一个地址,即把式子向前推了一个字符,直到\0 // Loop while character copied is not \0
if(*(str+i) != ' ') // Increment i as long as
i++; // character is not a blank
return;
}
// Function to evaluate an arithmetic expression
double expr(char * str)///真正处理,对加减的分函数
{
double value = 0; ///value是结果,也就是真实值 // Store result here
int index = 0; // Keeps track of current character position
value = term(str, &index);///先解决第一步,因为数字还是char型根本没法算,先把第一个数变成数顺便有()*/都做完了直到看见-+ // Get first term
for(;;) ///保证了多加的情况,后同 // Infinite loop, all exits inside
{
switch(*(str+index++)) ///通过加数组对应的地址时数组一个一个往后推,碰到\0 + -做判断 其他符号输出错误 // Choose action based on current character
{
case '\0': ///一直到最后的标记,输出 // We're at the end of the string
return value; // so return what we have got
case '+': ///先把第一个数变成数然后有()就先()有/*就先/* 最后不都没有了就到-+了然后-+后面的也要先乘除啊,就value += term(str, &index);这样也能让后面的也能变成数,也能让后面的先*/依次类推 // + found so add in the
value += term(str, &index); // next term
break;
case '-': // - found so subtract
value -= term(str, &index); // the next term
break;
default: // If we reach here the string
printf("Arrrgh!*#!! There's an error.\n");///其他符号输出错误因为先进行的*、和()运算,所以再不是-+就一定错了
exit(1);
}
}
}
// Function to get the value of a term
double term(char * str, int * pindex)///对乘除的分函数
{
double value = 0; // Somewhere to accumulate the result
value = number(str, pindex); // Get the first number in the term
// Loop as long as we have a good operator
while((*(str+(*pindex))=='*')||(*(str+(*pindex))=='/'))///进来的是/或者*才继续,不然直接输出了
{
if(*(str+(*pindex))=='*') // If it's multiply,
{
++(*pindex);///是乘先加,就是乘的是后面的
value *= number(str, pindex); ///通过这样,先括号后乘除解决第一步以后的 // multiply by next number
}
if(*(str+(*pindex))=='/') // If it's divide,
{
++(*pindex);
value /= number(str, pindex); // divide by next number
}
}
return value; // We've finished, so return what we've got
}
// Function to recognize a number in a string
double number(char * str, int * pindex)///对(的分函数
{
double value = 0.0; // Store the resulting value
char * psubstr; // Pointer for substring
if(*(str + (*pindex)) == '(') // Start of parentheses
{
++(*pindex);
psubstr = extract(str, pindex);///先看后括号 // Extract substring in brackets
value = expr(psubstr); ///打回来以后再直接用大的顺序进行计算 // Get the value of the substring
return value; // Return substring value
}
///以下是将我们在数组中定义为char的数变为int形式
while(isdigit(*(str+(*pindex)))) ///isdidit是调用的<ctype.h> 这个库函数的一种函数,判断字符是否为阿拉伯数字 // Loop accumulating leading digits
value=10*value + (*(str+(*pindex)++) - 48);///因为ASC码48就是'0',也就是说'0'的值是48,而后依次是'1'到'9'。这样正好是char型的减去48就是它对应的int值
///这样层层推进,直到value是这个数为止(如125就会定义为三个char变量,先判断1是阿拉伯数字,让它乘10加2就成12,再看5是阿拉伯数字,12乘10加5就成了125,变成阿拉伯数字了)
// Not a digit when we get to here
if(*(str+(*pindex))!='.') ///如果没有小数点可以回去了,这里小数点显然无法通过上面的isdigit,就是会有123.45这原来是六个字符(1/2/3/。/4/5)通过上面变成了(123/。/4/5)其中4/5还是char型 // so check for decimal point
return value; // and if not, return value
double factor = 1.0; // Factor for decimal places
while(isdigit(*(str+(++(*pindex)))))///当检测到小数点后面是数的时候就会进行 // Loop as long as we have digits
{
factor *= 0.1; // Decrease factor by factor of 10
value=value + (*(str+(*pindex))-48)*factor;///这里直接第一轮123加0.1*4,第二轮再加0.01*5 // Add decimal place
}
return value; // On loop exit we are done
if(*(str+(*pindex))!='.') // so check for decimal point
return value; ///在此看后面有无小数点,没有就回去,有的话就双小数点,没有返回值发生错误 // and if not, return value
}
// Function to extract a substring between parentheses
// (requires string.h)
char * extract(char * str, int * pindex)///对)的分函数
{
char buffer[MAX]; // Temporary space for substring
char * pstr = NULL; ///代表一个空指针 // Pointer to new string for return
int numL = 0; // Count of left parentheses found
int bufindex = *pindex;///这个定义是 bufindex直接指向当前所指了 // Save starting value for index
do///多次循环
{
buffer[(*pindex) - bufindex] = *(str + (*pindex));///这相当于重新引进了一套目的是不会混乱
switch(buffer[(*pindex) - bufindex])
{
case ')':///当遇到)时
if(numL == 0)///第一次就代表只有()没有套((()))这种情况,((()))会一层一层的算
{
buffer[(*pindex) - bufindex] = '\0'; ///就直接算()里面的把)当成结束去算 // Replace ')' with '\0'
++(*pindex);
pstr = (char *) malloc((*pindex) - bufindex + 1);///malloc是申请使用((*pindex) - bufindex + 1)大小的空间然后指向这个空间的指针设为pstr
if (!pstr)///指针无效就会运行下面这个
{
printf("Memory allocation failed, program terminated.") ;
exit(1);
}
strcpy(pstr, buffer); /// strcpy也是一个函数复制字符串买就是吧buffer的复制到 pstr中去// Copy substring to new memory
return pstr; ///把()里面的东西直接打回去。 // Return substring in new memory
}
else
numL--; // Reduce count of '(' to be matched
break;
case '(':
numL++; ///说明有((()))这样的结构,用numl记录有几个(,有一个)减一个1 // Increase count of '(' to be // matched
break;
}
} while(*(str + (*pindex)++) != '\0'); ///没有)直接结束会输出这句话 // Loop - don't overrun end of string
printf("Ran off the end of the expression, must be bad input.\n");
exit(1);
}
添加回答
举报