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

268 lines
7.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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=='/'){
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_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] == '-' && (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])) {
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_forprint(); //顯示用
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);
}printf(")");
return 0;
}