Data_Structure/作業/unit3/try.c
2025-01-20 21:30:53 +08:00

213 lines
5.9 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 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();
// === 檢查運算子優先順序 ===
int get_priority(char c){
if(c=='+' || c=='-'){
return 1;
}else if(c=='*' || c=='/'){
return 2;
}else if(c=='^'){
return 3;
}else{
return 0;
}
}
// === 檢查字元是否為運算子 ===
int is_operator(char c) {
return (c == '+' || c == '-' || c == '*' || 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);
default: return 0;
}
}
// === 轉換為後序表達式 ===
void convert_to_postfix() {
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[postfix_index++] = number_str[j];
}
postfix[postfix_index++] = ' ';
if(is_negative) {
postfix[postfix_index++] = '-';
postfix[postfix_index++] = ' ';
}
}
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] == '-' && (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[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(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();
double postfix_result = evaluate_postfix();
printf("\n運算結果:%.2f", 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);
}
printf(")");
return 0;
}