當前位置:首頁 » 編程語言 » c語言編程藝術
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言編程藝術

發布時間: 2022-07-20 20:44:12

1. 自學c語言 零基礎 看什麼書 該怎麼學

現在,市面上的
C語言書籍多的數不過來,但是很多不適合你這種初學者使用,作為一名老程序員,我給你推薦幾本我看過認為還不錯的書:
1)
《C語言小白變怪獸》:既適合對計算機一竅不通的小白,也適合有編程基礎的讀者,還可以用來進階。同時,最重要的是,這本書的作者還在不斷地更新這本書,我認為最大的特點是通俗易懂,深入淺出,只要認真看,就一定能看懂,我認為這是C語言入門的首選教材,吐血推薦,經典中的經典!!!
2)
《啊哈C語言》:適合對計算機一竅不通的純小白,有編程基礎的讀者請忽略。這本書語言幽默,生動形象,通俗易懂,給人耳目一新的感覺,但是這本書非常淺顯,並不深入,所以適合純小白入門,找到門以後也就扔了。這本書著重於語言藝術,針對純小白下足了功夫,小學生坐在馬桶上都能學會編程。說實話,我非常欣賞作者的創意和用心,國內像這樣寫書的少之又少,入門的書就應該是這個樣子。
上邊這兩本書是我推薦給你用於C語言入門的,我不建議你使用譚浩強的《C語言程序設計》這本書入門,雖然這本書的知名度很高,因為很多大學把它作為C語言的授課教材,然而,這本書被吐槽最多,不但代碼不標准,而且有很多錯誤,據說可以找出幾十個錯誤,這樣很容易誤導你這種小白。
等你有一定的C語言基礎了,可以看下面的這幾本書,進一步提升你的編程水平:
1)
《C
Primer
Plus》:暢銷
30
余年的C語言入門經典書籍,至今無人能撼動它的地位,它是最符合C語言標準的書籍,作為一名C語言程序員,不收藏一本都覺得自己很水。
2)
《C程序設計語言,The
C
Programming
Language》:C語言創始人丹尼斯·里奇(Dennis
MacAlistair
Ritchie)的著作,和《C
Primer
Plus》並駕齊驅,很難分出伯仲,這兩本書都是一樣的優秀,都是C語言程序員必須收藏的。
3)
《C專家編程》:適合已經具備C語言基礎、想進階的讀者。這貌似是一本吐槽C語言的書,基本上介紹了大多數C語言的坑,有不少精髓,在C語言界久負盛名,進階時一定要看。
4)
《C陷阱與缺陷》:和《C專家編程》類似,也是給C語言挑刺的,闡述了很多容易讓人誤解的語法細節,重在幫助C程序員繞過編程過程中的陷阱和障礙。
5)
《程序員的自我修養
--
鏈接、裝載與庫》:這真是一本深入骨髓的書,讓你徹底明白程序的編譯、鏈接、裝載和運行的全過程,你會從此上天,拉開和別人的差距,看任何問題都有了深度和高度。重點推薦!
所有的這些書我都有電子版,需要可以找我要!

2. 學習C語言有什麼書適合新手看

學習C語言不是一朝一夕的事情,但也不需要花費十年時間才能精通。如何以最小的代價學習並精通C語言是本文的主題。請注意,即使是「最小的代價」,也絕不是什麼捷徑,而是以最短的時間取得最多的收獲,同時也意味著你需要經歷艱苦的過程。

一、要讀就讀好書,否則不如不讀

所有初學者面臨的第一個問題便是:如何選擇教材。好的開始是成功的一半,選擇一本優秀的教材是事半功倍的關鍵因素。不幸的是,學校通常會幫你指定一本很差勁的C語言課本;而幸運的是,你還可以再次選擇。

大名鼎鼎的譚浩強教授出了一本《C語言程序設計》,據說發行量有超過400萬,據我所知,很多學校都會推薦這本書作為C語言課本。雖然本人的名字(譚浩宇)跟教授僅僅一字之差,但我是無比堅定地黑他這本書的。這本書不是寫給計算機專業的學生的,而是給那些需要考計算機等級考試的其它專業學生看的。這本書的主要缺點是:例子程序非常不專業,不能教給你程序設計應該掌握的思考方式;程序風格相當地不好,會讓你養成亂寫代碼的惡習;錯誤太多,曾經有人指出過這本書的上百個錯誤,其中不乏關鍵的概念性錯誤。好了,這本書我也不想說太多了,有興趣大家可以網路一下:)

Kernighan和 Ritchie的《The C Programming Language》(中譯名《C程序設計語言》)堪稱經典中的經典,不過舊版的很多內容都已過時,和現在的標准C語言相去甚遠,大家一定要看最新的版本,否則不如不看。另外,即使是最經典最權威的書,也沒有辦法面面俱到,所以手邊常備一本《C語言參考手冊》是十分必要的。《C語言參考手冊》就是《C Reference Manual》,是C語言標準的詳細描述,包括絕大多數C標准庫函數的細節,算得上是最好的標准C語言的工具書。順便提一句,最新的《C程序設計語言》是根據C89標准修訂的,而《C語言參考手冊》描述的是C99標准,二者可能會有些出入,建議按照C99標准學習。還有一本《C和指針》,寫得也是相當地不錯,英文名是《Pointers on C》,特別地強調指針的重要性,算是本書的一個特點吧。不過這本書並不十分適合初學者,如果你曾經學過C語言,有那麼一些C語言的基礎但又不是很扎實,那麼你可以嘗試一下這本書。我相信,只要你理解了指針,C語言便不再神秘。

如果你已經啃完了一本C語言教材,想要更進一步,那麼有兩本書你一定要看。首先是《C Traps and Pitfalls》(中譯名《C陷井與缺陷》),很薄的一本小冊子,內容非常非常地有趣。要注意一點,這本書是二十多年前寫成的,裡面提到的很多C語言的缺陷都已被改進,不過能夠了解一些歷史也不是什麼壞事。然後你可以挑戰一下《Expert C Programming》(中譯名《C專家編程》),書如其名,這本書頗具難度,一旦你仔細讀完並能透徹理解,你便可以放心大膽地在簡歷上寫「精通C語言」了。

切記一個原則,不要讀自己目前還看不懂的書,那是浪費生命。如果你看不懂,那你一定是缺失了某些必需基礎知識。此時,你要仔細分析自己需要補充哪些內容,然後再去書店尋找講述的這些內容的書籍。把基礎知識補充完畢再回頭來學習,才會真正的事半功倍。

二、Unix/Linux還是Windows,這是個很大的問題

不同的編程環境會造就出不同思維的程序員。Windows的程序員大多依賴集成開發環境,比如Visual Studio,而Unix程序員更加鍾愛Makefile與控制台。顯而易見,集成開發環境更容易上手,在Windows上學習C語言,只需要會按幾個基本的Visutal C++工具欄按鈕就可以開始寫Hello, World!了,而在Unix下,你需要一些控制台操作的基本知識。有人也許認為Unix的環境更簡潔,但習慣的力量是很大的,大家都很熟悉 Windows的基本操作,而為了學習C語言去專門裝一個Unix系統,似乎有點不劃算。

對於一個只懂得Windows基本操作、連 DOS是什麼都不知道的新手而言,盡快做一些有趣而有意義的事情才是最重要的。用C語言寫一個小程序遠比學習ls、cat等命令有趣,況且我們要專注於C 語言本身,就不得不暫時忽略一些東西,比如編譯鏈接的過程、Makefile的寫法等等等等。

所以我建議初學者應該以Visual C++ 6.0(不是VisualC++ .NET)或者Dev C++作為主要的學習環境,而且千萬不要在IDE的使用技巧上過多糾纏,因為今後你一定要轉向Unix環境的。Visual C++ 6.0使用很方便,調試也很直觀,但其默認的編譯器對C標準的支持並不好,而Dev C++使用gcc編譯器,對C99的標准都支持良好。使用順帶提一下,很多大學的C語言課程還在使用Turbo C 2.0作為實驗環境,這是相當不可取的,原因其一是TC 2.0對C標准幾乎沒有支持,其二是TC 2.0編譯得到的程序是16位的,這對今後理解32位的程序會造成極大的困擾(當然,用djgpp之類的東西可以使TC 2.0編譯出32位程序,不過那過於復雜了)。

等你學完一本C語言的教材,你一定要轉向Unix平台繼續學習,幾乎所有的C語言高級教程都是基於Unix平台的(比如《C專家編程》)。轉變的過程是痛苦的,你需要面對的是各種紛繁復雜的命令,完全不同於Windows平台的思考方式,但是這種痛苦是值得的。Unix與C是共生的,Unix的思考方式和習慣更加符合C語言的思考方式和習慣。在Unix下,你可以找到無數優秀的源代碼供你盡情閱讀,你可以方便地查看某個庫函數的聯機手冊,還可以看到最優秀的代碼風格(說到代碼風格,我會專門寫一篇文章詳細敘述)。

歸結起來就是一句話:初學C語言,建議使用Windows系統和集成開發環境,在准備向「高手」方向努力時,請先轉向Unix平台。

三、萬事俱備,你就是東風

書已選定,環境配置完成,正所謂萬事俱備,只欠你自己的努力了。請從書的前言開始,仔細地閱讀手頭的教材,很多人看書喜歡直接從第一章開始看,這是錯誤的做法。前言是作者對整本書的大體介紹,作者一般會告訴你需要什麼基礎才能夠順利閱讀本書,這可以幫助你檢驗自己的基礎知識是否已經具備。看完前言,還要瀏覽一下目錄,了解一下書的整體結構,順便給自己安排一下學習計劃。

學習C語言,必需注意每一個細節,書上的例子代碼一定要自己親自敲一遍,編譯執行輸出都跟書上說的一致才能算是學完了一個例子,如果不一致,就要仔細找原因。出了書本上有的例子,自己還要「創造」一些例子,比如學習運算符優先順序的時候,可以寫幾個相同的表達式,在不同的位置加上括弧,看看有哪些不同的行為,比如*p++和(*p)++,又比如a = b == c、(a = b) == c和a = (b == c)等等。自己抄的書上的例子以及改造之後的例子,還有自己「創造」的例子,都應該仔細地歸類保存,並且要在源代碼中寫上簡短的注釋,闡述這個例子的意圖。

例子之後就是習題了,我建議初學者把所有的習題都獨立做一遍,然後對照答案的代碼,看看自己的代碼有那些不足,再試著修改自己的代碼。很多人不重視習題,這是極大的錯誤,因為作者通常會在習題中說明一些重要的道理,而不是單純地檢驗前面的知識。

也許你認為這樣學習太慢,其實不然。學得細致就不用走回頭路,等你學到後面才發現自己前面沒搞清楚,那才是真的得不償失。一般說來,整本書讀完,你應該完成數千行乃至上萬行的代碼,無論是原封不動照抄書上的,還是自己心血來潮寫就的,都是今後繼續學習的一筆財富。以我自己舉例,閱讀《Windows核心編程》時(我只閱讀了3/4的內容),除了抄書上的代碼,還自己寫了很多例子,一共有5574行(用unix下的wc工具統計),時隔多日,我早已記不清 Windows的系統編程了,但只要花幾分鍾翻出以前的代碼看看,便會重新瞭然於胸。所謂好記性不如爛筆頭,就是這個道理。

仔細讀書、認真抄寫源代碼、獨立完成習題外加更進一步的實驗,最後將所有的代碼留下,成為自己的經驗和財富,絕對的辛苦,也絕對的事半功倍。當然,這種方式只適合學習需要精通的技術,如果不是學習C語言,你還要具體情況具體分析。

寫到最後,還有非常非常重要的一點沒有提及──代碼風格,從最開始學習就必須強迫自己模仿最優秀的代碼風格。因為代碼風格太重要內容也太多,我會用專門的一篇文章來詳細討論,請大家關注《程序員之路──關於代碼風格》。

3. 什麼事C語言

C語言是一種編程語言,通俗地講就是把你的想法通過計算機表現出來,人有人的語言,同樣,機器也有機器語言,而這些個語言就是類似一種翻譯工具,把人的命令傳達給計算機。最早的編程語言就是對計算機語言直接進行翻譯,是一對一的,更靠近機器一方,但機器的識別度高,還有一種語言叫VB,這種語言就是更靠近人,可以直接指令,都是英語單片語成的,但其機器識別度較低。。。而介於這兩種之間的就是C語言,如果有興趣建議你先去看看VB,積累編程思想。。。再慢慢深入,編程不只是記住代碼那麼簡單。。。它是一門藝術

4. c語言演算法經典入門書籍推薦!!!!!!!!!!!1最好是國外的書!

《演算法導論》原書名——《Introction to Algorithms》,是一本十分經典的計算機演算法書籍,與高德納(Donald E.Knuth)的《計算機程序設計藝術》(《The Art Of Computer Programming》)相媲美。 《演算法導論》由Thomas H.Cormen、Charles E.Leiserson、Ronald L.Rivest、Clifford Stein四人合作編著(其中Clifford Stein是第二版開始參與的合著者)。本書的最大特點就是將嚴謹性和全面性融入在了一起。

http://ke..com/link?url=-

大學教的數據結構和演算法基本上面都有,我就作為參考書

5. 誰能告訴我什麼叫C語言具體點,謝謝啦

首先:C語言是C語言 是面向過程的語言;而C++是面向對象的語言,兩者不同,但是C++是從C演變過來的,所以有了C的基礎對C++會有幫助。

首先:C語言入門相對比較簡單,但如果想成為一個優秀的C程序員,需要很艱苦的訓練,多讀代碼,多練習,多上機操作,多思考,學習是一件辛苦的事情,要放棄很多東西,要堅持下來才可以,可以說C語言是基礎,將來想學其他的C++,JAVA等,如果有C的基礎,還是比較好入門的.

C語言的用處比較廣泛,可以說任何精通計算機的人都掌握C語言了,我是本科計算機專業的,C被作為許多課程的先行課,沒有了C語言基礎,就不能學習數據結構,操作系統,編譯原理,計算機網路等核心課程,所以說,想學習計算機的話無論想在哪個方向發展(軟體,硬體,網路,應用,開發,設計等方向)都必須掌握C語言.

關於C語言的教材:我向你推薦幾本:
最經典的:《C程序設計語言》第2版,機械工業出版社
這個是C語言的設計者和UNIX系統的設計者合作編寫的最經典的C語言教材,原書名叫《The C Programming Language》當然,這本書不太適合0起點的人,看這本書之前最好把《C程序設計》(譚浩強,清華大學)看了,老譚的書銷量突破700萬冊了,雖然比較舊了,也不太符合新標准(現在出第3版了,也還是)但是,入門還是不錯的選擇。

另外還有必看的是《C Primer Plus》這個是一個美國人寫的,人民郵電出版社出了中文版了,第5版,比較厚,磚頭書,60元。但是非常適合初學的人,非常詳細。

還有《從問題到程序——程序設計與C語言引論》機械工業出版社,這本書也很不錯。

看完這些,就可以看演算法的書了,比如數據結構什麼的,這方面的書很多。如果想在程序界發展,那麼有部重量級的著作不得不看《The Art of computer programming》一共三卷,有翻譯版《計算機程序設計的藝術》這三卷書非常深,比較難,蓋茨說,誰如果把這上面的習題都做對了,直接可以到微軟上班了。

另外學習C語言要養成良好的程序風格,這點一定要注意練習!

6. 我想學c語言有什麼書好推薦的

入門:剛開始入門的話,可以先看《C Primer Plus中文版》(如果你英語好,可以看英文版《C Primer Plus 》),書後的題目推薦做一下。 很多人對譚浩強的《C語言程序設計》褒貶不一,我覺得這本書內容相對上面那本要少,看完後基本會寫小程序,也可以用來入門。上面那本確實是入門經典。
進階:《C專家編程 》,《C陷阱與缺陷》 ,《C和指針》,進階就看這三本書。《你必須知道的495個C語言問題》也可以看一下。
再深入的話,就是 《C語言參考手冊》,《C標准庫》,《 C語言介面與實現 》(必看),《C語言的科學和藝術》,《C程序設計語言》 (聖經)這幾本書了。

7. 怎麼才能學會c語言

我一直這么回答。
我認為,學好編程有四個方面:語言、演算法和數據結構、系統調用和設計。

語言。我可以告訴你C語言有兩大主題你要好好學,一個是內存管理,一個是指針!這個世界上90%以上的C/C++出的嚴重性錯誤全是和這兩個有關。不要看譚浩強的那本書,那本是本爛書。推薦這本書給你《C程序設計語言(第2版·新版)》

演算法和數據結構。我認為,用C語言實現演算法和數據結構莫過於最爽的事情。推薦你看這本書——演算法:C語言實現(第1~4部分)基礎知識、數據結構、排序及搜索(原書第3版),還有那本經典的《演算法導論》
系統設計。關於設計方面,我全力推薦《Unix編程藝術》,看完以後,你就明白什麼是真正的編程文化了。然後,當你看到Windows的Fans的某些言論時,你就知道什麼叫一笑了之了。

8. C語言編程,輸入2個實數,求它們的平均值。

#include<stdio.h>
intmain()
{
doublea,b,avg;
scanf("%lf%lf",&a,&b);
avg=(a+b)/2;
printf("avg=%lf ",avg);
return0;
}

9. c語言編程

//計劃做的腳本引擎的一部分
//參考的 C++編程藝術
//總地來說會有一些難度
//我的是C++應該會給你一些啟發
//TypeDef.h
#include "windows.h"
#ifndef B_TYPE_DEF_H
#define B_TYPE_DEF_H
const int MAX_T_LEN = 128;//可以分析的最大符號長度(同時決定了一個字元變數的最大長度為128位元組)
const int MAX_ID_LEN = 31;//允許的最大的標識長度(一個標識符是指一個變數名或函數名)
const int MAX_BUF_LEN = 1024;//解釋緩沖區1024位元組
const int NUM_PARAMS = 32;//最大參數數目
const int MAX_DIM_NUM = 65536//數組最大維數
//需要分析的所有東西
enum Token_Item { UNDEF=1, //未定義
E_TEMP,//當模板使用
E_CHAR,//char關鍵字
E_INT,//int關鍵字
E_FLOAT,//float關鍵字
E_SWITCH,//switch關鍵字
E_CASE,//case關鍵字
E_IF,//if關鍵字
E_ELSE,//else關鍵字
E_FOR,//for關鍵字
E_DO,//do關鍵字
E_WHILE,//while關鍵字
E_BREAK,//break關鍵字
E_RETURN,//return關鍵字
E_COUT,//cout關鍵字
E_CIN,//cin關鍵字
LBLOCK, //{
RBLOCK,//}
DOU,//,
EOS,//;
MAO,//:
SFEN,//'已舍棄,不含'分析
LT,//<
LE,//<=
GT,//>
GE,//>=
EQ,//==
NE,//!=
FF,//.
LK,//(
NOT,//!
INC,//++
DEC,//--
ADD,//+
SUB,//-
RK,//)
LZK,//[
RZK,//]
LS,//<<
RS,//>>
ASS,//=
AND,//&&
OR,//||
MUL,//*
DIV,///
MOD,//%
POW,//^
NUMBER, //數字
IDENTIFIER,//標識
STRING,//字元串
END//文件結束
};//需要分析的全部符號

enum Token_Type{
UNK,//未知類型
KEY,//關鍵字
FJF,//分界符
CMP,//比較運算符
OPE,//運算符
NUM,//數字
IDE,//標識符
STR,//字元串
NON,//結束符號
UDF//未定義
};

typedef struct Token_Table{//符號表
char name[MAX_T_LEN];
Token_Item token;
Token_Type type;
} TOKEN_TABLE,*PTOKEN_TABLE;

enum error_msg //錯誤類型
{ SYNTAX=1000, NO_EXP, NOT_VAR, DUP_VAR, DUP_FUNC,
SEMI_EXPECTED, UNBAL_BRACES, FUNC_UNDEF,
TYPE_EXPECTED, RET_NOCALL, PAREN_EXPECTED,
WHILE_EXPECTED, QUOTE_EXPECTED, DIV_BY_ZERO,
BRACE_EXPECTED, COLON_EXPECTED,FAIL_OPEN,ERROR_SIZE,
NO_MAIN,ERROR_ASSIGN,ERROR_RZK,ERROR_DIM};

class InterpExc { //錯誤類
error_msg err;
public:
InterpExc(error_msg e) { err = e; }
error_msg get_err() { return err; }
};

enum Vars{類型
V_Int,
V_Float,
V_String,
V_pInt,
V_pFloat,
V_pString,
V_Udef
};
#endif
#ifndef V_NULL
#define V_NULL (-1)
#endif

//Cfenxi.h

#include "TypeDef.h"
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
#include <string>

using namespace std;
//Fenxi類說明
//curr_pt始終指向將要分析的地址
//prev_pt為前一個分析的地址
//可以使用函數GotoPt來改變當前分析地址
//分析結果放在變數stoken,item,type
//在Cfenxi.cpp中定義了一個文件級變數TOKEN_TABLE tokentable[];
//在使用的時候必須聲明這個變數

#ifndef B_CFENXI_H
#define B_CFENXI_H

class Fenxi{

public:
char stoken[MAX_T_LEN+1];//分析出來的符號名
char buff[MAX_BUF_LEN+1];//緩沖區
Token_Item item;//分析出來的具體符號
Token_Type type;//符號大類

long curr_pt;//當前分析點
long prev_pt;//前一個分析點
char pFileName[256];//腳本文件名
PTOKEN_TABLE pTokenTable;//符號表
public:
Fenxi(){};
~Fenxi(){};
void Create(char*,PTOKEN_TABLE,int);//創建分析對象
void GetToken();//分析一步
void GotoPt(long);//跳分析點
void PutBack();//回退一個分析點
private:
int nTableItem;//分析表中的分析數目
long iFileLength;//腳本文件長度
int iBlock;//當前所在區塊
int iYouBiao;//當前游標
char cbuff;//當前所指向的字元
char cbuff1;//超前搜索的字元

void MoveNext();//向下移動
void MovePrev();//向前移動
void LoadBlock();//裝入一個塊
long GetPt(int i,int n){return (long)(i*MAX_BUF_LEN+n);};//計算位置
bool KeyLookUp(char*,Token_Item &);//查找是不是關鍵詞
bool isdelim(char);
};
//解釋類
class var_value{
public:
char string_value[MAX_T_LEN+1];
int int_value;
float float_value;
Vars v_type;
public:
var_value()
{
int_value=0;
float_value=0;
string_value[0]=0;
v_type=Udef;
}
var_value(const var_value&);
set_type(Vars type){v_type=type;}
~var_value(){}
friend bool operator == (const var_value& _X, const var_value& _Y);
friend bool operator < (const var_value& _X, const var_value& _Y);
};

class temp_var_value{
public:
char string_value[MAX_T_LEN+1];
int int_value;
float float_value;
int p_int;
int p_float;
int p_string;
vector<int> dim;
Vars v_type;
public:
temp_var_value()
{
int_value=0;
float_value=0;
string_value[0]=0;
p_int=p_float=p_string=V_NULL;
v_type=Udef;
};
temp_var_value(const temp_var_value&);
temp_set_type(Vars type){v_type=type;}
~temp_var_value(){}
friend bool operator == (const temp_var_value& _X, const temp_var_value& _Y);
friend bool operator < (const temp_var_value& _X, const temp_var_value& _Y);
};

struct var_type { //變數類型
char var_name[MAX_ID_LEN+1]; // 變數名
Vars v_type;//數據類型
vector<var_value> value; //變數值
vector<int> v_dim;//變數維數
int v_max;//變數的最大數目
};

struct func_type {
char func_name[MAX_ID_LEN+1]; //函數名
Vars ret_type; //返回值類型
long loc; // 函數入口點,函數的入口點是指分析點指向函數括弧後第一個字元
};

class Script{
public:
Fenxi theFx;//詞法分析對象,負責對腳本文件的操作
char FileName[256];//腳本文件名
var_value ret_value;//返回值
bool breakfound;//中斷
public:
Script(){};
~Script(){};
void Create(char*,PTOKEN_TABLE,int);//創建腳本對象
void ExecuteScript();//開始解釋腳本
private:
void PreScan();//預掃描
void decl_global();//聲明全局變數
long find_func(char*);//返回函數的入口點
void ItemToVar(Token_Item,Vars&);//根據一個項,得到相當的變數類型
void CallFun();//執行一個函數
void get_args();//得到函數的形式參數名
void Interp();//具體解釋
private:
void eval_exp (var_value &value);
void eval_exp0(var_value &value);
void eval_exp1(var_value &value);
void eval_exp2(var_value &value);
void eval_exp3(var_value &value);
void eval_exp4(var_value &value);
void eval_exp5(var_value &value);
void eval_exp6(var_value &value);
void eval_exp7(var_value &value);
void eval_exp8(var_value &value);
bool is_var(char *s);
// 變數名,變數的維數,變數的值,變數的類型
void assign_var(char *var_name,int idx, var_value value);
void find_var_value(char *var_name,int idx,var_value& value);
int find_idx(vector<int>,vector<int>);// 計算[][]
void find_vector(vector<int> &);//讀取[]
int cal_idx(vector<int>);
Vars is_var_type;//使用is_var的時候如果返回值是真那麼這個變數存儲了變數類型
public:
//每執行一個函數的時候就把進入前的局部變數數目
//放到函數結點棧,函數執行完的時候就根據棧里的
//數據改變局部函數表裡的變數,從而實現變數的靈活使用
//同理塊結點棧的原理也一樣

//變數表
vector<var_type> global_vars; //全局變數表
vector<var_type> local_var_stack; //局部變數表(函數參數作為局部變數處理)

vector<func_type> func_table; //函數表
stack<int> func_call_stack;//函數結點棧
stack<int> nest_scope_stack;//塊結點棧
};

#endif

//Fenxi.cpp
#include "CFenxi.h"
#include <cstring>
#include <cctype>
#include <fstream>
#include <cstdio>
#include <cmath>
using namespace std;
///////////////////////////////////////////////////////////////////////
/////////////////////////詞法分析類的函數定義//////////////////////////
///////////////////////////////////////////////////////////////////////
extern TOKEN_TABLE tokentable[]={
"char",E_CHAR,KEY,
"int",E_INT,KEY,
"float",E_FLOAT,KEY,
"switch",E_SWITCH,KEY,
"case",E_CASE,KEY,
"if",E_IF,KEY,
"else",E_ELSE,KEY,
"for",E_FOR,KEY,
"do",E_DO,KEY,
"while",E_WHILE,KEY,
"break",E_BREAK,KEY,
"return",E_RETURN,KEY,
"cout",E_COUT,KEY,
"cin",E_CIN,KEY,
"{",LBLOCK,FJF,
"}",RBLOCK,FJF,
",",DOU,FJF,
";",EOS,FJF,
"<",LT,CMP,
"<=",LE,CMP,
">",GT,CMP,
">=",GE,CMP,
"==",EQ,CMP,
"!=",NE,CMP,
".",FF,OPE,
"(",LK,OPE,
")",RK,OPE,
"[",LZK,OPE,
"]",RZK,OPE,
"++",INC,OPE,
"--",DEC,OPE,
"<<",LS,OPE,
">>",RS,OPE,
"=",ASS,OPE,
"!",NOT,OPE,
"&&",AND,OPE,
"||",OR,OPE,
"+",ADD,OPE,
"-",SUB,OPE,
"*",MUL,OPE,
"/",DIV,OPE,
"%",MOD,OPE,
"^",POW,OPE,
};

var_value::var_value(const var_value& p)
{
int_value=p.int_value;
float_value=p.float_value;
strcpy(string_value,p.string_value);
v_type=p.v_type;
}

bool operator == (const var_value& _X, const var_value& _Y)
{
if (_X.v_type != _Y.v_type)
{
return false;
}
else
{
switch (_X.v_type)
{
case V_Float:
return (abs(_X.float_value - _Y.float_value) < 0.0001);
break;
case V_Int:
return (_X.int_value == _Y.int_value);
break;
case V_Int:
return !(strcmp(_X.string_value, _Y.string_value));
break;
default:
return false;
}
}
}

bool operator < (const var_value& _X, const var_value& _Y)
{
if (_X.v_type != _Y.v_type)
{
return false;
}
else
{
switch (_X.v_type)
{
case V_Float:
return (_X.float_value < _Y.float_value);
break;
case V_Int:
return (_X.int_value < _Y.int_value);
break;
case V_Int:
return !(strcmp(_X.string_value, _Y.string_value));
break;
default:
return false;
}
}

temp_var_value::temp_var_value(const temp_var_value& p)
{
int_value=p.int_value;
float_value=p.float_value;
strcpy(string_value,p.string_value);
p_int=p.p_int;
p_float=p.p_float;
p_string=p.p_string;
v_type=p.v_type;
}
void Fenxi::Create(char* p,PTOKEN_TABLE ptt,int n)
{
strcpy(pFileName,p);
ifstream fin(pFileName,ios::in|ios::binary);
fin.seekg(0,ios::end);
iFileLength=fin.tellg();
fin.close();
if(iFileLength==0)
throw InterpExc(ERROR_SIZE);

iBlock=0;
LoadBlock();
MoveNext();//指向第一個字元
iYouBiao=0;//置游標於文件頭
curr_pt=0;
prev_pt=0;
cbuff=buff[0];//當前應該分析字元
cbuff1=buff[1];//超前搜索字元

pTokenTable=ptt;
nTableItem=n;//分析表設置

}

void Fenxi::MoveNext()
{
if(iYouBiao==MAX_BUF_LEN-1)//如果當前游標在緩沖區尾
{
iBlock++;
LoadBlock();
cbuff=buff[0];
cbuff1=buff[1];//超前搜索
}
else
{
iYouBiao++;
cbuff=buff[iYouBiao];
if(iYouBiao==MAX_BUF_LEN-1)//超前搜索
{
char temp[2];
temp[1]=0;
ifstream fin(pFileName,ios::in|ios::binary);
fin.seekg(MAX_BUF_LEN*(iBlock+1));
fin.read(temp,1);
int i=fin.gcount();
temp[i]=0;
fin.close();
cbuff1=temp[0];
}
else
cbuff1=buff[iYouBiao+1];
}

curr_pt=GetPt(iBlock,iYouBiao);
}

void Fenxi::MovePrev()
{
if(iYouBiao==0)//如果當前游標在緩沖區頭
{
cbuff1=cbuff;//超前搜索
iBlock--;
LoadBlock();
iYouBiao=MAX_BUF_LEN-1;
cbuff=buff[iYouBiao];
}
else
{
cbuff1=cbuff;//超前搜索
iYouBiao--;
cbuff=buff[iYouBiao];
}

curr_pt=GetPt(iBlock,iYouBiao);
}

void Fenxi::PutBack()
{
GotoPt(prev_pt);
}

void Fenxi::LoadBlock()//裝入一個塊
{
ifstream fin(pFileName,ios::in|ios::binary);
fin.seekg(MAX_BUF_LEN*iBlock);
fin.read(buff,MAX_BUF_LEN);
int i=fin.gcount();
buff[i]=0;
iYouBiao=0;
fin.close();
}

void Fenxi::GotoPt(long pt)
{

if(pt/MAX_BUF_LEN==curr_pt/MAX_BUF_LEN)//如果是在同一個塊內的話
{
curr_pt=pt;
iYouBiao=curr_pt-iBlock*MAX_BUF_LEN;
cbuff=buff[iYouBiao];
}
else//否則要重新裝入內存
{
curr_pt=pt;
iBlock=curr_pt/MAX_BUF_LEN;
LoadBlock();
iYouBiao=curr_pt-iBlock*MAX_BUF_LEN;
cbuff=buff[iYouBiao];
}

if(iYouBiao==MAX_BUF_LEN-1)//超前搜索
{
char temp[2];
temp[1]=0;
ifstream fin(pFileName,ios::in|ios::binary);
fin.seekg(MAX_BUF_LEN*(iBlock+1));
fin.read(temp,1);
int i=fin.gcount();
temp[i]=0;
fin.close();
cbuff1=temp[0];
}
else
cbuff1=buff[iYouBiao+1];
}

void Fenxi::GetToken()
{

prev_pt=curr_pt;//保存前一個的位置
char *temp; //利用一個指針向字元里寫內容
item=UNDEF;type=UDF;

temp = stoken;
*temp = '\0';

// 如果當前字元是空格且未到文件末
while(isspace(cbuff) && cbuff) MoveNext();

// 跳過行
while(cbuff == '\r') {
MoveNext();
MoveNext();
while(isspace(cbuff) && cbuff) MoveNext();
}

// 是否結尾
if(cbuff == '\0') {
*stoken = '\0';
item = END;
type=NON;
return ;
}

// 檢查{}標識符
if(strchr("{}", cbuff)) {

stoken[0]=cbuff;
stoken[1]='\0';
type=FJF;
if(cbuff=='{')
item=LBLOCK;
else
item=RBLOCK;
MoveNext();//指向下一個字元
return ;
}
// 檢查注釋信息
if(cbuff == '/')
if(cbuff1 == '*') { // /*注釋符
MoveNext();
MoveNext();
do { // 找到結尾
while(cbuff != '*') MoveNext();
MoveNext();
} while (cbuff != '/');
MoveNext();
GetToken();
return;
} else if(cbuff1 == '/') { // is a // CMPment
MoveNext();
MoveNext();
// Find end of CMPment.
while(cbuff != '\r' && cbuff != '\0') MoveNext();
if(cbuff == '\r') {MoveNext();MoveNext();}
GetToken();
return;
}

// 檢查雙操作符
if(strchr("!<>=+-&|", cbuff)) {
switch(cbuff) {
case '|':
if(cbuff1 == '|') {
MoveNext();MoveNext();
*temp = '|';
temp++;
*temp = '|';
temp++;
*temp = '\0';
item=OR;
type=OPE;

}
break;
case '&':
if(cbuff1 == '&') {
MoveNext();MoveNext();
*temp = '&';
temp++;
*temp = '&';
temp++;
*temp = '\0';
item=AND;
type=OPE;

}
break;

case '=':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '=';
temp++;
*temp = '=';
temp++;
*temp = '\0';
item=EQ;
type=CMP;

}
break;
case '!':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '!';
temp++;
*temp = '=';
temp++;
*temp = '\0';
item=NE;
type=CMP;
}
break;
case '<':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '<';
temp++;
*temp = '=';
item=LE;
type=CMP;
}
else if(cbuff1 == '<') {
MoveNext();MoveNext();
*temp = '<';
temp++;
*temp = '<';
item=LS;
type=OPE;
}
else {
MoveNext();
*temp = '<';
item=LT;
type=CMP;
}
temp++;
*temp = '\0';
break;
case '>':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '>';
temp++;
*temp = '=';
item=GE;
type=CMP;
} else if(cbuff1 == '>') {
MoveNext();MoveNext();
*temp = '>';
temp++;
*temp = '>';
item=RS;
type=OPE;
}
else {
MoveNext();
*temp = '>';
item=GT;
type=CMP;
}
temp++;
*temp = '\0';
break;
case '+':
if(cbuff1 == '+') {
MoveNext();MoveNext();
*temp = '+';
temp++;
*temp = '+';
temp++;
*temp = '\0';
item=INC;
type=OPE;
}
break;
case '-':
if(cbuff1 == '-') {
MoveNext();MoveNext();
*temp = '-';
temp++;
*temp = '-';
temp++;
*temp = '\0';
item=DEC;
type=OPE;
}
break;
}

if(*stoken) return;
}

// 其它運算符號
if(strchr("+-*^/=().[]|!%", cbuff)) {
type=OPE;
switch(cbuff){
case '+':
item=ADD;break;
case '-':
item=SUB;break;
case '*':
item=MUL;break;
case '/':
item=DIV;break;
case '=':
item=ASS;break;
case '(':
item=LK;break;
case ')':
item=RK;break;
case '[':
item=LZK;break;
case ']':
item=RZK;break;
case '.':
item=FF;break;
case '|':
item=UNDEF;type=UDF;break;
case '!':
item=NOT;break;
case '%':
item=MOD;break;
}
*temp = cbuff;
MoveNext();
temp++;
*temp = '\0';
return ;
}

// 分界符號
if(strchr(";,#:", cbuff)) {
type=FJF;
switch(cbuff){
case ';':
item=EOS;break;
case ',':
item=DOU;break;
case ':':
item=MAO;break;
}
*temp = cbuff;
MoveNext();
temp++;
*temp = '\0';
return ;
}

// 讀取一個字元串
if(cbuff == '"') {
MoveNext();
while(cbuff != '"' && cbuff != '\r' && cbuff) {
// Check for \n escape sequence.
if(cbuff == '\\') {
if(cbuff1 == 'n') {
MoveNext();
*temp++ = '\n';
}
}
else if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;

MoveNext();
}
if(cbuff == '\r' || cbuff == 0)
throw InterpExc(SYNTAX);
MoveNext(); *temp = '\0';
item=STRING;
type=STR;
return ;
}

// 讀取一個數字
if(isdigit(cbuff)) {
while((cbuff>='0'&&cbuff<='9')||(cbuff=='.')) {
if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;
MoveNext();
}
*temp = '\0';
item=NUMBER;
type=NUM;
return ;
}

// Read identifier or keyword.
if(isalpha(cbuff)) {
while(!isdelim(cbuff)) {
if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;
MoveNext();
}
item=E_TEMP;
}

*temp = '\0';

// Determine if token is a keyword or identifier.
if(item == E_TEMP) { // convert to internal form
if(KeyLookUp(stoken,item)) type=KEY; // is a keyword
else {type = IDE;item=IDENTIFIER;}
}
if(type==UDF)
throw InterpExc(SYNTAX);

}

bool Fenxi::KeyLookUp(char *s,Token_Item &it){
int i;
// char *p;

// 轉為小寫字母
// p = s;
// while(*p) { *p = tolower(*p); p++; }

for(i=0; i<nTableItem; i++) {
if((tokentable[i].type==KEY)&&!strcmp(tokentable[i].name, s))
{
it=tokentable[i].token;
return true;
}
}

return false;
}

// 符號檢查
bool Fenxi::isdelim(char c)
{
if(strchr(" !:;,+-<>/*^=().|&[]\"%", c) || c == 9 ||
c == '\r' || c == 0) return true;
return false;
}