運(yùn)用可表多類型的棧來實(shí)現(xiàn)計(jì)算器

問題描述

這里限定的簡單表達(dá)式求值問題是用戶輸入一個(gè)包含+玫氢、-倔撞、*、/慕趴、非負(fù)浮點(diǎn)數(shù)和圓括號的合法算術(shù)表達(dá)式痪蝇,計(jì)算該表達(dá)式的運(yùn)算結(jié)果鄙陡。

下面給出代碼

Stack.h

#ifndef _STACK_H
#define _STACK_H

#include <stdbool.h>

#define INCREASE_SIZE 10
#define STACK_SIZE 20

typedef enum { OK = 1, ERROR = 0 } Status;

typedef struct STACK {
  unsigned int typeSize;
  char *pBase;
  char *pTop;
  int stackSize;
} Stack;

Status InitStack(Stack *pStack, unsigned int typeSize);
Status DestructAStack(Stack *pStack);
bool IsEmpty(Stack *pStack);
bool IsFull(Stack *pStack);
unsigned int LenOfStack(Stack *pStack);
Status CleanAStack(Stack *pStack);
Status IncreaseASTack(Stack *pStack);
Status PushIntoStack(Stack *pStack, const void *value);
Status PopFromStack(Stack *pStack, void *popElement);
Status GetTopOfStack(Stack *pStack, void *topElement);
#endif

Stack.c

#include <stdio.h>
#include <stdlib.h>
#include "Stack.h"



Status InitStack(Stack *pStack, unsigned int typeSize) {
  pStack->typeSize = typeSize;
  pStack->pBase = (char *)malloc(sizeof(char *) *
                                          pStack->typeSize * STACK_SIZE);
  if (pStack->pBase == NULL) {
    return ERROR;
  }
  pStack->pTop = pStack->pBase;
  pStack->stackSize = STACK_SIZE;
  return OK;
}

Status DestructAStack(Stack *pStack) {
  free(pStack->pBase);
  pStack->pBase = NULL;
  pStack->pTop = NULL;
  pStack->stackSize = 0;
  pStack->typeSize = 0;
  return OK;
}

bool IsEmpty(Stack *pStack) {
  return (pStack->pTop - pStack->pBase) / pStack->typeSize == 0;
}

bool IsFull(Stack *pStack) {
  return (pStack->pTop - pStack->pBase) / pStack->typeSize == pStack->stackSize;
}

unsigned int LenOfStack(Stack *pStack) {
  return (pStack->pTop - pStack->pBase) / pStack->typeSize;
}

Status CleanAStack(Stack *pStack) {
  pStack->pTop = pStack->pBase;
  return OK;
}

Status IncreaseASTack(Stack *pStack) {
  pStack->pBase = (char *)realloc(
      pStack->pBase,
      sizeof(char *) * pStack->typeSize * INCREASE_SIZE);
  if (pStack->pBase == NULL) {
    return ERROR;
  }
  pStack->pTop = pStack->pBase + pStack->stackSize * pStack->typeSize;
  pStack->stackSize += INCREASE_SIZE;
  return OK;
}

Status PushIntoStack(Stack *pStack, const void *value) {
  int i;
  char *e = (char *)value;
  if (IsFull(pStack)) {
    IncreaseASTack(pStack);
  }
  for (i = 0; i < pStack->typeSize; i++) {
    pStack->pTop[i] = e[i];
  }
  pStack->pTop += pStack->typeSize;
  return OK;
}

Status PopFromStack(Stack *pStack, void *popElement) {
  int i;
  char *e = (char *)popElement;
  if (IsEmpty(pStack)) {
    return ERROR;
  }
  pStack->pTop-=pStack->typeSize;
  for (i = 0; i < pStack->typeSize;i++){
    e[i] = pStack->pTop[i];
  }
  return OK;
}

Status GetTopOfStack(Stack *pStack, void *topElement){
  int i;
  char *e = (char *)topElement;
  if (IsEmpty(pStack)) {
    return ERROR;
  }
  pStack->pTop-=pStack->typeSize;
  for (i = 0; i < pStack->typeSize;i++){
    e[i] = pStack->pTop[i];
  }
  pStack->pTop += pStack->typeSize;
  return OK;
}

Calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H
#define M 100

float BasicCalculate(float unit1, char operator, float unit2);
float Calculate(char *str);
#endif

Calculator.c

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "Stack.h"

float BasicCalculate(float unit1, char operator, float unit2){
    float sum = 0;
    switch(operator){
        case '+':
            sum = unit1 + unit2;
            break;
        case '-':
            sum = unit1 - unit2;
            break;
        case '*':
            sum = unit1 * unit2;
            break;
        case '/':
            if(unit2==0){
                printf("Wrong!The divisor can`t be zero!\n");
                exit(1);
            }
            sum = unit1 / unit2;
            break;
    }
    return sum;
}

float Calculate(char *str){
    char e;
    float unit1, unit2,tempSum,sum=0;
    Stack val,oper;
    InitStack(&val, sizeof(float));
    InitStack(&oper, sizeof(char));
    while(str!=NULL&&*str!='\0'){
    /*極其細(xì)微的錯(cuò)誤,如果寫出*str!='\0'&&str!=NULL則對于純數(shù)字表達(dá)式出錯(cuò)躏啰。
    錯(cuò)誤出自strpbrk函數(shù)趁矾,如果str指向NULL,則*str是錯(cuò)誤的行為给僵。*/
        switch(*str){
            case '(':
                PushIntoStack(&oper, str);
                str++;
                break;
            case ')':
                while(PopFromStack(&oper, &e),e!='('){
                    PopFromStack(&val, &unit2);
                    PopFromStack(&val, &unit1);
                    tempSum = BasicCalculate(unit1, e, unit2);
                    PushIntoStack(&val, &tempSum);
                }
                str++;
                break;
            case '+':
            case '-':
                while(!IsEmpty(&oper)){
                    GetTopOfStack(&oper, &e);
                    if(e!='('){
                        PopFromStack(&val, &unit2);
                        PopFromStack(&val, &unit1);
                        tempSum = BasicCalculate(unit1, e, unit2);
                        PushIntoStack(&val, &tempSum);
                        PopFromStack(&oper, &e);
                    }
                    else{
                        break;
                    }
                    PushIntoStack(&oper, str);
                    str++;
                    break;
                }
            case '*':
            case '/':
                while(!IsEmpty(&oper)){
                    GetTopOfStack(&oper, &e);
                    if(e=='*'||e=='/'){
                        PopFromStack(&val, &unit2);
                        PopFromStack(&val, &unit1);
                        tempSum = BasicCalculate(unit1, e, unit2);
                        PushIntoStack(&val, &tempSum);
                        PopFromStack(&oper, &e);
                    }
                    else{
                        break;
                    }
                }
                 PushIntoStack(&oper, str);
                str++;
                break;
            default:
                if(isdigit(*str)){
                    sscanf(str, "%f", &tempSum);
                    PushIntoStack(&val, &tempSum);
                    str = strpbrk(str, "+-*/()");
                }
        }
    }
    while(!IsEmpty(&oper)){
        PopFromStack(&oper, &e);
        PopFromStack(&val, &unit2);
        PopFromStack(&val, &unit1);
        tempSum = BasicCalculate(unit1, e, unit2);
        PushIntoStack(&val, &tempSum);
    }
    DestructAStack(&oper);
    while (!IsEmpty(&val)){
        PopFromStack(&val, &tempSum);
        sum += tempSum;
    }
    DestructAStack(&val);
    return sum;
}

main.c

#include <stdio.h>
#include <string.h>
#include "Calculator.h"

int main(void){
    char formula[M + 1];
    float sum;
    memset(formula, '\0',sizeof(formula));
    printf("Please enter a formula: ");
    scanf("%s", formula);
    sum = Calculate(formula);
    printf("The final result is: %g", sum);
    return 0;
}

運(yùn)行結(jié)果

運(yùn)行結(jié)果1
運(yùn)行結(jié)果2
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毫捣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子帝际,更是在濱河造成了極大的恐慌蔓同,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹲诀,死亡現(xiàn)場離奇詭異斑粱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)脯爪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門则北,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痕慢,你說我怎么就攤上這事尚揣。” “怎么了掖举?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵快骗,是天一觀的道長。 經(jīng)常有香客問我拇泛,道長滨巴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任俺叭,我火速辦了婚禮恭取,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘熄守。我一直安慰自己蜈垮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布裕照。 她就那樣靜靜地躺著攒发,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晋南。 梳的紋絲不亂的頭發(fā)上惠猿,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音负间,去河邊找鬼偶妖。 笑死姜凄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的趾访。 我是一名探鬼主播态秧,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扼鞋!你這毒婦竟也來了申鱼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤云头,失蹤者是張志新(化名)和其女友劉穎捐友,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盘寡,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡楚殿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了竿痰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脆粥。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖影涉,靈堂內(nèi)的尸體忽然破棺而出变隔,到底是詐尸還是另有隱情,我是刑警寧澤蟹倾,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布匣缘,位于F島的核電站,受9級特大地震影響鲜棠,放射性物質(zhì)發(fā)生泄漏肌厨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一豁陆、第九天 我趴在偏房一處隱蔽的房頂上張望柑爸。 院中可真熱鬧,春花似錦盒音、人聲如沸表鳍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽譬圣。三九已至,卻和暖如春雄坪,著一層夾襖步出監(jiān)牢的瞬間厘熟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绳姨,地道東北人颇玷。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像就缆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子谒亦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容