297 lines
9.3 KiB
C++
297 lines
9.3 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <ctype.h>
|
|
#define MAX 100
|
|
|
|
// === 全域變數宣告 ===
|
|
char input[MAX];
|
|
char postfix[MAX];
|
|
char postfix_1[MAX]; //顯示用
|
|
char stack[MAX];
|
|
double numStack[MAX];
|
|
int top = -1;
|
|
int numTop = -1;
|
|
|
|
// === 函式宣告 ===
|
|
int get_priority(char op);
|
|
int is_operator(char c);
|
|
double calculate(double a, double b, char op);
|
|
void convert_to_postfix();
|
|
double evaluate_postfix();
|
|
double evaluate_infix(char *expr);
|
|
double parse_number(char **expr);
|
|
|
|
int get_priority(char c){
|
|
if(c=='+' || c=='-'){
|
|
return 1;
|
|
}else if(c=='*' || c=='/' || c=='%' ){
|
|
return 2;
|
|
}else if(c=='^' || c=='s' || c=='c' ){
|
|
return 3;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// === 檢查字元是否為運算子 ===
|
|
int is_operator(char c) {
|
|
return (c == '+' || c == '-' || c == '*' || c == '/' || c == '^' || c == '%' ||c == 's' || c == 'c');
|
|
}
|
|
|
|
// === 執行運算 ===
|
|
double calculate(double a, double b, char op) {
|
|
switch(op) {
|
|
case '+': return a + b;
|
|
case '-': return a - b;
|
|
case '*': return a * b;
|
|
case '/':
|
|
if(b != 0) return a / b;
|
|
printf("錯誤:除數不能為零!\n");
|
|
exit(1);
|
|
case '^': return pow(a, b);
|
|
case '%': return (int)a % (int)b;
|
|
|
|
case 's': return sin(b);
|
|
case 'c': return cos(b);
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
//顯示用
|
|
void convert_to_postfix_forprint() {
|
|
int i = 0, j;
|
|
int postfix_index = 0;
|
|
top = -1;
|
|
char number_str[MAX];
|
|
int is_negative;
|
|
|
|
while(input[i] != '\0') {
|
|
if(isdigit(input[i]) || input[i] == '.' || (input[i] == '-' && (i == 0 || input[i-1] == '(' || is_operator(input[i-1])))) {
|
|
// 處理數字(包括負數)
|
|
is_negative = 0;
|
|
int num_len = 0;
|
|
|
|
// 檢查是否為負數
|
|
if(input[i] == '-') {
|
|
is_negative = 1;
|
|
i++;
|
|
}
|
|
|
|
// 收集完整數字字串
|
|
while(input[i] != '\0' && (isdigit(input[i]) || input[i] == '.')) {
|
|
number_str[num_len++] = input[i++];
|
|
}
|
|
number_str[num_len] = '\0';
|
|
i--; // 回退一個位置,因為外層 while 會再加一
|
|
|
|
// 輸出數字
|
|
printf("%s ", number_str);
|
|
if(is_negative) {
|
|
printf("- ");
|
|
}
|
|
|
|
// 將數字加入後序表達式
|
|
for(j = 0; j < num_len; j++) {
|
|
postfix_1[postfix_index++] = number_str[j];
|
|
}
|
|
postfix_1[postfix_index++] = ' ';
|
|
if(is_negative) {
|
|
postfix_1[postfix_index++] = '-';
|
|
postfix_1[postfix_index++] = ' ';
|
|
}
|
|
}
|
|
else if(input[i] == '(') {
|
|
stack[++top] = input[i];
|
|
}
|
|
else if(input[i] == ')') {
|
|
while(top >= 0 && stack[top] != '(') {
|
|
printf("%c ", stack[top]);
|
|
postfix_1[postfix_index++] = stack[top];
|
|
postfix_1[postfix_index++] = ' ';
|
|
top--;
|
|
}
|
|
if(top >= 0) top--;
|
|
}
|
|
else if(is_operator(input[i])) {
|
|
// 如果不是處理負數的減號
|
|
if(input[i] == '+' && input[i-1] == '('){
|
|
|
|
}
|
|
else if(input[i-1] != 'o'){
|
|
if(!(input[i] == '-' && (i == 0 || input[i-1] == '(' || is_operator(input[i-1])))) {
|
|
while(top >= 0 && stack[top] != '(' &&
|
|
(get_priority(stack[top]) > get_priority(input[i]) ||
|
|
(get_priority(stack[top]) == get_priority(input[i]) && input[i] != '^'))) {
|
|
printf("%c ", stack[top]);
|
|
postfix_1[postfix_index++] = stack[top];
|
|
postfix_1[postfix_index++] = ' ';
|
|
top--;
|
|
}
|
|
stack[++top] = input[i];
|
|
}
|
|
}
|
|
|
|
}
|
|
i++;
|
|
}
|
|
|
|
while(top >= 0) {
|
|
printf("%c ", stack[top]);
|
|
postfix_1[postfix_index++] = stack[top];
|
|
postfix_1[postfix_index++] = ' ';
|
|
top--;
|
|
}
|
|
postfix_1[postfix_index] = '\0';
|
|
printf("\n");
|
|
}
|
|
|
|
// === 轉換為後序表達式 ===
|
|
//計算用
|
|
void convert_to_postfix() {
|
|
int i = 0 , j;
|
|
int postfix_index = 0;
|
|
top = -1;
|
|
|
|
while(input[i] != '\0') {
|
|
|
|
if(isdigit(input[i]) || input[i] == '.' || (input[i] == '-' && (i == 0 || input[i-1] == '(' || is_operator(input[i-1])))) { // 檢查是否為數字、小數點或是負號(且是表達式的開始,或緊跟在左括號或運算符後面)
|
|
char *end;
|
|
double num = strtod(&input[i], &end); //strtod 把字串換成浮點數
|
|
int len = end - &input[i]; //計算數字字串的長度 數字末端的記憶體位址減掉首項的記憶體位置
|
|
printf("%.1f ", num);
|
|
for(j = 0; j < len; j++) {
|
|
postfix[postfix_index++] = input[i+j];
|
|
}
|
|
postfix[postfix_index++] = ' ';
|
|
i += len - 1;
|
|
}else if(input[i] == '(') {
|
|
stack[++top] = input[i];
|
|
}
|
|
else if(input[i] == ')') {
|
|
while(top >= 0 && stack[top] != '(') {
|
|
printf("%c ", stack[top]);
|
|
postfix[postfix_index++] = stack[top];
|
|
postfix[postfix_index++] = ' ';
|
|
top--;
|
|
}if(top >= 0) top--;
|
|
}else if(is_operator(input[i])) {
|
|
if(input[i] == '+' && input[i-1] == '('){
|
|
|
|
}else if(input[i-1]!='o' ){
|
|
while(top >= 0 && stack[top] != '(' && (get_priority(stack[top]) > get_priority(input[i]) || (get_priority(stack[top]) == get_priority(input[i]) && input[i] != '^'))) {
|
|
printf("%c ", stack[top]);
|
|
postfix[postfix_index++] = stack[top];
|
|
postfix[postfix_index++] = ' ';
|
|
top--;
|
|
}
|
|
stack[++top] = input[i];
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
while(top >= 0) {
|
|
printf("%c ", stack[top]);
|
|
postfix[postfix_index++] = stack[top];
|
|
postfix[postfix_index++] = ' ';
|
|
top--;
|
|
}
|
|
postfix[postfix_index] = '\0';
|
|
printf("\n");
|
|
}
|
|
|
|
// === 計算後序表達式 ===
|
|
double evaluate_postfix() {
|
|
int i;
|
|
numTop = -1;
|
|
char *token = strtok(postfix, " ");
|
|
|
|
printf("\n計算過程:\n");
|
|
|
|
while(token != NULL) {
|
|
printf("處理標記:'%s'\n", token);
|
|
|
|
if(isdigit(token[0]) || (token[0] == '-' && isdigit(token[1]))) {
|
|
double num = atof(token);
|
|
numStack[++numTop] = num;
|
|
printf("壓入數字:%.2f\n", num);
|
|
}else if(token[0] == 's'|| token[0] == 'c' ){
|
|
if(numTop < 1) {
|
|
printf("運算子 '%c' 缺少足夠的運算元\n", token[0]);
|
|
exit(1);
|
|
}
|
|
double b = numStack[numTop--];
|
|
double result = calculate(0, b, token[0]);
|
|
numStack[++numTop] = result;
|
|
printf("計算:%c %.2f = %.2f\n", token[0], b, result);
|
|
|
|
}else if(is_operator(token[0])) {
|
|
if(numTop < 1) {
|
|
printf("運算子 '%c' 缺少足夠的運算元\n", token[0]);
|
|
exit(1);
|
|
}
|
|
double b = numStack[numTop--];
|
|
double a = numStack[numTop--];
|
|
double result = calculate(a, b, token[0]);
|
|
numStack[++numTop] = result;
|
|
printf("計算:%.2f %c %.2f = %.2f\n", a, token[0], b, result);
|
|
}
|
|
else {
|
|
printf("錯誤:未知的標記 '%s'\n", token);
|
|
exit(1);
|
|
}
|
|
|
|
printf("當前堆疊:");
|
|
for(i = 0; i <= numTop; i++) {
|
|
printf("%.2f ", numStack[i]);
|
|
}
|
|
printf("\n\n");
|
|
|
|
token = strtok(NULL, " ");
|
|
}
|
|
|
|
if(numTop != 0) {
|
|
printf("錯誤:計算結束後堆疊中剩餘 %d 個元素\n", numTop + 1);
|
|
exit(1);
|
|
}
|
|
return numStack[numTop];
|
|
}
|
|
|
|
int main() {
|
|
|
|
printf("請輸入中序表示式(支援+-*/%^()運算) => ");
|
|
|
|
fgets(input, MAX, stdin);
|
|
input[strcspn(input, "\n")] = 0;
|
|
|
|
printf("\n對應的後序表示法式: ");
|
|
convert_to_postfix_forprint(); //顯示用
|
|
printf("\n計算的後序表示法式: ");
|
|
convert_to_postfix();
|
|
double postfix_result = evaluate_postfix();
|
|
printf("\n運算結果:%.4f", postfix_result);
|
|
|
|
printf("\t(正確值為:");
|
|
if(strcmp(input,"10+20*(50-30)/2^4-6*8")==0){
|
|
printf("%g",10+20*(50-30)/pow(2,4)-6*8);
|
|
}else if(strcmp(input,"10+20*(-50+30)/-2^4-6*8")==0){
|
|
printf("%g",10+20*(-50+30)/pow(-2,4)-6*8);
|
|
}else if(strcmp(input,"10.5+20.8*(50.1-30.6)/2.5^4-6.6*8.2")==0){
|
|
printf("%g",10.5+20.8*(50.1-30.6)/pow(2.5,4)-6.6*8.2);
|
|
}else if(strcmp(input,"10.5+20.8*(-50.1+30.6)/2.5^-4-6.6*8.2")==0){
|
|
printf("%g",10.5+20.8*(-50.1+30.6)/pow(2.5,-4)-6.6*8.2);
|
|
}else if(strcmp(input,"10-30*(-40-20)%2^4+7.5*-6")==0){
|
|
printf("%g",10-30*(-40-20)%(int)pow(2,4)+7.5*-6);
|
|
}else if(strcmp(input,"1+sin((-50.2+sin(3.8*20)*cos(-30-100%40))*2^-2.5)*cos(123.456)")==0){
|
|
printf("%g",1+sin((-50.2+sin(3.8*20)*cos(-30-100%40))*pow(2,-2.5))*cos(123.456));
|
|
}else if(strcmp(input,"100*(sin(sin(sin(50.2*cos((30+100%40)*sin(60/5.5)))+20*(50/30.0)^3.5-6*8)))^2")==0){
|
|
printf("%g",100*pow(sin(sin(sin(50.2*cos((30+100%40)*sin(60/5.5)))+20*pow(50/30.0,3.5)-6*8)),2));
|
|
}else if(strcmp(input,"100*(sin(sin(sin(+50.2*cos((30+100%40)*sin(60/5.5)))+20*(+50/30.0)^3.5-6*8)))^2")==0){
|
|
printf("%g",100*pow(sin(sin(sin(50.2*cos((30+100%40)*sin(60/5.5)))+20*pow(50/30.0,3.5)-6*8)),2));
|
|
}printf(")");
|
|
|
|
return 0;
|
|
}
|