欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言實(shí)現(xiàn)簡單計(jì)算器程序

 更新時間:2020年02月28日 10:23:02   作者:talent_CYJ  
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡單計(jì)算器程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

這兩天在看一個C語言寫的計(jì)算器程序,做了不少的功夫,跟著作者一步步的進(jìn)行完善,了解了許多細(xì)節(jié)性的東西,在此自己做個總結(jié),加深自己對程序的印象,也算是梳理。

在該計(jì)算器程序,能進(jìn)行加減乘除、sin、cos、exp等操作,同時能進(jìn)行數(shù)值保存功能。而該計(jì)算器使用逆波蘭表示法。即所有運(yùn)算符都跟在操作數(shù)的后面,比如下列表達(dá)式:
(1 - 2) * (4 + 5)采用逆波蘭表示法表示為:1 2 - 4 5 + *
逆波蘭表達(dá)法中不需要圓括號,只要知道每個運(yùn)算符需要幾個操作數(shù)就不會引起歧義。

計(jì)算器程序?qū)崿F(xiàn)很簡單,具體原理如下:

while(/* 下一個運(yùn)算符或操作數(shù)不是文件結(jié)束指示符 */)
 if(/* 是數(shù) */)
 /* 將該數(shù)壓入到棧中 */
 else if (/* 是運(yùn)算符 */)
 /* 彈出所需數(shù)目的操作數(shù) */
 /* 執(zhí)行運(yùn)算 */
 /* 將結(jié)果壓入到棧中 */
 else if (/* 是換行符 */)
 /* 彈出并打印棧頂?shù)闹?*/
 else
 /* 出錯 */

在程序設(shè)計(jì)中,使用模塊化思想,getop函數(shù)來進(jìn)行讀入,該函數(shù)返回一個標(biāo)識,用來標(biāo)識讀入的是什么類型。主循環(huán)體中根據(jù)該標(biāo)識執(zhí)行相應(yīng)的動作。

以下是該程序: (我將所有函數(shù)和變量放在同一文件)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXOP 100
#define NUMBER '0' //標(biāo)識讀入的是數(shù)字
#define NAME 'n' //標(biāo)識讀入的是字符串(函數(shù)名或非法字符串)
#define ALPHA 26 
int getop(char []); 
void push (double); //壓棧
double pop(void); //出棧
void clear(void); //清空棧
void mathfnc(char []); //執(zhí)行相應(yīng)的數(shù)學(xué)函數(shù)sin、cos、exp等

int main(void)
{
 int type;
 int i, var = 0;
 double op1, op2,v;
 char s[MAXOP];
 double variable[ALPHA];

 for (i = 0; i < ALPHA; i++) //初始化用于保存數(shù)值的變量數(shù)組
 variable[i] = 0.0;

 while ((type = getop(s)) != EOF) //讀取輸入
 {
 switch (type)
 {
  case NUMBER:
  push (atof(s));
  break;
  case NAME:
  mathfnc(s);
  break;
  case '+':
  push (pop() + pop());
  break;
  case '*':
  push (pop() * pop());
  break;
  case '-':
  op2 = pop();
  push (pop() - op2);
  break;
  case '/':
  op2 = pop();
  if (op2 != 0.0)
   push (pop() / op2);
  else
   printf ("error: zero divisor\n");
  break;
  case '%':
  op2 = pop();
  if (op2 != 0.0)
   push (fmod(pop(), op2));
  else
   printf ("error: zero divisor\n");
  break;
  case '?': //打印棧頂元素
  op2 = pop();
  printf ("\t%.8g\n", op2);
  push (op2);
  break;
  case '=': //保存數(shù)值
  pop();
  if (var >= 'A' && var <= 'Z')
   variable[var - 'A'] = pop();
  else
   printf ("error: no variable name\n");
  break;
  case 'c':
  clear();
  break;
  case 'd': //復(fù)制棧頂元素
  op2 = pop();
  push(op2);
  push(op2);
  break;
  case 's': //交換棧元素
  op1 = pop();
  op2 = pop();
  push(op1);
  push(op2);
  case '\n':
  v = pop(); //v保存最后的一次結(jié)果
  printf ("\t%.8g\n", v);
  break;
  default:
  if (type >= 'A' && type <= 'Z')
   push(variable[type - 'A']);
  else if (type == '@') //輸入的字符@表示最近一次結(jié)果值 
   push(v);
  else
   printf ("error: unknown command %s\n", s);
  break;
 }
 var = type; 
 }
 return 0;
}

/* ----------------------------------------------------------- */

#define MAXVAL 100

int sp = 0; //標(biāo)識棧頂
double val[MAXVAL];

void push(double f)
{
 if (sp < MAXVAL)
 val[sp++] = f;
 else
 printf ("error: stack full, can't push %g\n", f);
}

double pop(void)
{
 if (sp > 0)
 return val[--sp];
 else
 {
 printf ("error: statck empty\n");
 return 0.0;
 } 
}

void clear(void)
{
 sp = 0;
}

void mathfnc (char s[])
{
 double op2;

 if (strcmp (s, "sin") == 0)
 push(sin(pop()));
 else if(strcmp (s, "cos") == 0)
 push(cos(pop()));
 else if(strcmp (s, "exp") == 0)
 push(exp(pop()));
 else if(strcmp (s, "pow") == 0)
 {
 op2 = pop();
 push (pow(pop(), op2));
 }
 else
 printf ("error: %s not supported\n", s);
}

/* ----------------------------------------------------------- */

#include <ctype.h>

int getch(void);
void ungetch(int);

int getop(char s[])
{
 int i, c;
 while ((s[0] = c = getch()) == ' ' || c == '\t') //過濾開頭的空白字符
 ;
 s[1] = '\0';

 i = 0;

 if (islower(c)) //判斷是否為小寫字母,也即讀取由小寫字母組成的字符串
 {
 while (islower(s[++i] = c = getch()))
  ;
 s[i] = '\0';

 if (c != EOF)
  ungetch(c);
 if (strlen (s) > 1)
  return NAME;
 else 
  return c;
 }

 if (!isdigit(c) && c != '.' && c != '-')
 return c;

 if (c == '-') //用于判斷是負(fù)數(shù)還是減操作  
 { 
 if (isdigit(c = getch()) || c == '.') 
  s[++i] = c;
 else
 {
  if (c != EOF)
  ungetch(c);
  return '-';
 }
 }

 if (isdigit(c)) //收集整數(shù)部分
 while (isdigit(s[++i] = c = getch()))
  ;

 if (c == '.') //收集小數(shù)部分
 while (isdigit(s[++i] = c = getch()))
  ;

 s[i] = '\0';

 if (c != EOF)
 ungetch(c);

 return NUMBER;
}


/* ----------------------------------------------------------- */
/*
 * 引用以下兩個函數(shù)是因?yàn)椋撼绦虿荒艽_定它已經(jīng)讀入的輸入是否足夠 *
 * 除非超前多讀入一些輸入,在本程序中,讀入一些字符合成一個數(shù)字 *
 * 所以在看到第一個非數(shù)字字符之前,已經(jīng)讀入的數(shù)的完整性是不能確定的
 * 由于程序要超前讀入一個字符,這樣就導(dǎo)致最后又一個字符不屬于當(dāng)前所要讀入的數(shù) 
 */

#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;

int getch(void) 
{
 return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch (int c)
{
 if (bufp >= BUFSIZE)
 printf ("ungetch: too many characters\n");
 else
 buf[bufp++] = c;
}

該程序雖然簡單,但是還是存在一些小小的問題,比如沒有數(shù)據(jù)時進(jìn)行pop的話,會打印棧中無數(shù)據(jù)同時返回?cái)?shù)值0.0,在循環(huán)體中許多執(zhí)行操作會將該數(shù)值保存到棧中,之后打印該值,用戶體驗(yàn)度比較差。程序設(shè)計(jì)方面,模塊化設(shè)計(jì)使得該程序容易增加功能而不影響其他模塊,比如增加一些數(shù)學(xué)函數(shù)處理,在mathfnc函數(shù)中去添加,或增加一些運(yùn)算符操作,可以在主循環(huán)體中增加。

總之,這次學(xué)習(xí)還是頗有收獲。

關(guān)于計(jì)算器的精彩文章請查看《計(jì)算器專題》 ,更多精彩等你來發(fā)現(xiàn)!

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C++?STL?中的數(shù)值算法示例講解

    C++?STL?中的數(shù)值算法示例講解

    本片文章講解了C++STL?中的數(shù)值算法,包含iota、accumulate、adjacent_difference、inner_product、partial_sum這些方法的使用,感興趣的朋友來看看吧<BR>
    2022-04-04
  • 基于Matlab實(shí)現(xiàn)離散系統(tǒng)分岔圖的繪制

    基于Matlab實(shí)現(xiàn)離散系統(tǒng)分岔圖的繪制

    這篇文章主要介紹了如何利用Matlab實(shí)現(xiàn)離散分岔圖的繪制,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Matlab有一定的幫助,需要的可以參考一下
    2022-04-04
  • 淺談C++STL之雙端隊(duì)列容器

    淺談C++STL之雙端隊(duì)列容器

    deque雙端隊(duì)列容器與vector很類似,采用線性表順序存儲結(jié)構(gòu)。但與vector區(qū)別,deque采用分塊的線性存儲結(jié)構(gòu)來存儲數(shù)據(jù),每塊的大小一般為512B,將之稱為deque塊,所有的deque塊使用一個map塊進(jìn)行管理,每個map數(shù)據(jù)項(xiàng)記錄各個deque塊的首地址。
    2021-06-06
  • C語言 structural body結(jié)構(gòu)體詳解用法

    C語言 structural body結(jié)構(gòu)體詳解用法

    C 數(shù)組允許定義可存儲相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許您存儲不同類型的數(shù)據(jù)項(xiàng),結(jié)構(gòu)用于表示一條記錄,假設(shè)您想要跟蹤圖書館中書本的動態(tài),您可能需要跟蹤每本書的下列屬性
    2021-10-10
  • Linux中使用C語言的fork()函數(shù)創(chuàng)建子進(jìn)程的實(shí)例教程

    Linux中使用C語言的fork()函數(shù)創(chuàng)建子進(jìn)程的實(shí)例教程

    fork是一個在Linux系統(tǒng)環(huán)境下專有的函數(shù),現(xiàn)有的進(jìn)程調(diào)用fork后將會創(chuàng)建一個新的進(jìn)程,這里我們就來看一下Linux中使用C語言的fork()函數(shù)創(chuàng)建子進(jìn)程的實(shí)例教程
    2016-06-06
  • C++實(shí)現(xiàn)一行一行讀取文本的方法

    C++實(shí)現(xiàn)一行一行讀取文本的方法

    今天小編就為大家分享一篇C++實(shí)現(xiàn)一行一行讀取文本的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • C++中std::chrono時間庫的全面解析

    C++中std::chrono時間庫的全面解析

    C++?std::chrono時間庫是C++標(biāo)準(zhǔn)庫提供的一個時間處理庫,提供了一個方便、靈活和精確的時間處理工具,下面小編就帶大家深入了解一下std::chrono時間庫的使用吧
    2023-10-10
  • C語言菜鳥基礎(chǔ)教程之求1到100的和

    C語言菜鳥基礎(chǔ)教程之求1到100的和

    在C語言中可以通過定義一個累加器(一個變量)并結(jié)合for循環(huán)來實(shí)現(xiàn)計(jì)算1到100之和。
    2017-10-10
  • C++?sqlite3數(shù)據(jù)庫配置使用教程

    C++?sqlite3數(shù)據(jù)庫配置使用教程

    SQLite 是一種嵌入式的關(guān)系型數(shù)據(jù)庫管理系統(tǒng),它是一個開源項(xiàng)目,已經(jīng)被廣泛應(yīng)用于各種應(yīng)用程序和操作系統(tǒng)中,這篇文章主要介紹了C++?sqlite3數(shù)據(jù)庫配置使用,需要的朋友可以參考下
    2023-08-08
  • C++繼承詳細(xì)介紹

    C++繼承詳細(xì)介紹

    我們都知道面向?qū)ο笳Z言的三大特點(diǎn)是:**封裝,繼承,多態(tài)。**之前在類和對象部分,我們提到了C++中的封裝,那么今天呢,我們來學(xué)習(xí)一下C++中的繼承
    2022-10-10

最新評論