最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C指針原理教程之編譯原理-小型計(jì)算器實(shí)現(xiàn)

 更新時(shí)間:2019年02月07日 11:31:25   作者:myhaspl  
本文給大家分享的是如何使用C語(yǔ)言編寫一個(gè)小型計(jì)算器的實(shí)例代碼,有需要的小伙伴可以參考下

1、打開(kāi)cygwin,進(jìn)入home目錄,home目錄在WINDOWS系統(tǒng)的cygwin安裝目錄映射為home目錄。

2、首先,在home目錄中新建文件夾,在文件夾中放置如下內(nèi)容的test1.l

/*統(tǒng)計(jì)字?jǐn)?shù)*/

%{

int chars=0;

int words=0;

int lines=0;

%}

%%

[a-zA-Z]+ {words++;chars+=strlen(yytext);}

\n {chars++;lines++;}

.  {chars++;}

%%

main(int argc,char**argv)

{

  yylex();

  printf("%d%d%d\n",lines,words,chars);

}

然后調(diào)用flex生成詞法分析器

Administrator@2012-20121224HD /home/flexlinux

$ cd /home

Administrator@2012-20121224HD /home

$ cd flexlinux

Administrator@2012-20121224HD /home/flexlinux

$ flex test1.l

Administrator@2012-20121224HD /home/flexlinux

$

可以看到目錄中的lex.yy.c就是剛生成的C源碼,可分析詞法。

Administrator@2012-20121224HD /home/flexlinux

$ ls

lex.yy.c test1.l

二、flex和bison聯(lián)合工作

1 、我們開(kāi)始構(gòu)造一個(gè)計(jì)算器程序。

創(chuàng)建flex代碼

/*計(jì)算器*/

%{

enum yytokentype{

   NUMBER=258,

 ADD=259,

 SUB=260,

 MUL=261,

 DIV=262,

 ABS=263,

 EOL=264

};

int yylval;

%}

%%

"+"  {return ADD;}

"-"  {return SUB;}

"*"  {return MUL;}

"/"  {return DIV;}

"|"  {return ABS;}

[0-9]+ {yylval=atoi(yytext);return NUMBER;}

\n {return EOL;}

[ \t] {/*空白忽略*/}

. {printf("非法字符 %c\n",*yytext);}

%%

main(int argc,char**argv)

{

  int tok;

  while(tok=yylex()){

   printf("%d",tok);

 if (tok==NUMBER) printf("=%d\n",yylval);

 else printf("\n");

  }

}

2、編譯

Administrator@2012-20121224HD /home/flexlinux

$ flex test2.l

Administrator@2012-20121224HD /home/flexlinux

$ gcc lex.yy.c -lfl

3、運(yùn)行

Administrator@2012-20121224HD /home/flexlinux

$ ./a

- 12 66

260

258=12

258=66

264

Administrator@2012-20121224HD /home/flexlinux

$ ./a

/ 56 2 + |32

262

258=56

258=2

259

263

258=32

264

Administrator@2012-20121224HD /home/flexlinux

$

(2)計(jì)算器的BISON程序

%{
#include <stdio.h>
%}

%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL

%%

calclist:/**/
 |calclist exp EOL{printf ("=%d\n",$2);}
 ;

exp:factor {$$ = $1;}
 |exp ADD factor{$$=$1+$3;}
 |exp SUB factor{$$=$1-$3;}
 ;

factor:term {$$=$1;}
 |factor MUL term{$$=$1*$3;}
 |factor DIV term{$$=$1/$3;}
 ;
term:NUMBER {$$=$1;}
 |ABS term {$$=$2>=0?$2:-$2;}
 ;
%%
main(int argc,char **argv){
yyparse();
}
yyerror(char *s)
{
 fprintf(stderr,"error:%s\n",s);
}
$ bison -d test2.y
t$ ls

test2.tab.c test2.tab.h test2.y test2.y~

然后,修改剛才的flex文件,將其命名為test21.l

test2.tab.h中包含了記號(hào)編號(hào)的定義和yylval的定義,因此,將其第一部分的相關(guān)定義刪除,并改為:

/計(jì)算器/

%{

  #include "test2.tab.h"

%}

然后刪除,其第三部分的main函數(shù)。

最后,進(jìn)行編譯。

bison -d test2.y

flex test21.l

gcc test2.tab.c lex.yy.c -lfl

可以測(cè)試一下

root@myhaspl:~# ./a.out

12 + 36 * 2

=84

12 / 6 + 2 * 3

=8

(2)擴(kuò)充計(jì)算器

加入對(duì)括號(hào)和注釋的支持,

首先修改flex文件,在第二部分加入更多的詞法規(guī)則(對(duì)于注釋直接忽略):

"("   {return LEFTBRACKET;}

")"   {return RIGHTBRACKET;}

"#". /忽略注釋*/

然后,修改bison文件,在第二部分加入更多的語(yǔ)法規(guī)則:

term:NUMBER {$$=$1;}

  |ABS term {$$=$2>=0?$2:-$2;}

  |LEFTBRACKET exp RIGHTBRACKET {$$=$2;}

  ;

我們的注釋以“#”表示

測(cè)試結(jié)果

myhaspl@myhaspl:~/flex_bison/2$ make

bison -d calculator.y

flex calculator.l

gcc calculator.tab.c lex.yy.c -lfl

myhaspl@myhaspl:~/flex_bison/2$ ls

a.out     calculator.tab.c calculator.y makefile

calculator.l calculator.tab.h lex.yy.c

myhaspl@myhaspl:~/flex_bison/2$ ./a.out

12-36*10/(1+2+3)#compute

=-48

^C
myhaspl@myhaspl:~/flex_bison/2$ 

前面都是以鍵盤輸入 的方式進(jìn)行計(jì)算器運(yùn)算,我們下面以文件方式提供給該解釋器進(jìn)行計(jì)算,首先,將flex文件改為(將其中中文去除,然后對(duì)于非法字符的出現(xiàn)進(jìn)行忽略):

%{
#include "calculator.tab.h"
%}

%%
"+"  {return ADD;}
"-"  {return SUB;}
""  {return MUL;}
"/"  {return DIV;}
"|"  {return ABS;}
"("  {return LEFTBRACKET;}
")"  {return RIGHTBRACKET;}
"#". /comment/
[0-9]+ {yylval=atoi(yytext);return NUMBER;}
\n {return EOL;}
[ \t] /blank/
. /invalid char/
%

接著,改bison文件,加入對(duì)文件的讀寫

%{
#include <stdio.h>
%}

%token NUMBER
%token ADD SUB MUL DIV ABS LEFTBRACKET RIGHTBRACKET
%token EOL 

%%

calclist:/**/
 |calclist exp EOL{printf ("=%d\n",$2);}
 ;
 
exp:factor {$$ = $1;}
 |exp ADD factor{$$=$1+$3;}
 |exp SUB factor{$$=$1-$3;}
 ;
 
 
factor:term {$$=$1;}
 |factor MUL term{$$=$1*$3;}
 |factor DIV term{$$=$1/$3;}
 ;
term:NUMBER {$$=$1;}
 |ABS term {$$=$2>=0?$2:-$2;}
 |LEFTBRACKET exp RIGHTBRACKET {$$=$2;}
 ;
%%
main(int argc,char **argv){
int i;
if (argc<2){
  yyparse();
}
else{
  for(i=1;i<argc;i++)
    {
    FILE *f=fopen(argv[i],"r");
    if (!f){
     perror(argv[i]);
     return (1);
    }
   yyrestart(f);
   yyparse();
   fclose(f);
  }
}
}

yyerror(char *s)
{
 fprintf(stderr,"error:%s\n",s);
}

最后 測(cè)試一下

root@myhaspl:~/test/3# make
bison -d calculator.y
flex calculator.l
gcc calculator.tab.c lex.yy.c -lfl
root@myhaspl:~/test/3# ./a.out mycpt1.cpt mycpt2.cpt
=158
=-8
root@myhaspl:~/test/3# 

其中兩個(gè)CPT文件內(nèi)容類似 為:

12*66/(10-5)

我們接著完善這個(gè)計(jì)算器程序,讓算式能顯示出來(lái),修改calculator.l

通過(guò)加入printf語(yǔ)句,打印詞法分析器解析到的字符。比如 :

..................

[0-9]+ {yylval=atoi(yytext);printf("%d",yylval);return NUMBER;}

\n  {return EOL;}

[ \t] /blank/

. /invalid char/

%%

然后編譯執(zhí)行。

root@myhaspl:~/test/4# make

bison -d calculator.y

flex calculator.l

gcc calculator.tab.c lex.yy.c -lfl

root@myhaspl:~/test/4# ./a.out

12+66

12+66=78

^C

root@myhaspl:~/test/4# ./a.out mycpt1.cpt mycpt2.cpt  

12*66/(10-5)=158

77/(10+1)-15=-8

接下來(lái)加上讀取的行號(hào),將結(jié)果的顯示更加人性化

flex文件要改:

\n  {printf("<line:%4d>",yylineno);yylineno++;return EOL;}

然后,bison文件也改:

calclist:/**/
  |calclist exp EOL{printf ("the result is:%d\n",$2);}
  ;

最后 ,編譯運(yùn)行測(cè)試一下。

root@myhaspl:~/test/4# make
bison -d calculator.y
flex calculator.l
gcc calculator.tab.c lex.yy.c -lfl
root@myhaspl:~/test/4# ./a.out mycpt1.cpt mycpt2.cpt
1266/(10-5)<line:  1>the result is:158
12/22-8<line:  2>the result is:-8
77(6-2)<line:  3>the result is:308
77/(10+1)-15<line:  4>the result is:-8
root@myhaspl:~/test/4# 

相關(guān)文章

  • 詳解C語(yǔ)言中Char型指針數(shù)組與字符數(shù)組的區(qū)別

    詳解C語(yǔ)言中Char型指針數(shù)組與字符數(shù)組的區(qū)別

    這篇文章主要介紹了詳解C語(yǔ)言中Char型指針數(shù)組與字符數(shù)組的區(qū)別的相關(guān)資料,希望通過(guò)本文能幫助到大家掌握理解這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • C++設(shè)計(jì)模式之享元模式(Flyweight)

    C++設(shè)計(jì)模式之享元模式(Flyweight)

    這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式之享元模式Flyweight,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • 在C++中加載TorchScript模型的方法

    在C++中加載TorchScript模型的方法

    這篇文章主要介紹了在C++中加載TorchScript模型的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-02-02
  • OpenCV實(shí)現(xiàn)拼圖算法

    OpenCV實(shí)現(xiàn)拼圖算法

    這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)拼圖算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++中正則表達(dá)式的使用方法詳解

    C++中正則表達(dá)式的使用方法詳解

    幾乎所有的編程語(yǔ)言都支持正則表達(dá)式。 C++從C++11開(kāi)始直接支持正則表達(dá)式。除了編程語(yǔ)言之外,大多數(shù)文本處理程序都使用正則表達(dá)式。本文將探討正則表達(dá)式的一般細(xì)節(jié)以及C++編程方面的細(xì)節(jié),感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • VC++在TXT文件指定位置追加內(nèi)容的方法

    VC++在TXT文件指定位置追加內(nèi)容的方法

    這篇文章主要介紹了VC++在TXT文件指定位置追加內(nèi)容的方法,功能較為實(shí)用,需要的朋友可以參考下
    2014-08-08
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易掃雷小游戲

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易掃雷小游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • c語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單日歷

    c語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)單日歷

    本文給大家分享的是一則使用C語(yǔ)言來(lái)實(shí)現(xiàn)的一個(gè)簡(jiǎn)單日歷的代碼,根據(jù)項(xiàng)目需求,實(shí)現(xiàn)了3個(gè)簡(jiǎn)單的小功能,推薦給大家,有需要的小伙伴可以參考下。
    2015-03-03
  • 簡(jiǎn)單了解C語(yǔ)言中直接插入排序與直接選擇排序?qū)崿F(xiàn)

    簡(jiǎn)單了解C語(yǔ)言中直接插入排序與直接選擇排序?qū)崿F(xiàn)

    這篇文章主要介紹了C語(yǔ)言中直接插入排序與直接選擇排序?qū)崿F(xiàn),插入排序的基本操作就是將一個(gè)數(shù)據(jù)插入到已經(jīng)排好序的有序數(shù)據(jù)中,從而得到一個(gè)新的、個(gè)數(shù)加一的有序數(shù)據(jù),需要的朋友可以參考下
    2016-03-03
  • 深入理解卡特蘭數(shù)及其應(yīng)用

    深入理解卡特蘭數(shù)及其應(yīng)用

    本篇文章是對(duì)卡特蘭數(shù)及其應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評(píng)論

石首市| 新绛县| 盖州市| 谷城县| 新竹县| 佛教| 公主岭市| 徐闻县| 丰顺县| 江永县| 仙居县| 大洼县| 个旧市| 玉山县| 闵行区| 依兰县| 轮台县| 廉江市| 宝清县| 镇巴县| 南康市| 京山县| 博野县| 广宁县| 安新县| 咸阳市| 卓资县| 拉孜县| 红原县| 新巴尔虎左旗| 高邮市| 昌宁县| 黑山县| 老河口市| 沁水县| 天等县| 丰宁| 福鼎市| 崇礼县| 乌兰察布市| 乌什县|