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);
}
添加回答
舉報