C語言程序設計教程_第1頁
C語言程序設計教程_第2頁
C語言程序設計教程_第3頁
C語言程序設計教程_第4頁
C語言程序設計教程_第5頁
已閱讀5頁,還剩799頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

(第3版)林雄主講

2007.9C語言程序設計教程第1章C語言程序設計的概念第2章基本數據類型第3章C語言的流程控制第4章模塊化程序設計第5章數組第6章指針第7章用戶定制數據類型第8章文件第9章面向對象的程序設計介紹第1章C語言程序設計的概念1.1程序與程序設計語言1.2

C語言及其標準1.3

C語言程序概要1.1程序與程序設計語言

1.1.1常量一提起計算機,人們就會聯想到鍵盤、顯示器和主機。其實,應用要早得多、并一直流傳至今的計算機工具是算盤(見圖1.1)。那么,現代電子計算機與算盤的最大區別在哪里呢?關鍵在于現代計算機可以自動完成計算過程,而算盤進行的計算過程是在人的撥動下才能進行。圖1.1算盤那么,為什么現代計算機可以自動完成計算過程呢?這首先要從程序說起。程序實際上是一個非常普通的概念:按照一定的順序安排的工作步驟。可以說,做任何事情都有相應的程序。做的事情不同,要求的效果不同,程序就不同。例如,用同樣的原料,采用不同的程序,會做出不同的菜肴來。一種工具能夠自動工作,一是要有記憶功能,能夠記住程序;二是具有按照程序控制相關部件操作的能力。如果能讓算盤記住做某種計算的口訣和計算的數據,并且有能按照口訣控制算珠自動運動的機制,則只要發出開始執行的命令,算盤就會自動完成計算。可惜這樣的機制并沒有在算盤中實現。但是,卻有另外一種機器卻在這方面向前推進了一步。這就是明朝末年宋應星在其《天工開物》中記載的中國古代提花機(見圖1.2)圖1.2中國古代的提花機中國提花機大約出現于西漢末年(公元前)。它采用用絲線結成的“花本”(花版)控制經線起落,以織成要求的圖樣。這是最早的程序控制思想。后來,提花機沿著絲綢之路傳到歐洲,歷經改進,1805年法國人JosephJacquard制造成功用穿孔卡片(見圖1.3)控制連桿(橫針),用有孔和無孔進一步控制經線起落的提花機。圖1.3穿孔卡片

穿孔卡片把程序控制技術向前推進了一步。這一技術被一位英國數學家CharlesBabbage(見圖1.4)引入到了計算機中機,用有孔和無孔的組合來表示數據和程序。圖1.4英國數學家CharlesBabbage

18世紀末,法國數學界調集大批數學家,組成了人工手算的流水線,經過長期艱苦奮斗,終于完成了17卷《數學用表》的編制,但是,手工計算出的數據出現了大量錯誤。這件事情強烈刺激了Babbage。1812年20歲的Babbage開始計算機的研制工作,他要把函數表的復雜算式轉化為差分運算,用簡單的加法代替平方運算,快速編制不同函數的數學用表,并將這種機器稱為“差分機”。經過十年的努力,終于于1822年完成了第一臺差分機,可以處理3個不同的5位數,計算精度達到6位小數。1833年他又開始投身于一種“會分析的機器”——分析機的研制中。他把機器設計成三個部分,一是用來儲存數據信息的“倉庫(TheStore)”,二是進行數據運算處理的“工場(Themill)”,三是使用穿孔卡片來輸入程序并用穿孔卡片輸出數據。這臺機器雖然沒有制造成功,但它的工作原理—程序存儲控制為今天的計算機奠定了基礎:(1)任何工具的工作,都是由程序控制的;(2)只有工具具有了記憶程序的功能,并具有了按照程序進行自我控制的功能,該工具才能自動工作。

1.1.2計算機程序設計語言程序要需要用某種形式(語言)來描述。例如,用算盤進行計算,程序是用口訣描述的,珠算的語言是口訣?,F代計算機的程序則是用計算機程序設計語言來描述的。從計算機誕生到今天,程序設計語言也在伴著計算機技術的進步不斷升級換代。1.1.2計算機程序設計語言

程序要需要用某種形式(語言)來描述。例如,用算盤進行計算,程序是用口訣描述的,珠算的語言是口訣?,F代計算機的程序則是用計算機程序設計語言來描述的。從計算機誕生到今天,程序設計語言也在伴著計算機技術的進步不斷升級換代。1.機器語言一種CPU的指令系統,也稱該CPU的機器語言,它是該CPU可以識別的一組由0和1序列構成的指令碼。下面是某CPU指令系統中的兩條指令:

10000000(進行一次加法運算)

10010000(進行一次減法運算)用機器語言編程序,就是從所使用的CPU的指令系統中挑選合適的指令,組成一個指令系列。這種程序雖然可以被機器直接理解和執行,卻由于它們不直觀,難記、難認、難理解、不易查錯,只能被少數專業人員掌握,同時編寫程序的效率很低,質量難以保證。這種繁重的手工方式與高速、自動工作的計算機極不相稱。這種方式僅使用于計算機出現的初期(使用穿孔紙帶的時期)的編程(用有孔、無孔,分別代表1、0),現在已經不再使用。

2.匯編語言為減輕人們在編程中的勞動強度,20世紀50年代中期人們開始用一些“助記符號”來代替0,1碼編程。如前面的兩條機器指令可以寫為

A+B=>A或ADDA,B

A-B=>個樣A或SUBA,B這種用助記符號描述的指令系統,稱為符號語言或匯編語言。用匯編語言編程,程序的生產效率及質量都有所提高。但是匯編語言指令是機器不能直接識別、理解和執行的。用它編寫的程序經檢查無誤后,要先翻譯成機器語言程序才能被機器理解、執行。這個翻譯轉換過程稱為“代真”。代真后得到的機器語言程序稱為目標程序(objectprogram),代真以前的程序,稱為源程序(sourceprogram)。由于匯編語言指令與機器語言指令基本上具有一一對應的關系,所以匯編語言源程序的代真可以由匯編系統以查表的方式進行。匯編語言與機器語言,都是依CPU的不同而異,它們都稱為面向機器的語言。用面向機器的語言編程,可以編出效率極高的程序。但是程序員用它們編程時,不僅要考慮解題思路,還要熟悉機器的內部結構,并且要“手工”地進行存儲器分配。這種編程的勞動強度仍然很大,給計算機的普及推廣造成很大的障礙。

3.高級語言匯編語言和機器語言是面向機器的,不同類型的計算機所用的匯編語言和機器語言是不同的。1954年出現的FORTRAN語言以及隨后相繼出現的其它高級語言,開始使用接近人類自然語言的、但又消除了自然語言中的二義性的語言來描述程序。這些高級語言使人們開始擺脫進行程序設計必須先熟悉機器的桎梏,把精力集中于解題思路和方法上。第一種高級語言是1954年問世的FORTRAN語言。此后不久,不同風格、不同用途、不同規模、不同版本的面向過程的高級語言便風涌而起。據統計,全世界已有2500種以上的計算機語言,其中使用較多的有近百種。圖1.5為幾種廣泛流行的高級語言的發展變遷情況。5254565860626466687072747678808284868890929496AdaALGOL60ALGOL68PascalModula-2CPLBCPLBCC++JavaLISPPROLOGCOBOLFORTRAN77FORTRANPL/1Simula67Smalltalk80BASICANSI-BASICQBASICVBFORTRAN90<>圖1.5幾種廣泛流行的高級語言的發展變遷情況

1.1.3高級語言程序的開發過程一般來說,程序開發的一般過程有如圖1.6所示幾個步驟圖1.6高級語言程序的開發過程

1.分析一般來說,一個具體的問題要涉及許許多多的方面,這是問題的復雜性所在。為了便于求解,往往要忽略一些次要方面。這種通過忽略次要方面,而找出解題規律,就稱為建立模型。

2.建立模型,表現模型表現模型就是用一種符號-語言系統來描述模型。一般來說,模型的表現會隨著對問題抽象程度的加深和細化,不斷由領域特色向計算機可解釋、執行靠近,中間也可能采用一些其他的符號系統,如流程圖等,直到最后用一種計算機程序設計語言描述出來。

3.源程序的編輯源程序的編輯就是在某種字處理環境下,用具體的程序設計語言書寫并修改的過程。為此就要掌握一種計算機程序設計語言。還要應用一種專用程序編輯器或通用的文字編輯器進行。

4.程序的編譯(或解釋)與鏈接寫出一個高級語言程序后,并不是就可以立即拿來執行。要讓機器直接執行,還要將它翻譯成由機器可以直接辨認并可以執行的機器語言程序。為區別它們,把用高級語言寫的程序(文件)稱為源程序(文件),把機器可以直接辨認并執行的程序(文件)稱為可執行程序(文件)。這一過程一般分為兩步:第1步:在程序編輯過程中輸入到源文件中的是一些字符碼,但是機器可以直接處理的是0、1信息。為此,首先要將源程序文件翻譯成0、1碼表示的信息,并用相應的文件保存。這種保存0、1碼信息的文件稱為目標程序文件。由源文件翻譯成目標文件的過程稱為編譯。在編譯過程中,還要對源程序中的語法和邏輯結構進行檢查。編譯任務是由稱做編譯器(compiler)的軟件完成的。目標程序文件還不能被執行,它們只是一些目標程序模塊。第2步:將目標程序模塊以及程序所需的系統中固有的目標程序模塊(如執行輸入輸出操作的模塊)鏈接成一個完整的程序。經正確鏈接所生成的文件才是可執行文件。完成鏈接過程的軟件稱為鏈接器(linker)。圖1.7為編譯和鏈接過程的示意圖。程序在編譯、鏈接過程中,也可能發現錯誤。這時要重新進入編輯器進行編輯。圖1.7編譯和鏈接過程的示意圖

5.程序的測試與調試經編譯、鏈接的程序文件,生成可執行文件,就可以讓計算機執行了。但是,并不是就可以得到預期的結果而交付用戶使用了,因為程序仍然會存在某些錯誤。因此,每一個人編寫出一個程序后,在正式交付使用前,總要試通一下?!霸囃ā本褪窃囘\行程序,也就是對程序進行測試。測試是以程序通過編譯、沒有語法和鏈接上的錯誤為前提,目的是找出程序中可能存在的錯誤并加以改正。因此,應該測試程序在不同情況下運行的情況,輸入不同的數據可以檢測出程序在不同情況下運行的情況。測試的數據應是以“程序是會有錯誤的”為前提精心設計出來的,而不是隨心所欲地亂湊而成的。它不僅應含有被測程序的輸入數據,而且還應包括程序執行它們后預期的結果。每次測試都要把實際的結果與預期的結果相比較,以觀察程序是否出錯。

6.編寫程序文檔經過了問題分析、設計、程序編碼、測試后,程序開發的工作基本上結束了。但是,這時還不能交付使用。因為,隨著程序規模的增大和日益復雜化,程序的使用和運行也越來越不那么直接,用戶要運行程序,還需要知道許多信息,如:

●程序的功能

●需要輸入的數據類型、格式和取值范圍

●需要使用的文件數量、名稱、內容以及存放位置等

●程序運行需要的軟、硬件環境

●程序的裝入、啟動方法以及交互方式等。為此,程序開發者需要向用戶提供這些資料——稱為程序使用說明書或用戶文檔。需要說明的是,在許多軟件中,這些內容已經部分或全部地以“readme”或“help”的形式提供。目前,程序文檔已經成為軟件開發產品的必要部分。文檔在程序使用和維護中的重要性也改變了軟件的概念,使之由早期的“軟件是計算機程序的總稱”演化為“軟件是計算機的程序連同計算機化的文檔的總稱?!?.程序的維護程序交付用戶使用之后,并不是萬事大吉了。由于多種原因,還可能要對程序進行修改。交付之后對程序的修改稱為程序的維護。維護程序的原因主要有:

●原來的程序沒有完全滿足用戶要求;

●用戶要求的改變;

●程序中遺留有錯誤,在運行中被發現。程序的維護可以由開發者進行,也可能是由別人進行。為能便于程序的維護,開發者應當提供必要的技術資料,并且要保證程序的可讀好——能讓人看懂。1.2C語言及其標準1.2.1C語言的出現

C語言是目前程序設計領域中最有影響力的一種程序設計語言。可是,它卻是“漫不經心”地開發出來的。

20世紀60年代,Bell實驗室的KenThompson(見圖1.8)著手開發后來對計算機產生了巨大影響的UNIX操作系統。為了描述UNIX,Thompson首先將當時的一種專門用來描述系統程序的BCPL語言改進為他稱為B的語言。1970年Thompson發表了用匯編語言和B語言寫成的PDP-7上實現UNIX的初版。

1971年,DennisRitchie(見圖1.8)開始協助Thompson開發UNIX。他對B語言做了進一步的充實和完善,加入數據類型和新的句法,于1972年推出了一種新型程序設計語言——C語言(取BCPL的第2個字母)。為了使UNIX操作系統推廣,1977年DennisM.Ritchie

發表了不依賴于具體機器系統的C語言編譯文本《可移植的C語言編譯程序》。于是,C語言是借助UNIX操作系統的翅膀而起飛的,UNIX操作系統也由于C而得已快速移植落地生根,兩者相輔相承,成就了軟件開發史上歷時30年的時代。

1978年BrianW.Kernighian和DennisM.Ritchie出版了名著《TheCProgrammingLanguage》,從而使C語言成為目前世界上流行最廣泛的高級程序設計語言。以后,又有多種程序設計語言在C語言的基礎上產生,如C++、VisualC++、Java、C#等。圖1.8Thompson(左)和Ritchie(中)于1999

年接受當時美國總統克林頓授予的國家技術勛章1.2.2C語言的標準

C語言的靈活性、豐富性、可移植性很快得到了普遍的承認,接著適合于各種不同操作系統(UNIX,MS-DOS,CP/M-80,86等)和不同機種(字長為8bit~32bit)的C語言編譯系統相繼出現。1982年美國國家標準局(ANSI)語言標準化委員會成立了一個委員會開始著手進行C語言的標準化工作,并于1983年公布了第一個C語言標準草案(83ANSIC)。1989年,ASNI又發布了一個完整的C語言標準——ANSIX3.159-1989,通常稱做“ANSIC”,簡稱“C89”。1990年,國際標準組織ISO/JECJTC1/SC22/WG14采納了C89,做了少編輯性修改后,以國際標準ISO/IEC9899:1990發布,通常稱其為“C90”,它同C89基本相同。

1995年,WG14對C89做了兩處技術修訂和一個擴充。人們將其稱為“C89增補1”或“C95”。同時,WG14開始著手對C標準做全面修訂,并于1999年完成獲得通過,形成正式的C語言標準,命名為ISO/IEC9899:1999,簡稱“C99”。本書將基于C99介紹C語言程序設計的基本方法。目前各廠家所提供的所有C編譯系統都還未實現C99所建議的功能。為了讀者能實際運行C程序,本書所介紹的程序都是符合ASNIC標準并能在大多數C編譯系統通過和運行的程序。但在文字敘述中,會介紹C99所增加的新功能,以使讀者今后能順利地過渡到用C99編程。1.3C語言概要1.3.1函數任何一部機器都是用部件組裝而成的。計算機程序和機器一樣,也是由一些部件構建起來的。C語言程序部件是函數。也就是說,設計C語言程序就是設計它的構成函數。下面舉例說明C語言程序中的函數是什么樣的。例1.1一個輸出一串字符的C程序。/*文件名:ex010101.c*/#include<stdio.h>int

main(void){

printf("Programmingisfun.");//輸出一串字符

return0;/*向操作系統返回一個數字0*/}這是一個非常簡單的C語言程序,它的執行結果是顯示一行字符:

Programmingisfun.說明:(1)這里

intmain(void){ …}是一個函數。這個函數的名字為“main”。這個名字是專用的,表示這個函數是“主函數”。所謂主函數,就是執行這個程序時,由操作系統直接調用的函數。每一個C語言程序必須也只能有一個主函數。(2)函數名后面的圓括號用于表示參數。一般說來,用函數進行計算,需要給定參數。但是廣義的計算也可以沒有參數而只執行一個過程。在C語言程序中,參數部分寫為“void”,表示該函數沒有參數,只執行一個過程?!皏oid”可以省寫,如程序第一行可寫為:

intmain()

在許多教材和程序中,可以常常見到這種形式的主函數首行。但是,C標準建議寫上void,使含義清晰。在本書的程序中都是寫成main(void)形式的。(3)再后面的一對花括號中的部分稱為函數體,用來表明該函數的功能是如何實現的。通常,函數體用一些語句表述。C語言規定語句必須用分號結束。先分析下面的語句:

printf(″Programmingisfun.″);

它的功能是調用編譯系統提供的函數庫中的一個函數printf(),來輸出后面的一串字符。函數printf的使用比較復雜,后面將陸續介紹。(4)函數名前面的“int”表明函數的返回值是一個整數。有的操作系統(如Unix)要求在執行一個程序后應向系統返回一個整數值,如程序正常執行和結束,應返回0,否則返回一個非0值。因此,需要將main函數指定為int(整型),同時在函數體的最后寫一返回語句:

return0;

它的功能是向調用者(操作系統)返回0值,表示主函數正常結束(也就是程序正常結束)。此語句必須寫在函數體的最后一行才有意義,因為只要執行到這條語句,就表達程序正常結束,向操作系統返回一個0,如果程序未執行到這個返回語句就非正常結束了,就不會向操作系統返回0。操作系統會據此作出相應的處理。有的操作系統(如DOS,Windows)并無程序必須返回整數的要求,因此,可以不指定main函數為整型。這時可在main函數的前面加上void,如∶

voidmain(void)或voidmain()

表示main函數是無類型的,不返回任何類型的值。顯然在main函數的最后也不必寫返回語句“return0;”。讀者可以在其他教材或程序中看到這種形式的main函數。以上兩種用法都是是合法的、有效的,編程者可以根據情況決定。為了使程序具有一般性,采用以下形式∶

intmain(void)

并在函數體最后有“return0;”語句。(5)程序最前面的

#include<stdio.h>是一種在程序編譯之前要處理的內容,稱為編譯預處理命令。編譯預處理命令還有一些,它們都用“#”開頭,并且不用分號結束,所以不是C語言的語句。這里的編譯預處理命令稱為文件包含命令,它的作用是在編譯之前把程序中需要使用關于系統定義的函數printf()的一些信息文件stdio.h包含進來。用“.h”作為后綴的文件稱為頭文件。(6)“/*…*/”中的文字用于做一些說明——注釋,讓讀程序的人容易讀懂。例如,注釋

/*文件名:ex1_01.c*/是告訴讀程序的人,這個程序的源代碼用文件ex1_01保存。而其他兩個注釋是對其左面兩條語句功能的說明。上面的程序只由一個函數組成(在主函數中又調用了庫函數printf()。在例1.2中將介紹由兩個函數組成的程序。例1.2計算兩個整數(2,3)相加的結果/*文件名:ex010201.c*/#include<stdio.h>intadd(int,int); /*聲明后面將要使用函數add()*/intmain(void){ints; /*聲明后面使用的變量s是整型的*/s=add(2,3); /*調用add()進行計算,并用s接收*/

printf("Thesumis:%d",s); /*輸出s的值 */return0;}intadd(int

a,intb) /*函數add()的定義 */{intsum; /*定義一個整數sum,用于存放和*/sum=a+b; /*將a和b求和,并把結果送sum*/returnsum; /*返回sum的值到調用者*/}說明(1)圖1.9表明了該程序的執行過程。為了清晰,僅列出了執行語句。將2和3傳遞給a和bex1_02.exemain(){s=add(2,3);printf(“Thesumis%d”,s);return0;}操作系統add(inta,intb){

sum=a+b;

returnsum;}編譯系統提供庫函數printf

進行計算并輸出結果①操作系統調用main()②計算a+b返回sum的值到調用處③返回操作系統④圖1.9程序ex1_02的執行過程

①經過編譯、鏈接后的C語言程序就成為一個可執行文件。例如,程序的ex1_02的默認可執行文件名為“ex1_02.exe”。若要執行這個程序,只要在操作系統的命令執行環境中打入這個文件名,系統就會開始執行這個程序。對于C語言程序而言,首先從調用主函數開始。②在主函數main中,第一個語句是

s=add(2,3);但是,這個語句的執行要分如下步驟才能完成。

調用函數add(),同時將數據2和3分別傳送給函數add()中的變量a和b;

使用表達式a+b進行加法計算。

將和用“=”賦給函數add()中的變量sum中。注意“=”是賦值操作符,不是等號。C語言中的等號是“==”。

用return語句將sum的值返回的函數add()的調用處。

將函數add()的返回值送給主函數中的變量s。③執行函數printf(),輸出下面的內容:

Thesumis5這個語句的執行也需要如下多個步驟才能實現:

圓括號中的引號中的“Thesumis:”要求原樣輸出。

圓括號中的引號中的“%”表示后面的字符“d”是一個格式字符,要求將雙引號后面的表達式的值,按照整型數據輸出。

函數printf()將流程返回到調用處。printf()也有返回值(成功返回輸出的字符個數;失敗時,返回一個負整數),但是一般不用。④執行main()中的返回語句return,用“0”向操作系統送回“平安”信號。(2)變量及其類型本例中的s和sum都稱為變量。變量是程序中被命名的數據實體,并且它的值是可以改變的。同時,為了便于計算與存儲,C語言中程序中所使用的每個數據都被規范化了。這種數據的規范稱為數據類型。本例中使用語句

ints;和

intsum;的作用就是聲明了兩個變量s和sum名字和類型(用“int”表明它們是整型數據)。變量在使用之前都要先行聲明。(3)函數的聲明本例中的

int

add(int,int);稱為函數聲明。函數聲明的作用是讓編譯器知道該函數的原型(包括返回類型、參數個數和類型,以便對調用語句進行語法檢查。如果定義在調用前,從定義可以直接獲得這些信息,就可以不寫聲明;如果調用在定義之前,則需要一個原型聲明說明這些信息。對于編譯系統提供的庫函數,它們的定義不在程序中,因此需要給出相應的原型聲明。為了方便使用,系統把某些類型的庫函數的原型聲明寫在某個頭文件中,程序員只要把要求的頭文件用文件包含語句寫在程序中函數調用之前,就等于把原型聲明寫在了函數調用之前。這就是使用函數printf(),必須在其前寫一條#include<stdio.h>的原因。(4)關于printf()函數的參數

printf()函數的參數有兩部分:前面的用雙引號引起的部分稱為“控制串”??刂拼梢恍┳址M成,這些字符可以分成兩類:第一類字符可以直接顯示出來,第二類字符作為格式說明符使用。或者說,除了格式說明符之外的字符,都是可以直接顯示的。格式說明符是由“%”開頭,后面跟著的是格式碼。本例中的“d”就是格式碼,它后面輸出的數據按照帶符號十進制輸出。其他格式說明符將陸續介紹。(5)關于賦值運算在C語言中,符號“=”稱為賦值運算符,它的作用是把后面(右面)的值,送到其前(左面)的變量(左值)中。一定不要將其當作是等號。在C語言中,等號是“==”。例1.3計算一個數的正弦值的C語言程序。#include<stdio.h>#include<math.h>int

main(void){floatx; /*定義x為實型變量*/x=sin(0.19199); /*調用sin函數*/

printf("%f\n",x);//調用printf函數,輸出x的值}程序的執行結果如下:0.190813說明:

(1)“floatx;”是聲明:x是一個實型變量。(2)“x=sin(0.19199)”可執行一次函數調用,求出0.19199弧度的正弦值,并賦給實型變量x。sin()是一個庫函數,math.h是其要求的頭文件。(3)printf()中的格式說明符“%f”,指定一個實型格式輸出(前面介紹的%d是整型數據格式符)。通常輸出的數據在小數后有6位數字;小數點前的數字位數不指定,根據實際值的位數輸出。格式說明符的類型要與后面要輸出的數據類型相一致。(4)printf()中的“\n”稱為轉義字符序列,前面加了反斜桿后,“n”不再作為字符,而是作為一條換行命令使用。轉義字符還有一些,以后陸續介紹。

從這一小節可以得出如下結論:

C語言程序是由函數組成的。

●設計C語言程序時,一個必須設計的函數是主函數。C語言的執行是從系統調用主函數開始的。

●主函數的部分功能也可以通過其他子函數補充實現。子函數應當首選從函數庫中的函數;函數庫中沒有時??梢钥紤]自行設計。

●使用庫函數時,要用文件包含命令將需要的頭文件包含到程序中調用該庫函數之前。1.3.2C語言的標準由前一小節中的例子可以看出,在C語言程序中,函數下面的組成單位是語句。在C99中,基本的語句有表達式語句、流程控制語句和塊語句。1.表達式語句

C語言程序的具體計算過程是由表達式完成的。表達式是由運算符(如上述+,=等)、變量(如上述s,sum,a,b,x等)和常量(如上述2,3,0.19199等)組成。前面使用過的

s=add(2,3)sum=a+bx=sin(0.19199)都是表達式。表達式加上語句結束符(分號)就構成表達式語句。學習C語言程序設計,必須掌握正確地使用變量、常量和運算符的表示方法和使用規則。變量和常量的使用涉及它們的數據類型、表示(命名)規則等,后面要專門介紹。

C語言中的運算符種類很多,正確地使用這些運算符,有三點需要注意:

它們的含義。特別要區分一個運算符符號在C語言中和在普通數學中的意義的不同。如“=”。

優先級,即在一個表達式中存在多個運算符時,進行運算的先后順序。

結合性,即在一個表達式中有多個優先級別相同的運算符時,先進行哪個運算符的運算。例如,在表達式2*3/5(在C語言中,“*”為乘運算符?!?”為除運算符)中,先進行除呢,還是先進行乘。在這個表達式中,好像對運算結果沒有影響,但有時是有影響的。關于這些問題,后面將專門介紹。2.流程控制語句一般說來,程序中的語句是按照書寫順序執行的。但是,有些情況下,需要改變默認的執行順序,例如像圖1.10(a)那樣要從兩個或多個語句中挑選一個語句執行,或者像圖1.10(b)那樣要重復執行某一個語句或語句塊。前者稱為選擇控制,后者稱為重復控制。

(a)選擇結構(b)重復結構

圖1.10兩種基本的流程控制結構下面給出兩個實例。例1.4由鍵盤輸入兩個數,輸出其中的大數。本例中函數max2()的執行過程如圖1.11所示。圖1.11函數max2()的執行過程程序如下:#include<stdio.h>floatmax2(floatx,floaty){floatmax;

if(x>=y) /*選擇判斷 */max=x; /*條件滿足進行的運算*/elsemax=y; /*條件不符進行的運算*/

printf("Themaxis:%f",max);}int

main(void){floata,b;

printf("Inputtworealnumbers:\n");/*輸入提示*/

scanf("%f%f",&a,&b); /*輸入數據*/max2(a,b); /*調用函數max2()*/return0;}說明:(1)本例的函數max2()中有一個選擇結構,條件是“x>=y”。滿足該條件,則執行運算max=x;不滿足,則執行運算max=y。這樣,就在max中保存了x和y中的大者。(2)在主函數中,函數scanf(“%f%f”,&a,&b)的功能是從鍵盤上輸入兩個實數,分別存放到地址&a和&b中。地址&a和&b是變量a和b地址,“&”是一個運算符。用于計算其后面變量的地址。(3)在函數scanf(“%f%f”,&a,&b)中,“%f”表示要輸入的數據是實型數據。也就是說,格式說明符的類型,要與輸入數據的類型一致。另外,鍵入的兩個數據之間應當以空格、制表符(按Tab鍵)或回車分隔。程序運行時的情形如下:

Inputtworealnumbers:1.2352.345Themaxis:2.345例1.5求累加和的值。程序如下:#include<stdio.h>int

sigma(intn){inti=0,sum=0;

while(i<=n){ sum=sum+i;i++; } returnsum;}int

main(void){int

m,total;

scanf("%d",&m);total=sigma(m);

printf("total=%d\n",total);return0;}說明:(1)聲明

inti=0,sum=0;

有兩個功能:一是定義了兩個整型變量;二是對兩個整型變量設定了初值。這稱為變量的初始化。變量在沒有初始化時并且也沒有執行賦值操作之前,其值是不確定的。為了避免使用這些不確定的值,應當盡量在變量定義的同時對其進行初始化。一般說來,存放和的變量的初始值應當為0,而存放積的變量的初始值應當為1。

(2)在本例中,函數sigma()用來計算。計算的方法是:先設置sum的初值為0、i的初值為0。先執行sum=sum+i。然后用表達式“i++”將自增1,相當于執行操作:i=i+1每執行一次i的自增1,

用流程圖表示如圖1.12所示。i<=nsum=sum+

i是否i=0,sum=0i++returnsum圖1.12

函數sigma()的執行過程

除了上述兩種控制語句外,C語言還提供了其他一些控制語句,以后會專門介紹。3.塊語句塊語句也稱為復合語句,就是用一對花括號將一組語句括起來。在一個塊語句中可以包括若干聲明和若干語句。在例1.8的函數sigma()中,while下面的用花括號括起的兩個語句,就組成一個塊語句。塊語句在語法上相當于一條語句。因此,當語法上需要一個語句,而一個語句又不能滿足需要時,就必須使用塊語句。

1.3.3名字與聲明1.標識符與關鍵字標識符也稱為名稱。變量的名字、函數的名字、文件的名字等,都是關鍵字。在C語言程序中,所使用的標識符應當符合如下的詞法規則:(1)標識符是大小寫字母、數字和下劃線組成的序列,但不能以數字開頭。例如,下面是合法的C標識符:

aAAb_Ax_aX

A_x

abcd

但是下列不是合法的C標識符:

5_A(數字打頭)A-3(含非法字符)(2)C語言區別同一字母的大小寫,如abc與abC被看作識不同的名標識符。(3)C89要求C編譯器能識別的標識符長度為不少于31個有效字符,C99要求C編譯器能識別的標識符長度為不少于63個有效字符。一個標識符中超過了這個長度的字符可能會不被辨認。例如在符合C99的系統中,當兩個標識符的前63個字符都相同時,不管后面的有效字符是否相同,都可能被當作同一個標識符。(4)普通標識符不能使用對于系統有特殊意義的名稱。這些對系統有特殊意義的名稱稱為關鍵字。表1.1為C99關鍵字。auto_Boolbreakcasechar_Complexconstcontinuedefaultdodoubleelseenumexternfloatforgotoif_Imaginaryinlineintlongregisterrestrictreturnshortsignedsizeofstaticstructswitchtypedefunionunsignedvoidvolatilewhile表1.1C99關鍵字在一個程序中,往往要使用大量的名字。大量的名字的使用,可能會造成名字的沖突和使用錯誤。為此,除了上述詞法規則外,人們還總結了在程序中使用“好”名字的一些原則:(1)盡量做到“見名知義”,以增加程序的可讀性。(2)盡量避免使用容易混淆的字符,例如

0(數字)、O(大寫字母)、o(小寫字母)、1(數字)-I(大寫字母)、i(小寫字母)、2(數字)、Z(大寫字母)、z(小寫字母)匈牙利前綴數據訐類型變量名舉例a或ar數組arAgebBULL(布爾值)bDone,bbyBYTE(無符號字符)byCount,byc或chcharc,chd或dbldoubled,dbl,dCost,dblCostdw或w無符號整數wNumberf或flfloatf,fl,fCost,flCostfn函數fnFun1h句柄hWndL或llongL,l,lCountm類的數據成員n或iintn,i,nCount,iCountp指針pInt,pWnds字符串sNamesz“0”結束的字符串sz,szMystringx,y無符號整型或坐標表1.2

部分常用匈牙利前綴

(3)名字不要太短,一般函數名盡量使用動賓結構,如PrintCalendar、IsPrime等。(4)許多國外的Windows程序員還采用匈牙利人CharlesSimonyi提出的將類型作為變量名前綴的命名方法——通常稱為匈牙利命名法。表1.2為部分常用匈牙利前綴。2.聲明在程序中,有許多東西是需要系統為其開辟存儲空間的,例如變量、函數類型定義等。它們都有自己的名字,并且要在內存中獨立存儲,為此可以將它們稱做程序實體。那么,如何建立它們的名字與實體之間的關聯呢?這就是聲明的作用。聲明也稱為說明,它的作用非常重要,包括如下一些:●告訴編譯器,一個名字是與哪個實體聯系,不能張冠李戴●告訴編譯器,也要程序員明白這個實體的類型?!窀嬖V編譯器,這個實體什么時候建立?在什么范圍內可以使用?前面已經使用過了變量和函數的聲明。所以,例1.2中的

ints;就是建立變量名s與它的實體之間的關聯。在一個語句塊中關于聲明的進一步用法,后面還要陸續介紹。目前要牢記的是,在使用一個程序實體之前,一定要讓編譯器知道該程序實體的屬性。在C99之前,對變量和函數的聲明不作為語句(盡管它們也是用分號結尾),它們必須出現在C語句的前面(聲明的位置必須集中寫在語句之前)。C99改變了這一做法,它吸取了C++的做法,聲明不必集中放在執語句之前,可以出現在程序中的任意行。這樣,C語句就有執行語句和非執行語句之分。聲明是非執行語句,表達式語句和流程控制語句是執行語句。

1.3.4變量及其賦值1.變量變量(variable)是一種程序實體。它具有一個值,并且這個值是可以通過程序操作改變的。2.變量的賦值運算在C語言中,符號“=”稱為賦值運算符,它連接了左右兩個操作數(即運算量):右操作數也稱右值,可以是一個表達式,左操作數也稱左值(lvalue),只能是變量。賦值操作的過程是把右操作數的值先轉換成左操作數(變量)的類型,并把該值存放到左操作數(變量)中。例如

inta;

a=2.6;

printf(“%d”,a);結果為2這是因為計算機在執行上述語句時,首先將2.6舍去小數部分截尾(truncation)成整型,賦值給變量a。應當注意,賦值運算符是“=”。這個符號不是等號。例如

inta=2,b=3;

a=a+b;的操作是把表達式a+b的值(2+3)送到(賦值給)變量a。即經上述操作后,變量的a的值由2變為5。圖1.13表明這一操作過程:先計算a+b的值,然后把這個結果送到變量a中。于是,變量a的值由2變為5。

23aba+b235運算器圖1.13a=a+b的操作過程賦值運算符具有“自右至左”的結合性,例如

inta=0,b=0,c=0;

a=b=c=5+3;相當于

inta,b,c;

a=(b=(c=(5+3)));即先計算把5+3

的值,得8,賦值給變量c;再把變量c的值(8)賦值給變量b;最后把變量b的值(8)賦值給變量a。圖1.14表明這一操作過程。執行的結果,a、b、c三個變量中的值均為8。也就是說,從一個變量向另一個變量賦值后,原來變量中的值并不會消失或改變。所以,賦值操作相當于拷貝,而不是移動。a+b53運算器0a0b0ca+b53運算器0a0b8c運算器0a8b8c運算器8a8b8c(c)

執行操作b=c=5+3后變量a、b、c的值

(b)執行操作c=5+3后變量a、b、c的值

(a)操作前變量a、b、c的值(d)執行操作a=b=c=5+3后變量a、b、c的值

圖1.14a=b=c=5+3的操作過程

1.3.5算術運算算術運算是一切計算的基礎,也是大家都認為非常熟悉的。但是對于高級程序設計語言尤其是C語言中的算術運算符,還需要有一個再學習的過程。C語言中的算術運算符與普通數學中的算術運算符有如下一些不同。

運算符符號有所不同。

種類有所不同。

結合性可能會破壞交換率。1.C語言的基本算術運算符

表1.3為C語言中的基本算術運算符及其說明。表1.3C語言中的基本算術運算符及其說明

運算符名稱運算對象功能示例表達式示例值*乘任何兩個實數或整數求兩數之積5.5*4.022.000000/除任何實數或整數,但右操作數不可為0求兩數之商4.5/50.900000%模兩個整數,但右操作數不可為0求整除的余數13%85+加任何兩個實數或整數求兩數之和8+3.511.500000-減任何兩個實數或整數求兩數之差10-4.65.400000說明:(1)這幾個算術運算符的運算對象有兩個,所以也稱為雙目算術運算符。(2)這幾個算術運算符的優先級別為:*、/、%高于+、-。并且它們都比賦值運算符的優先級別高。所以,在一個表達式中有賦值運算符,也有算術運算符時,不使用圓括號,可以先進行算術運算,后進行賦值運算(3)這幾個算術運算符均為“自左至右”。(4)需要特別注意的是整數除和模運算的結果都是整數。

例1.6分析下面的程序的執行結果。/*文件名:ex010601.c*/#include<stdio.h>intmain(void){printf("300*2/3=%d\n",300*2/3);

printf("2/3*300=%d\n",2/3*300);return0;}觀察上面的程序,按照交換率,似乎它們的計算結果應該相同。但是,非常遺憾!結果完全不同:

300*2/3=200

2/3*300=0原因在于算術運算符具有自左至右的結合性,即對于第1個表達式語句,執行的順序為:

300*2=600,600/3=200對于第2個表達式語句,執行的順序則為:

2/3=0(注意是整數相除),0*300=0因此,使用整數除,應當特別小心。2.自反算術賦值運算符前面介紹過這樣的賦值表達式:

a=a+b它的作用是將變量a的值加上變量b的值,再送回到變量a中?;蛘哒f是將變量a的值增加一個變量b的值。這樣類似的運算很多。為此C語言為這種運算提供了一種簡潔形式:

a+=b這樣,就可以用一個復合運算符代替原來的兩個運算符。這種復合運算符稱為自反算術賦值運算符。除自反加以外,還有下列一些:

-=(自反減賦值)*=(自反乘賦值)/=(自反除賦值)%=(自反模賦值)自反算術賦值的結合方向與賦值運算符一樣,為自右向左。另外,它的優先級別相當低,與賦值是同一級別。例如表達式語句:

c=b*=a+2;相當于如下兩個表達式語句:

b=b*(a+2);

c=b;3.自加和自減運算自反算術賦值運算中有兩種更特殊的情況,即:

i=i+1即i+=1和

i=i–1即i-=1這是兩種極為常用的操作。把i稱為計數器,用來記錄完成某一工作的次數。C語言為它們專門提供了兩個更簡潔的運算符:

i++或++i和

i--或--i前一種(i++和i--)稱為后綴形式;后一種(++i和--i)稱為前綴形式,都稱為自加或自減運算符。例如:

inti=5;inti=5;

i++;

++i;

y=i;y=i;兩段程序執行的結果i值都為6,y的值也都為6。但是把它們引用在表達式中就表現出區別了。例如:

inti=5;

x=i++; /*相當于x=i;i=i+1;*/

y=i;的執行結果為:x為5,y為6。即后綴方式是“先引用后增值”。而

inti=5;

x=++i; /*相當于x=i=i+1;*/

y=i;

的執行結果為:x為6,y為6。即前綴方式是“先增值后引用”。自加和自減運算符的結合方向是“自右至左”,它的運算對象只能是整型變量而不能是表達式或常數。例如:5++或(x+y)++是錯誤的。4.正負號運算符正負號運算符為+(正號)和-(負號),它們是一元運算符。例如,-5和+65。它們的優先級別高于*、/運算符。例如:

-a*b先使a變符號再乘以b。其實正負號運算相當于一次算術賦值運算,例如:

-a 相當于a=0–a-a*b 相當于(0-a)*b它的結合方向為自右至左。綜上所述,凡賦值運算符及其變種(包括自反算術賦值運算符、自加自減運算符和正負號運算符)的結合方向都是自右至左的。1.3.6賦值類運算符的副作用及限制

在程序設計中,效率與易讀性是一對主要矛盾。人們為了提高程序的效率,往往要使用技巧把程序寫得盡可能簡潔一些。但這樣就降低了程序的可讀性和可理解性??勺x性差的后果是易于隱藏錯誤,難于糾正錯誤,不易維護,降低了程序的可靠性。鑒于“軟件危機”的教訓,現代人們進行程序設計時要遵守的基本規范是:可靠性第一,效率第二。為保證可靠性第一,就要清晰易讀第一。這就要求進行程序設計時,把程序寫得清晰易懂一些。初學者從一開始就應當培養這個良好的程序設計風格。

C語言允許在一個表達式中使用一個以上的賦值類運算符(包括賦值符,自反算術賦值符,自加、自減運算符等)。這種靈活性在給程序帶來簡潔性的同時也會引起副作用。這種副作用表現在兩個方面.1.費解、易于誤解——對人的副作用下面是容易引起誤解的兩個例子。①c=b*=a+2;容易誤解為b*=a;c=b+2;②x=i+++j;應該理解為x=(i++)+j呢?還是x=i+(++j)呢?實際上C編譯器總是從左至右盡量多地將若干個字符組成一個運算符(對標識符也如此),因此i+++j被處理成(i++)+j而不是i+(++j)。

克服這類副作用的方法是:盡量把程序寫得易懂一些。為了使表達式清晰易懂,可以采用這樣一些措施:

(1)將費解處分解。例如將上面第①個表達式語句分寫為

a=a+2;

b=b*a;

c=b;或c=a+2;

c=b*c;對第②個表達式語句,可分寫為:

x=i+j;

i++;(2)加一些“冗余”括號為了避免出現差錯,在易于誤解的地方加一些“冗余”括號。例如,c=b*=a+2可以改寫為

c=b*=(a+2);或c=(b*=(a+2));便清晰些了。所謂“冗余”括號是指如果不加這些括號的話計算機也不會錯,但為了讓人不致誤解而多加的括號。

(3)加注釋說明。注釋是提高程序清晰性的有力工具。對C語言來說,注釋不會影響程序的效率。所以,一方面想保證程序的效率,一方面又怕別人誤解(當然自己不能誤解)的情況下,可以加注釋說明。如對c=b*=a+2可以寫為:

c=b*=a+2;

/*a=a+2;c=b*c*/2.不定解——對機器的副作用先看一個例子:

j=3;

i=(k=j+1)+(j=5);執行這段程序時,不同機器上得到i的值可能是不同的。有的機器先執行(k=j+1)然后再執行(j=5),i值得9。而有的機器是先執行(j=5)后執行(k=j+1),i的值就成了11。在數學中,a+b和b+a是一樣的,因為符合交換律,所以(a+b)+(c+d)也可以寫成(c+d)+(a+b)。換言之,(a+b)+(c+d)的求值順序不影響結果(可以先求a+b,也可以先求c+d)。但在C表達式中含有一個以上的賦值類運算符時,交換律不再適用。由于C語言對表達式的求值順序(方向)無統一規定,而是由各個C編譯系統自己決定,這就造成了同一程序在不同計算機系統運行時會得到不同的結果。為了提高程序的可移植性,應當使表達式分解,使之在任何機器上運行都能得到同一結果。因此上面語句可改為:

j=3;

k=j+1;

j=5;

i=k+j;第2章基本數據類型

2.1基本數據類型的特征2.2數據常量2.3數據類型轉換2.4數據的控制臺輸入與輸出C語言數據類型基本數據類型導出數據類型double(雙精度浮點型)long(長整型)

char(字符類型)整型short(短整型)int(整型)浮點型float(單精度浮點型)longdouble(長雙精度浮點型)

void類型用戶定制類型T*(指針類型)struct{…}(結構體類型)union{…}(共用體類型)文件類型enum(枚舉)函數類型構造類型T[…](數組類型)C語言提供有豐富的數據類型:2.1基本數據類型的特征

C語言提供的基本數據類型包括char(字符)型、int(整)型、float(單精度實)型、double(雙精度實)型。并且還可以通過使用short、long、signed和unsigned修飾char和int,用long修飾double,形成更多的類型。2.1.1數值的定點表示與浮點表示

定點表示和浮點表示,是C語言基本數據類型的重要特征。為了說明什么是“定點”,什么是“浮點”,先看π值的幾種表示形式:日常的表示法C語言中的表示形式 3.14159×100 3.14159e0 0.314159×101

0.314159e+1 0.0314159×102

0.0314159e+2 31.4159×10-1

31.4159e-1 3141.59×10-3

3141.59e-3實型常量實型常量有十進制的定點和浮點兩種表示方法,但并不存在其他進制的表示。

(1)定點表示的實數簡稱定點數,實際上是以小數形式表示實數。定點表示的實數是由一個正號或負號(正號可以省略)后接若干個十進制數字和一個小數點所組成,這個小數點可以處在任何一個數字位的前面或后面。例如,數字長度為4,小數點位于中間,那么可以表示10.28,也可以表示0.01,與這種方法性質類似的定點表示還有使用分數的形式。定點數的固定窗口形式使得他既不能夠表示非常大的數又并且當除法發生時,大量

的精度丟失.(2)浮點表示的實數簡稱浮點數,實際上是以指數形式表示實數。浮點表示的實數是由一個十進制整數或定點數后接一個字母E(大、小寫均可)和一個1至3位的十進制整數所組成,字母E之前的部分稱為該浮點數的尾數,之后的部分成為該浮點數的指數或階,該浮點數的值就是它的尾數乘以10的指數冪。對于一個浮點數,若將它尾數中的小數點調整到最左邊第一個非零數字的后面,如1.234e1,則稱它為規格化(或標準化)浮點數。浮點數可以表示較大精度范圍的一個實數。定點數:小數點固定。浮點數:小數點不固定(位置不固定)隨階碼浮動。1、定點表示法小數點固定在數值部分的最高位之前或最低位之后。例如:

1.101011或1101011.2、浮點表示法3.14159+1數值部分(尾數)指數(階碼)N=S*2PS——二進制小數,稱 “尾數”,S≥0P——稱為數N的階碼,為非負正數2——階碼“底”浮點形式存儲2.1.2整數的有符號類型與無符號類型

內存中的數值是以補碼形式存放的,一個正數的補碼就是該數的二進制數(如10的補碼為0000000000001010)。求一個負數的補碼的方法如下:

如-10的補碼可以這樣求: ①先取該數的絕對值; 即先取10

②然后以二進制形式表示; 10的二進制碼為 0000000000001010

③再對其取反; 取反得1111111111110101

④然后加1; 加1,得1111111111110110,即-10的16位存儲形式為:1111111111110110。2.1.3類型寬度與取值范圍

C語言對不同類型的數據分配不同寬度的存儲空間,典型的存儲空間寬度有:1個字節(8位)、2個字節(16位)、4個字節(32位)、8個字節(64位)和10個字節(80位)幾種。顯然,不同的長度,對應的數據的取值范圍是不同的。當然,同樣長度的取值范圍還與有無符號、是定點表示(整型)還是浮點表示(實型)有關。另外還取決于所用的編譯系統。大多數編譯系統對一個帶符號整數的數值范圍處理為:-2n-1~2n-1-1。其中n為該整數所占的比特數。如果一個整數所占的比特數為16,則該想整數的范圍為-32768~32767。也有一些編譯系統對一個帶符號整數的數值范圍處理為:-2n-1-1~2n-1-1。如果一個整數所占的比特數為16,則該想整數的范圍為-32767~32767。不同長度整型數據的取值范圍數據長度(比特)取值范圍Signed(有符號)Unsigned(無符號)8-128~1270~25516-32768~327670~6553532-2147483648~21474836470~429496729564-(263)

~263-10~264-1(18446744073709551615)由于內存和效率的原因,數據的表示總是有限的。比如2/3=0.66666666...計算機不可能用無限位的比特來表示這個數。那么它就只能用有限的數位來表示浮點數。設用十進制表示。

0.XXXXXXX*10^(n)

這里0.XXXXXXX是一個小于1.0大于等于0.1的小數,而n是一個整數。如上所說,浮點數分兩個部分:有效數位部分和指數部分。一般來說分配給這兩個部分的表示數位都是固定的。比如有8位(10進制),把其中7位用來表示有效數位,另外一位表示指數部分。那么上面2/3的例子就是

66666670

其意思是0.666667*10^0。

在實際的計算機中,假設有32位(2進制),拿23位當有效數位,8位當指數部分,1位當符號位。在有效數位部分,因為有23個有效數位,設十進制的有效數字位為X,則有223=10x,即相當于十進制的x=23*log10(2)=6.92369位。即約是7位十進制有效數字。而指數部分有8*log10(2)=2.4082位C語言中不同長度實型數據的取值范圍和數字精度寬度(比特)數據類型機內表示(位數)取值范圍有效數字和精度階碼尾數符號32float8231|3.4e-38|~3.4e+38|大約7位十進制有效數字,(

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論