




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
目 錄第1章開發(fā)環(huán)境搭建及調(diào)試窗口設(shè)置 1開發(fā)環(huán)境搭建 1C語言的那些事 1開發(fā)環(huán)境安裝 3新建項(xiàng)目 7新建代碼及編譯運(yùn)行 9程序的編譯過程 13斷點(diǎn)及調(diào)試窗口設(shè)置 14學(xué)習(xí)C語言后的境界 16練習(xí)題 17第2章數(shù)據(jù)類型、運(yùn)算符與表達(dá)式 182.1 數(shù)據(jù)類型 182.2 常量 192.3 變量 19整型數(shù)據(jù) 19符號(hào)常量 19整型常量的不同進(jìn)制表示 22補(bǔ)碼的作用 25整型變量 27浮點(diǎn)型數(shù)據(jù) 28浮點(diǎn)型常量 28浮點(diǎn)型變量 28字符型數(shù)據(jù) 30字符型常量 30字符數(shù)據(jù)在內(nèi)存中的存儲(chǔ)形式及其使用方法 31字符串型常量 32混合運(yùn)算 32數(shù)值按int型運(yùn)算 32浮點(diǎn)型常量默認(rèn)按double型運(yùn)算 34類型強(qiáng)制轉(zhuǎn)換場(chǎng)景 35常用的數(shù)據(jù)輸入/輸出函數(shù) 36scanf函數(shù)的原理 36scanf函數(shù)的循環(huán)讀取 38VI 多種數(shù)據(jù)類型混合輸入 39getchar函數(shù)介紹 40putchar函數(shù)介紹 41printf函數(shù)介紹 42運(yùn)算符與表達(dá)式 43運(yùn)算符分類 43算術(shù)運(yùn)算符及算術(shù)表達(dá)式 44關(guān)系運(yùn)算符與關(guān)系表達(dá)式 45邏輯運(yùn)算符與邏輯表達(dá)式 47位運(yùn)算符 48賦值運(yùn)算符 49條件運(yùn)算符與逗號(hào)運(yùn)算符 51自增、自減運(yùn)算符及求字節(jié)運(yùn)算符 51練習(xí)題 52答案解析 52第3章選擇與循環(huán) 60選擇結(jié)構(gòu)程序設(shè)計(jì) 60關(guān)系表達(dá)式與邏輯表達(dá)式 60if語句 60switch語句 62循環(huán)結(jié)構(gòu)程序設(shè)計(jì) 64goto語句 64while循環(huán) 65dowhile循環(huán) 66for循環(huán) 67continue語句 68break語句 69練習(xí)題 69答案解析 70第4章數(shù)組 83一維數(shù)組 83數(shù)組的定義 83一維數(shù)組在內(nèi)存中的存儲(chǔ) 84??臻g和數(shù)組 87二維數(shù)組 88二維數(shù)組的定義與引用 88二維數(shù)組的初始化及傳遞 89目錄PAGE\*ROMANIX目錄PAGE\*ROMANIXPAGE\*ROMANXPAGE\*ROMANX字符數(shù)組 91字符數(shù)組的定義及初始化 91gets函數(shù)與puts函數(shù) 93str系列字符串操作函數(shù) 93strn系列字符串操作函數(shù) 95mem系列操作函數(shù) 96練習(xí)題 97答案解析 98第5章指針 106指針的本質(zhì) 106指針的定義 106取地址操作符與取值操作符 107指針的使用場(chǎng)景 108指針的傳遞 108指針的偏移 指針與自增、自減運(yùn)算符 指針與一維數(shù)組 指針與動(dòng)態(tài)內(nèi)存申請(qǐng) 字符指針與字符數(shù)組的初始化 深入理解const memcpy函數(shù)與memmove函數(shù)的差異 數(shù)組指針與二維數(shù)組 120數(shù)組指針的應(yīng)用 120二維數(shù)組的偏移計(jì)算 122二級(jí)指針 122二級(jí)指針的傳遞 122二級(jí)指針的偏移 123函數(shù)指針 125練習(xí)題 126答案解析 126第6章函數(shù) 133函數(shù)的聲明、定義與調(diào)用 133函數(shù)的聲明與定義 133函數(shù)的分類與調(diào)用 135嵌套調(diào)用 137遞歸調(diào)用 138變量及函數(shù)的作用域 140局部變量與全局變量 140動(dòng)態(tài)存儲(chǔ)方式與靜態(tài)存儲(chǔ)方式 142函數(shù)調(diào)用原理詳解 1446.5.1 關(guān)于棧 1446.5.2 代碼實(shí)例分析 145練習(xí)題 146答案解析 147第7章結(jié)構(gòu)體 149結(jié)構(gòu)體與結(jié)構(gòu)體指針 149結(jié)構(gòu)體的定義、引用、初始化 149結(jié)構(gòu)體指針 151typedef的使用 152鏈表的增刪查改 1527.2.1 鏈表 1527.2.2 增刪查改鏈表 153共用體與枚舉 1587.3.1 共用體 1587.3.2 枚舉 159練習(xí)題 159答案解析 160第8章常用數(shù)據(jù)結(jié)構(gòu)與算法 1828.1 數(shù)據(jù)結(jié)構(gòu) 1828.1.1 棧 1828.1.2 隊(duì)列 1848.1.3 二叉樹 1878.1.4 紅黑樹 1928.1.5 數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)技巧 2098.2 算法 209時(shí)間復(fù)雜度與空間復(fù)雜度 209排序算法 210二分查找算法 235哈希查找算法 236其他算法 239練習(xí)題 239答案解析 239第9章文件操作 243C文件概述 243文件的打開、讀寫、關(guān)閉 244文件指針介紹 244文件的打開與關(guān)閉 244fread函數(shù)與fwrite函數(shù) 247fgets函數(shù)與fputs函數(shù) 249ftell函數(shù) 251fprintf函數(shù)與fscanf函數(shù) 252練習(xí)題 253答案解析 253第10章C語言預(yù)處理和C語言庫(kù) 260預(yù)處理簡(jiǎn)介 260預(yù)處理的工作原理 260預(yù)處理指令 26210.4宏定義 263簡(jiǎn)單的宏 263帶參數(shù)的宏 26510.4.3 操作符# 26710.4.4 操作符## 267宏的通用屬性 268較長(zhǎng)的宏中的逗號(hào)操作符 269宏定義中的dowhile循環(huán) 270預(yù)定義宏 270空宏參數(shù) 271const與#define的差異 272條件編譯 273#if指令和#endif指令 273defined操作符 273#ifdef指令和#ifndef指令 274#elif指令和#else指令 275條件編譯 276其他指令 277指令#line 277指令#undef 278變參宏...和VA_ARGS 27810.7內(nèi)聯(lián)函數(shù)(C99) 27910.8C庫(kù)中的可變參數(shù)stdarg.h 280練習(xí)題 282答案解析 283第章學(xué)生信息管理系統(tǒng) 285系統(tǒng)功能描述 285系統(tǒng)模塊設(shè)計(jì) 286系統(tǒng)用到的相關(guān)函數(shù) 288第12章編譯器詞法、語法分析項(xiàng)目 290詞法分析項(xiàng)目 290項(xiàng)目需求描述 290詞法分析模塊設(shè)計(jì) 290建立字典模塊 290字符串存儲(chǔ)及其TOKEN值的快速識(shí)別設(shè)計(jì) 293詞法及語法分析簡(jiǎn)單樣例研究 296算術(shù)表達(dá)式的合法性判斷 296詞法分析 296算術(shù)表達(dá)式的語法分析 299升級(jí)版功能:編譯器語法分析 303整體流程分析 304函數(shù)體內(nèi)流程分析 305表達(dá)式解析流程分析 30612.4.4 總結(jié) 307附錄AASCII碼表 308附錄B C語言運(yùn)算符優(yōu)先級(jí) 參考文獻(xiàn) 313第1章 開發(fā)環(huán)境搭建及調(diào)試窗口設(shè)置CCC語言運(yùn)行在哪些主流的操作系Windows下使用的主要開發(fā)環(huán)境是uldSSC學(xué)習(xí)目標(biāo):開發(fā)環(huán)境的搭建與使用新建項(xiàng)目及編譯運(yùn)行基本的調(diào)試方法C語言需要達(dá)到的目標(biāo)和境界開發(fā)環(huán)境搭建C語言的那些事在搭建開發(fā)環(huán)境之前,這里先講一個(gè)故事。CC語言呢?其實(shí)是因?yàn)橄扔懈呒?jí)語言ALGOLA語言BCPL(B語言CBCC語言編BStudiomasm編譯器和Linuxgcc編譯器(Mac計(jì)算機(jī)也使用這個(gè)編譯器C的版本及標(biāo)準(zhǔn)意義不大,關(guān)鍵是要掌握編譯器支持的語言特性。8CWindowsLinuxMacOS上,都可以編譯通過。UNIX1965年前,計(jì)算機(jī)并不像今天這樣普遍,它不是普通人能用得起的,除非是軍事機(jī)構(gòu)或?qū)W30(301.1.1所示。為了解決終端數(shù)量不夠用的問題,1965年前后,貝爾實(shí)驗(yàn)室加入麻省理工學(xué)院和通用電氣300個(gè)終端。1969年前后,該項(xiàng)目進(jìn)展緩慢,資金短缺,貝爾實(shí)驗(yàn)室于是退出了研究。1969年8月,從這個(gè)項(xiàng)目中退出的KenThompson為了能在實(shí)驗(yàn)室中一臺(tái)空閑的計(jì)算機(jī)上運(yùn)行“星際旅行”(SpaceTravel)游戲,在妻子探親的1個(gè)月時(shí)間內(nèi),使用匯編語言編寫了UNIX操作系統(tǒng)的原型。第1第1章 開發(fā)環(huán)境搭建及調(diào)試窗口設(shè)置PAGE17PAGE16PAGE16圖1.1.1大型主機(jī)的連接方式1970年,KenThompson以BCPL語言為基礎(chǔ),設(shè)計(jì)出了很簡(jiǎn)單且很接近硬件的B語言(取LBNX1971DennisM.Ritchie為了能早一些玩上這款游戲,加入了KenThompsonUNIXB語言的跨平臺(tái)性較差。1972MRitchieBBCPL的第C語言。1973年初,C語言的主體完成,KenThompson和DennisMRitchie(1.1.2)迫不及待UNIX操作系統(tǒng)。圖1.1.2KenThompson(左)和DennisM.Ritchie(右)2.C語言在把UNIXx86AlphaARM等機(jī)CC語言編譯器和庫(kù),將C源代碼編譯、鏈接成目標(biāo)二進(jìn)制文件后即可運(yùn)行。aaCCCLinuxCCJavaCC開發(fā)環(huán)境安裝8rftuldo2(S1VSVS2013VS2017。讀者既可以到網(wǎng)上下載安裝包,又可以加入前QQ群(其中提供了安裝包的分享鏈接VS2012C語言呢?Linuxgcc,VS2012的圖形化調(diào)試界面清晰直觀,對(duì)于初學(xué)者非常友好。那么VSC語言時(shí)暫不相關(guān)的其他功能,而我們學(xué)習(xí)CLinux下進(jìn)行系統(tǒng)開發(fā),所以不使用最新版本完全沒有影響。操作系統(tǒng)為Windows10VS2017QQ群中的視頻。下面介紹安裝VS2012的步驟。Windows7ISODAEMONLite(DAEMONLiteQQDAEMONLite1.1.3所示的界面,選擇相關(guān)選項(xiàng)后,單擊“下一步”按鈕。圖1.1.3DAEMONToolsLite安裝向?qū)Ы缑?.1.4Microsoft.Visual.Studio.2012.Ultimate.CHS映像。1.1.5所示,在出現(xiàn)的界面中單擊三角形按鈕載入映像。載入映像后,雙擊箭頭指iso1.1.6vs_ultimate即可開始安裝。對(duì)于無法安裝DAEMONToolsLite虛擬光驅(qū)的讀者,可以試一下其他虛擬光驅(qū);另外,Windows10操作系統(tǒng)可以直接解壓縮iso安裝包進(jìn)行安裝,而不用安裝DAEMONToolsLite虛擬光驅(qū)。圖1.1.4單擊左下方帶方框的加號(hào)按鈕添加Microsoft.Visual.Studio.2012.Ultimate.CHS映像圖1.1.5載入映像并打開iso安裝包的界面圖1.1.6雙擊vs_ultimate開始安裝界面1.1.7C1.1.8.1020121.1.12圖1.1.7同意許可條款和條件及安裝位置界面 圖1.1.8選擇安裝選項(xiàng)界面 圖1.1.9安裝已完成界面 圖1.1.10輸入產(chǎn)品密鑰界面圖1.1.11成功應(yīng)用產(chǎn)品密鑰界面 圖1.1.12“選擇默認(rèn)環(huán)境設(shè)置”界面安裝VS2017時(shí),安裝過程中會(huì)出現(xiàn)如圖1.1.13所示的提示界面,選擇“使用C++的桌面開發(fā)”選項(xiàng)和“通用Windows平臺(tái)開發(fā)”選項(xiàng)。圖1.1.13安裝VS2017時(shí)的提示界面JavaPython等語言的集成開發(fā)環(huán)境,安裝到固態(tài)硬盤上都有助于提升啟動(dòng)速度。新建項(xiàng)目開發(fā)環(huán)境安裝完畢后,我們來看一下如何新建項(xiàng)目,并測(cè)試開發(fā)環(huán)境是否正常。首先在如圖1.2.1所示的界面中選擇菜單項(xiàng)“文件”→“新建”→“項(xiàng)目”,彈出如圖1.2.2所示的對(duì)話框,圖1.2.1新建項(xiàng)目ul+2(D盤上創(chuàng)建了BOOK,后面本書所有章節(jié)的代碼均放在該文件夾中。讀者也可以創(chuàng)建一個(gè)文件夾,Her圖1.2.2選擇控制臺(tái)應(yīng)用程序1.2.31.2.4所示C標(biāo)準(zhǔn)的安1.2.5所示的界面,單擊“完成”按鈕。圖1.2.3接受當(dāng)前設(shè)置界面圖1.2.4選擇附加選項(xiàng)界面圖1.2.5選擇附加選項(xiàng)后出現(xiàn)的界面新建代碼及編譯運(yùn)行新建項(xiàng)目完成后,會(huì)出現(xiàn)如圖1.3.1所示的界面,右鍵單擊“源文件”文件夾,在出現(xiàn)的菜1323((psm編譯器是C與.命名,masmC1.3.4所示的界面。圖1.3.1新建項(xiàng)目完成后的界面圖1.3.2選擇“添加”→“新建項(xiàng)”界面在main.c中添加代碼,得到如圖1.3.5所示的界面;然后,單擊圖中箭頭所指的三角形按鈕(136oo1.3.3C++文件(”并命名的界面圖1.3.4單擊“添加”按鈕后出現(xiàn)的界面圖1.3.5添加代碼后的界面圖1.3.6程序執(zhí)行后出現(xiàn)的字符串說明:mainintCmain,程mainC語句均以半角分號(hào)結(jié)束。使用標(biāo)準(zhǔn)庫(kù)函數(shù)時(shí)應(yīng)在程序開頭一行書寫如下內(nèi)容:#include<stdio.h>//printf函數(shù)需要使用該頭文件#include<stdio.h>//printf函數(shù)需要使用該頭文件#include<stdlib.h>//system函數(shù)需要使用該頭文件其中,兩個(gè)斜杠“//”后面的內(nèi)容為代碼注釋,程序編譯時(shí)不會(huì)編譯到程序中。printfHelloworldpause實(shí)際上是Windows的一個(gè)批處理命令。按組合鍵Win+R7138pausecmd(又稱控制臺(tái)窗口system函數(shù)是C語言調(diào)用其他語言的一個(gè)接口,system("pause")使我們通過C語言調(diào)用執(zhí)行了Windowspause。圖1.3.7“運(yùn)行”窗口 圖1.3.8pause命令的作用顯示窗口程序的編譯過程1.4.1f.c。編寫完畢后,通過編譯器進(jìn)行編譯,Linux系統(tǒng)編程中講解。讀者如果有興趣,可以參閱關(guān)于編譯原理的書籍。f.cf.obj文0/1CPU能夠識(shí)別的微指令(英特爾的機(jī)器指令。f.obj文件并不能執(zhí)行,因?yàn)槲覀冋{(diào)用的標(biāo)準(zhǔn)庫(kù)函數(shù)的代碼并不在f.obj文件中。例如,上面main.cprintfmain.obj中,這時(shí)經(jīng)過鏈接就得到可執(zhí)行文件f.exe1.4.21.Hello_World3在界面中我們可以看到一個(gè)解決方案,它其實(shí)是一個(gè)大文件會(huì)在我們的解決方案文件夾“開發(fā)環(huán)境搭建及調(diào)試窗口設(shè)置”下新建文件夾main.cmain.cDebugmain.objDebug1.Hello_World.exe文件。
圖1.4.1程序的編譯過程圖1.4.2選擇“在文件資源管理器中打開文件夾”界面圖1.4.3選擇“在文件資源管理器中打開文件夾”后的界面斷點(diǎn)及調(diào)試窗口設(shè)置1.5.1152圖1.5.1選擇菜單欄中的“工具”選項(xiàng)1.5.36indows調(diào)試器即為“執(zhí)行”按鈕,運(yùn)行后的顯示1.5.31序會(huì)向下執(zhí)行一步;按鈕2是“繼續(xù)執(zhí)行”按鈕,單擊后程序會(huì)執(zhí)行到最后,或執(zhí)行到下一個(gè)3(左鍵單擊斷點(diǎn)可以取消斷點(diǎn)。圖1.5.2“選項(xiàng)”對(duì)話框圖1.5.3按鈕說明窗口1.5.41551.5.4圖1.5.5顯示效果窗口1.5.5學(xué)習(xí)C語言后的境界CC語言后,達(dá)到的效果是理解程序的執(zhí)行過程。對(duì)于理解程序的執(zhí)行過程,C語言是當(dāng)之無愧的最佳選擇,C語言,以后在學(xué)習(xí)其他任何語言并調(diào)試程序的問題時(shí)就會(huì)事半功倍!練習(xí)題打上斷點(diǎn)?如何取消斷點(diǎn)?答案啟動(dòng)程序時(shí)單擊小三角按鈕或按快鍵逐步執(zhí)行程序時(shí)按F10鍵或單擊按鈕終止程序時(shí)單擊按鈕或按組合鍵Shift+F5;單擊代碼行左側(cè)的灰色區(qū)域可打上斷點(diǎn),再次鼠標(biāo)左鍵單擊斷點(diǎn)可取消斷點(diǎn)。第2章 數(shù)據(jù)類型、運(yùn)算符與表達(dá)式(視頻講解:6小時(shí))學(xué)習(xí)目標(biāo):數(shù)據(jù)類型常量與變量的差異整型、浮點(diǎn)型、字符型的原理及應(yīng)用scanf函數(shù)的原理及應(yīng)用運(yùn)算符與表達(dá)式數(shù)據(jù)類型2.1.1所示。圖2.1.1數(shù)據(jù)類型的分類C(C2.1.1列C語言中的關(guān)鍵字。表2.1.1C語言中的關(guān)鍵字autoconstdoublefloatintshortstructunsignedbreakcontinueelseforlongsignedswitchvoidcasedefaultenumgotoregistersizeoftypedefvolatilechardoexternifreturnstaticunionwie第2第2章 數(shù)據(jù)類型、運(yùn)算符與表達(dá)式PAGE59C語言編程C語言編程PAGE58本章介紹C語言中的基本數(shù)據(jù)類型,即常量和變量。下面首先介紹常量。常量(也稱浮點(diǎn)型、2.2.1所示。整型常量、實(shí)型常量、字符型常量是在編譯時(shí)可以直接編入代"你好"ASCII都是字符串型常量。后面的章節(jié)中我們會(huì)深入講解不同類型的常量。變量
圖2.2.1常量的分類圖2.3.1變量名、變量值和存儲(chǔ)單元的關(guān)系
變量代表內(nèi)存中具有特定屬性的一個(gè)存儲(chǔ)單元,它用來存放數(shù)據(jù),即變量的值。這些值在程序的執(zhí)行過程中是可以改變的。變量名實(shí)際上以一個(gè)名字代表一個(gè)對(duì)應(yīng)的存儲(chǔ)單元地址。編譯、鏈接程序時(shí),由編譯系統(tǒng)為每個(gè)變量名分配對(duì)應(yīng)的內(nèi)存地址。從變量中取值實(shí)際上是通過變量名找到內(nèi)存中存儲(chǔ)單元的地址,并從該存儲(chǔ)單元中讀取數(shù)據(jù),如圖2.3.1所示。 sum,_total,month,Student_name,lotus_1_2_3,BASIC,li_ling 是正確的;而 M.D.John,¥123,3D64,a>b 是錯(cuò)誤的。C語言要求對(duì)所有用到的變量做強(qiáng)整型數(shù)據(jù)符號(hào)常量定義一個(gè)整型變量時(shí)要使用關(guān)鍵字int。下面來看圖2.4.1中的例子。i(即結(jié)果e定義的Idefine定義的內(nèi)容是常量的原因。右鍵單擊對(duì)應(yīng)的項(xiàng)2.4.2所示。設(shè)置完畢后,選擇重新編譯會(huì)顯示編譯失敗,但此時(shí)不用擔(dān)心,因?yàn)殚_啟預(yù)編譯后VS只進(jìn)行預(yù)處理,而不再進(jìn)行其他編譯動(dòng)作(VS針對(duì)沒有編譯出最終可執(zhí)行程序的操作會(huì)提示編譯失敗2.4.31.Debug2.4.4所示。圖2.4.1定義整型變量圖2.4.2將“預(yù)處理到文件”設(shè)置為“是”的界面Debug文件夾中找到main.i2.4.4Notepad++main.i2.4.5define已definedefinePIPI3PI是常量,不可修改。define定義的方法來簡(jiǎn)化操作。這樣,在編寫程序時(shí),如果需要改變程序中多處的同一個(gè)常量,那么只需改變definePI的值即可。圖2.4.3選擇“在文件資源管理器中打開文件夾”選項(xiàng)圖2.4.4打開后的Debug文件夾圖2.4.5預(yù)處理后文件的內(nèi)容整型常量的不同進(jìn)制表示0下面介紹不同進(jìn)制數(shù)的對(duì)應(yīng)關(guān)系。8101int型常量的大小432位。01000001010122的30次方,最高位為符號(hào)位,具體情況將在補(bǔ)碼部分講解。0。3130100110000110001010130,0。上面的二進(jìn)制數(shù)對(duì)應(yīng)的十進(jìn)制數(shù)是1278301950,直接賦值即可。上面的二進(jìn)制數(shù)對(duì)應(yīng)的十六進(jìn)制數(shù)是x36x0~9A417整型的進(jìn)制轉(zhuǎn)換”設(shè)為啟動(dòng)項(xiàng)目。圖2.4.6在已有的解決方案內(nèi)新建項(xiàng)目界面圖2.4.7將“2.整型的進(jìn)制轉(zhuǎn)換”設(shè)為啟動(dòng)項(xiàng)目界面72.4.8所示的結(jié)果。在監(jiān)(取地址ii3200x000000000xFFFFFFFF,2.4.9所示,這稱為進(jìn)程(程序運(yùn)行起來后稱為進(jìn)程)地址空間。程序編譯完畢,開始執(zhí)行時(shí),會(huì)被放入進(jìn)程地址空間的代碼段區(qū)域。執(zhí)行到哪條語句,PC指針就指向該條語句對(duì)應(yīng)的地inti=0x7bi4字節(jié),0x0013FAF8F102.4.10i7b(我們11。i的值是077b000000CPU采用了小端方式進(jìn)行數(shù)據(jù)存儲(chǔ),因此低位在前、高位在后。圖2.4.8單擊“執(zhí)行”按鈕后得到的結(jié)果圖2.4.932位控制臺(tái)應(yīng)用程序的地址范圍圖2.4.10按F10鍵后的結(jié)果2.4.110173轉(zhuǎn)換為十182+781+380=123123如何轉(zhuǎn)換為二進(jìn)制數(shù)呢?方法是讓12320,然后逆序?qū)懗鏊杏鄶?shù),2.4.12小技巧:手動(dòng)轉(zhuǎn)換一個(gè)數(shù)的進(jìn)制后,若不知道轉(zhuǎn)換后的進(jìn)制數(shù)是否正確,則可在Windows243圖2.4.11按“繼續(xù)執(zhí)行”按鈕運(yùn)行到最后的結(jié)果圖2.4.12十進(jìn)制數(shù)123轉(zhuǎn)換為二進(jìn)制數(shù)的詳細(xì)過程圖2.4.13“計(jì)算器”的程序員界面補(bǔ)碼的作用CPUCPU252501,因此我們編寫程序來查看計(jì)算機(jī)是如何存儲(chǔ)?52.4.141?55取反后12.4.15所示。?50xfffffffb50xfffffffa12k代表負(fù)數(shù))0xfffffffd1(1后取反,結(jié)果是一樣的)3,所以其值為?3。圖2.4.14查看計(jì)算機(jī)如何存儲(chǔ)?5的程序圖2.4.15?5在內(nèi)存中的存儲(chǔ)方式圖2.4.165取反、加1并加2后的存儲(chǔ)方式整型變量整型變量包括6種類型,如圖2.4.17所示,其中有符號(hào)基本整型與無符號(hào)基本整型的最高位所代表的意義不同,如圖2.4.18所示。不同整型變量表示的整型數(shù)的范圍如表2.4.1所示,超出范圍會(huì)發(fā)生溢出現(xiàn)象,導(dǎo)致計(jì)算出錯(cuò)。圖2.4.17整型變量的6種類型 圖2.4.18有符號(hào)基本整型與無符號(hào)基本整型的最高位所代表的意義表2.4.1不同整型變量表示的整型數(shù)的范圍類 型類型說明符長(zhǎng) 度整型數(shù)的范圍基本整型int4字節(jié)?231~(231?1)短整型short2字節(jié)?215~(215?1)長(zhǎng)整型long4字節(jié)(64位為8字節(jié))?231~(231?1)或?263~(263?1)無符號(hào)整型unsignedint4字節(jié)0~(232?1)無符號(hào)短整型unsignedshort2字節(jié)0~65535無符號(hào)長(zhǎng)整型unsignedlong4字節(jié)(64位為8字節(jié))0~(232?1)或0~(264?1)由圖2.4.19可以看出不同類型的整型變量的定義方法。下面介紹溢出。圖2.4.19不同類型的整型變量的定義方法327671時(shí),b的值會(huì)變?yōu)槎嗌倌兀繉?shí)際運(yùn)行打印得到的是?32768327670x7fff1后變?yōu)?,其首位?2768,0x8000是最小的負(fù)數(shù),即?32768327671,希望得到的值32768,但結(jié)果卻是?32768264?1時(shí)怎么辦?答案是可以自行實(shí)現(xiàn)大整數(shù)加法,詳見后面介紹數(shù)組時(shí)的說明。圖2.4.19中代碼的執(zhí)行結(jié)果如圖2.4.20所示。圖2.4.20 圖2.4.19中代碼的執(zhí)行結(jié)果b浮點(diǎn)型數(shù)據(jù)浮點(diǎn)型常量表示浮點(diǎn)型常量的形式有兩種,如表2.5.1所示,其中e代表10的冪次,冪次可正可負(fù)。表2.5.1表示浮點(diǎn)型常量的兩種形式小數(shù)形式0.123指數(shù)形式3e?3(為310?3,即0.003)注意:e(E)e后面的指數(shù)必須為整數(shù)。正確示例:1e3、1.8e?3、?123e?6、?.1e?3。錯(cuò)誤示例:e3、2.1e3.5、.e3、e。浮點(diǎn)型變量Cfloatdouble關(guān)鍵字定義浮點(diǎn)型變量。float型變量占用的4字節(jié),double8字節(jié)。與整型數(shù)據(jù)的存儲(chǔ)方式不同,?。∕表示(E表示并分別存放。指數(shù)部分采用規(guī)范化的指數(shù)形式,指數(shù)也分正、負(fù)(S2.1所示。1012.5.2圖2.5.1浮點(diǎn)型數(shù)據(jù)的組成
是IEEE-754浮點(diǎn)型變量存儲(chǔ)標(biāo)準(zhǔn)。表2.5.2IEEE-754浮點(diǎn)型變量存儲(chǔ)標(biāo)準(zhǔn)格式SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM二進(jìn)制數(shù)01000000100100000000000000000000十六進(jìn)制數(shù)40900000S:S是符號(hào)位,用來表示正、負(fù),是1時(shí)代表負(fù)數(shù),是0時(shí)代表正數(shù)。E:E2這是410000001129,12912722。M:M001000000000000000000001,1.00100000000000000000000。下面以浮點(diǎn)數(shù)4.5(十進(jìn)制數(shù))為例具體介紹。10221.0012位即100.142?10.5,因此4.52?12?22?3…來近似一個(gè)小數(shù)的。下面介紹浮點(diǎn)數(shù)的精度控制。double)型三2.5.3所示,因?yàn)楦↑c(diǎn)數(shù)使用的是指數(shù)表示法,所以我們不用擔(dān)心數(shù)值的范圍,也不用2.5.2a的值為201.23456788e+010,變得float71.234567e10abdouble型。表2.5.3浮點(diǎn)數(shù)的數(shù)值范圍與有效數(shù)字類 型位數(shù)數(shù)值范圍有效數(shù)字float3210?37~10386~7位double6410?307~1030815~16位lngob12810?4931~10493218~19位圖2.5.2驗(yàn)證精度丟失現(xiàn)象的程序圖2.5.2中程序的執(zhí)行結(jié)果如圖2.5.3所示。圖2.5.3圖2.5.2中程序的執(zhí)行結(jié)果思考題:把上例程序中的a和b都改為double型,實(shí)際求和后b的值是否正確?字符型數(shù)據(jù)字符型常量''"1表2.6.1各種轉(zhuǎn)義字符及其作用轉(zhuǎn)義字符作 用\n換行\(zhòng)t橫向跳格\r回車\\反斜杠\b退格\0空字符,用于標(biāo)示字符串的結(jié)尾,它不是空格,無法打印\dddddd表示1~3位八進(jìn)制數(shù),用處不大\xhhhh表示1~2位十六進(jìn)制數(shù),用處不大2.6.1圖2.6.1理解轉(zhuǎn)義字符的程序示例圖2.6.1中程序的執(zhí)行效果如圖2.6.2所示。圖2.6.2圖2.6.1中程序的執(zhí)行效果思考題:為什么abc\rd打印出的效果是dbc?字符數(shù)據(jù)在內(nèi)存中的存儲(chǔ)形式及其使用方法char1字節(jié)大小的空間。一個(gè)字符常量存放到一個(gè)字符型變量中時(shí),實(shí)際上并不是把該字符的字型放到內(nèi)存中,而是把該字符的ASCIIASCIIA。打印字符型變量時(shí),如果以ASCII碼表中查找字ASCII2.6.2所示。這樣,字符型數(shù)據(jù)和整2.6.32.6.42.6.5
2.6.3ASCII碼值并顯示對(duì)應(yīng)的字符圖2.6.4獲取字符的程序圖2.6.5圖2.6.4中程序的執(zhí)行結(jié)果ASCII碼值還是賦字符,使用%c打印輸出時(shí)得到的都是字符,使用%d打印輸出時(shí)得到的都是ASCIIAASCII32c32A。字符串型常量字符串型常量是由一對(duì)雙引號(hào)括起來的字符序列。例如,"Howdoyoudo."、"CHINA"、"a"printf("Howdoyoudo.")輸出一個(gè)字符串。但要注意的是,'a'是字符型常量,而"a"是字符串型常量,二者是不同的。charccc="a"c="CHINA",那么這樣的賦值C語言中沒有定義字符串型變量的關(guān)鍵字,介紹字符數(shù)組時(shí)我們將詳細(xì)講解如何存放字符串。C語言規(guī)定以字符'\0'作為字符串結(jié)束標(biāo)志。5個(gè)66'\0'無法顯示。CHINA\0
圖2.7.1字符串型常量"CHINA"在內(nèi)存中的存儲(chǔ)結(jié)果(r(r包括ole2.8.1短字節(jié)到長(zhǎng)字節(jié)的類型轉(zhuǎn)換是由系統(tǒng)自動(dòng)進(jìn)行的,編譯時(shí)不會(huì)給出警告;若反向進(jìn)行,則編譯時(shí)編譯器會(huì)給出警告。int型運(yùn)算C語言中的整型數(shù)算術(shù)運(yùn)算總是以默認(rèn)整型類型的精度進(jìn)行的。為了獲得這個(gè)精度,表達(dá)式中的字符型和短整型操圖2.8.1不同類型數(shù)據(jù)的轉(zhuǎn)換級(jí)別
作數(shù)在使用之前會(huì)被轉(zhuǎn)換為基本整型(int型)操作數(shù),這(negralPooochara,b,c;a=b+c;chara,b,c;a=b+c;其中,bca82.8.1中,結(jié)果不再相同。【例2.8.1】整型常量默認(rèn)按int型運(yùn)算實(shí)例。#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>intmain(){charb=0x93<<1>>1;printf("%x\n",b);//ffffff93b=0x93<<1;b=b>>1;printf("%x\n",b);//13system("pause");}2.8.2
圖2.8.2例2.8.1中程序的執(zhí)行結(jié)果x4b3ff6ff呢?如果用%d輸出,那么可以得到一個(gè)%x4b131。為什么把操作分成兩步后,b130x934字節(jié)進(jìn)行,0x26b后,b0x26b進(jìn)行右移時(shí),單4b4字節(jié)運(yùn)213。int2.8.20VSWin32控制臺(tái)應(yīng)用程32Linux640。那么怎2.8.2。【例2.8.2】?jī)蓚€(gè)較大常量相乘溢出實(shí)例。#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>intmain()intmain(){longl;l=131072*131072;printf("%ld\n",l);system("pause");}我們可以在做乘法前,將整型數(shù)強(qiáng)制轉(zhuǎn)換為long型,32位控制臺(tái)應(yīng)用程序代碼如例2.8.3所示,在32位操作系統(tǒng)下,longlong型只占8字節(jié)而long型占4字節(jié)?!纠?.8.3】32位程序兩個(gè)較大的常量相乘不會(huì)溢出實(shí)例。#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>intmain(){longlongl;l=(longlong)131072*131072;printf("%lld\n",l);system("pause");}2.8.3642.8.4long型即可。圖2.8.3例2.8.3程序的輸出結(jié)果【例2.8.4】64位程序兩個(gè)較大的常量相乘不會(huì)溢出實(shí)例。#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>intmain(){longl;l=(long)131072*131072;printf("%ld\n",l);system("pause");}dodouble
型運(yùn)算浮點(diǎn)型常量默認(rèn)按8字節(jié)運(yùn)算,如例2.8.5所示?!纠?.8.5】浮點(diǎn)型常量運(yùn)算實(shí)例。#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>//浮點(diǎn)型常量默認(rèn)按8字節(jié)運(yùn)算intmain(){floatf=12345678900.0+1;doubled=f;printf("%f\n",f);printf("%f\n",12345678900.0+1);system("pause");return0;}2.8.4
圖2.8.4例2.8.5程序的輸出結(jié)果7f46~71~78double%f8字節(jié)的空間進(jìn)行浮點(diǎn)運(yùn)算,因此可以正常輸出。思考題:在代碼中我們定義了doubled=f,請(qǐng)問d輸出會(huì)是12345678901嗎?類型強(qiáng)制轉(zhuǎn)換場(chǎng)景2.8.5所示的結(jié)果,f2,g2.5。圖2.8.5未進(jìn)行強(qiáng)制類型轉(zhuǎn)換的程序2.8.52.8.6行因?yàn)閷⒁粋€(gè)整型表達(dá)式賦值給浮點(diǎn)數(shù),有13lshort,在做加法產(chǎn)生警告,如果增加了short強(qiáng)制轉(zhuǎn)換,那么就可以去除第13行的警告。圖2.8.6未進(jìn)行強(qiáng)制類型轉(zhuǎn)換的程序的編譯結(jié)果代碼執(zhí)行結(jié)果如圖2.8.7所示。圖2.8.7代碼執(zhí)行結(jié)果思考題:longshortdoublefloat常用的數(shù)據(jù)輸入/輸出函數(shù)2.9.1所示,程序員可以給程序輸入數(shù)據(jù),程序處理后會(huì)返回一個(gè)輸出。C語言通過函printf函數(shù),printfscanf、getcharpintf、putchar。scanf
圖2.9.1程序執(zhí)行流程C語言未提供輸入/C語言通過scanfscanfscanf(專業(yè)用語為阻塞2.9.2所示。圖2.9.2阻塞函數(shù)程序2.9.3scanf函數(shù)不會(huì)被阻塞呢?其實(shí)是因?yàn)榈诙€(gè)scanf函數(shù)讀取了緩沖區(qū)中的'\n',即scanf("%c",&c)實(shí)現(xiàn)了讀取,打印其實(shí)輸出了換行,所以不會(huì)阻塞。圖2.9.3程序執(zhí)行結(jié)果下面介紹緩沖區(qū)原理。緩沖區(qū)其實(shí)就是一段內(nèi)存空間,分為讀緩沖、寫緩沖。C語言緩沖的三種特性如下。全緩沖I/OI/O行緩沖I/OI/O(n)(不帶緩沖ANSIC(C89)要求緩存具有下列特征。當(dāng)且僅當(dāng)標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出不涉及交互設(shè)備時(shí),它們才是全緩存的。標(biāo)準(zhǔn)出錯(cuò)絕不會(huì)是全緩存的。2''%di'f,scanffscanf'。scanf函數(shù)的循環(huán)讀取scanf如圖294fwhile(while3章以后再來看本節(jié)。代碼中為什么要加入fflush(stdin)函數(shù)呢?因?yàn)閒flush函數(shù)具有刷新(清空)標(biāo)準(zhǔn)輸入緩沖scanf函數(shù)就無法匹配成功,scanf函0ret0EOFEOF的返回值為-1。scanf2.9.5Ctrl+Zscanf函數(shù)匹配失敗,循環(huán)結(jié)束。讀者fflush(stdin)a,看一看效果。圖2.9.4實(shí)現(xiàn)多次輸入的程序圖2.9.5程序的執(zhí)行結(jié)果針對(duì)VS2013VSCtrl+Zwhile3次組合Ctrl+Zscanf函數(shù)出錯(cuò)返回-1。2.9.6所示。原理scanfscanf函數(shù)是循環(huán)匹配的,所以不能加fflush(stdin)。如果加了,那么會(huì)導(dǎo)致第一個(gè)字符匹配以后,后面的字符被清空。讀者可以自行嘗試一下。圖2.9.6讀取字符串并打印對(duì)應(yīng)字符串的大寫字母圖2.9.6中程序的執(zhí)行結(jié)果如圖2.9.7所示。圖2.9.7程序的執(zhí)行結(jié)果多種數(shù)據(jù)類型混合輸入scanf數(shù)據(jù)中存在字符型數(shù)據(jù)讀取時(shí),讀取的字符并不會(huì)忽略空格和'(回車符2.9.8所示。編寫代碼時(shí),我們需要在%d與%c之間加入一個(gè)空格。輸入格式和輸出效果如2.9.9所示,scanf44,我們可以通過返回值來判斷scanf函數(shù)匹配成功了幾個(gè)成員,中間任何有一個(gè)成員匹配出錯(cuò),后面的成員都會(huì)匹配出錯(cuò)。圖2.9.8一次讀取多種類型的數(shù)據(jù)圖2.9.9輸入格式和輸出效果由圖2.9.9可以看出浮點(diǎn)數(shù)輸出默認(rèn)帶了6位小數(shù),看起來非常不美觀,此時(shí)我們可以如例2.9.1所示那樣修改代碼,使得輸出效果美觀一些?!纠?.9.1】scanf函數(shù)讀取混合類型輸入。#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>//整型,字符型,浮點(diǎn)型混合輸入intmain(){inti=5;doublef;floatl;charc;intret;ret=scanf("%d%c%lf%f",&i,&c,&f,&l);printf("i=%d,c=%c,f=%5.2lf,l=%5.2f,ret=%d\n",i,c,f,l,ret);system("pause");return0;}程序中,l=%5.2f55個(gè)空格的位置,2代表小數(shù)點(diǎn)后顯示兩位,2.9.10所示。getchar
圖2.9.10例2.9.1中程序的輸出結(jié)果#include<stdio.h>intgetchar(void);使用getchar函數(shù)可以一次從標(biāo)準(zhǔn)輸入讀取一個(gè)字符,它等價(jià)于charc,scanf("%c",&c),#include<stdio.h>intgetchar(void);通過例2.9.2中的代碼我們可以用getchar函數(shù)讀取一個(gè)字符?!纠?.9.2】getchar函數(shù)的使用。#include<stdio.h>#include<stdlib.h>intmain()#include<stdio.h>#include<stdlib.h>intmain(){charc;charc;c=getchar();printf("youinputalphabet=%c\n",c);system("pause");}getchar函數(shù)每次只能讀取一個(gè)字符。例2.9.2中程序的執(zhí)行結(jié)果如圖2.9.11所示。圖2.9.11例2.9.2中程序的執(zhí)行結(jié)果思考題:printfgetchargetchar函數(shù)是否會(huì)被阻塞?putchar函數(shù)介紹putchar輸出字符型數(shù)據(jù)時(shí)使用putchar函數(shù),其作用是向顯示設(shè)備輸出一個(gè)字符,語法格式如下:#include<stdio.h>intputchar(intch);#include<stdio.h>intputchar(intch);其中,參數(shù)ch是要輸出的字符,它既可以是字符型變量、整型變量,又可以是常量。輸出字符'H'的代碼如下:putchar('H');putchar('H');例2.9.3的代碼通過putchar函數(shù)實(shí)現(xiàn)變量、轉(zhuǎn)義字符的打印?!纠?.9.3】putchar函數(shù)的使用。#include<stdio.h>#include<stdlib.h>intmain()#include<stdio.h>#include<stdlib.h>intmain(){chara='a';b='b';c='c';putchar(a);putchar('\b');//putchar(b);putchar(c);putchar('\n');//輸出轉(zhuǎn)義字符system("pause");}例2.9.3中程序的輸出結(jié)果如圖2.9.12所示。圖2.9.12例2.9.3中程序的輸出結(jié)果思考題:如果想讓輸出結(jié)果是ac而非bc,那么應(yīng)該如何改動(dòng)?prprintfprintf是f'語法如下:#include<stdio.h>#include<stdio.h>intprintf(constchar*format,...);printf函數(shù)根據(jù)format給出的格式打印輸出到stdout(標(biāo)準(zhǔn)輸出)和其他參數(shù)中。intage=21;printf("Hello%s,youare%dyearsold\n","Bob",age);字符串格式(format)printf函數(shù)顯示的其他formatprintfintage=21;printf("Hello%s,youare%dyearsold\n","Bob",age);代碼的輸出如下:HelloBob,youare21yearsold sd%-codesprintf函數(shù)的具體代碼格式如表2.9.1所示。priprintf
函數(shù)的具體代碼格式代 碼格 式%c字符%d帶符號(hào)整數(shù)%i帶符號(hào)整數(shù)%e科學(xué)記數(shù)法,使用小寫"e"%E科學(xué)記數(shù)法,使用大寫"E"%f浮點(diǎn)數(shù)%o八進(jìn)制數(shù)%s一串字符%u無符號(hào)整數(shù)%x無符號(hào)十六進(jìn)制數(shù),用小寫字母%X無符號(hào)十六進(jìn)制數(shù),用大寫字母%p一個(gè)指針%%一個(gè)'%'符號(hào)位于%000。另外,也可以使用一個(gè)精度修飾符,精度修飾符根據(jù)使用的格式代碼的不同通常有著不同的含義:用%e、%E和%f精度修飾符指定想要的小數(shù)位數(shù)。例如,%5.2f5位數(shù)字并帶有2位小數(shù)的浮點(diǎn)數(shù)。用%s精度修飾符簡(jiǎn)單地表示一個(gè)最大的長(zhǎng)度,以補(bǔ)充句點(diǎn)前的最小字段長(zhǎng)度。printf函數(shù)的所有輸出都是右對(duì)齊的,除非在%符號(hào)后放置了負(fù)號(hào)。例如,%-5.2f會(huì)顯示5位字符、2位小數(shù)位的浮點(diǎn)數(shù)并且左對(duì)齊。下面來看一個(gè)例子,如例2.9.4所示?!纠?.9.4】printf函數(shù)輸出對(duì)齊。#include<stdio.h>#include<stdlib.h>intmain()#include<stdio.h>#include<stdlib.h>intmain(){inti=10;floatf=96.3;printf("studentnumber=%3dscore=%5.2f\n",i,f);printf("studentnumber=%-3dscore=%5.2f\n",i,f);printf("%10s\n","hello");system("pause");}2.9.1310%10s10printf"hello"字符串5圖2.9.13例2.9.4中程序的執(zhí)行結(jié)果運(yùn)算符與表達(dá)式運(yùn)算符分類C語言提供了13種類型的運(yùn)算符,如下所示。()(+-*/()(><>=()(!&|()(~|^賦值運(yùn)算符(=及其擴(kuò)展賦值運(yùn)算符。(((和。((類型。.(。其他算術(shù)運(yùn)算符及算術(shù)表達(dá)式和5(((((作符的兩個(gè)操作數(shù)都是整型數(shù)時(shí),它執(zhí)行整除運(yùn)算,在其他情況下執(zhí)行浮點(diǎn)型數(shù)除法。%2.10.1s圖2.10.1算術(shù)運(yùn)算符應(yīng)用實(shí)例圖2.10.1中程序的執(zhí)行結(jié)果如圖2.10.2所示。圖2.10.2圖2.10.1中程序的執(zhí)行結(jié)果思考題:abab的值,應(yīng)如何做?CPU(如王者榮耀中采用分?jǐn)?shù)來代替小數(shù)進(jìn)行運(yùn)算。如何比較兩個(gè)分?jǐn)?shù)的大?。ú荒苡贸ㄞD(zhuǎn)成小數(shù)進(jìn)行比較)?12321是對(duì)稱數(shù),123321也456不是對(duì)稱數(shù)。關(guān)系運(yùn)算符與關(guān)系表達(dá)式><==>=<=!=1CC003>45>2B2.10.37圖2.10.3比較一個(gè)浮點(diǎn)數(shù)是否等于某個(gè)值圖2.10.3中程序的執(zhí)行結(jié)果如圖2.10.4所示。圖2.10.4圖2.10.3中程序的執(zhí)行結(jié)果i是否等33==i,即把常量寫在前面而把變量寫在后面。這是因?yàn)楫?dāng)不小心將兩個(gè)(這種寫法屬于華為公司內(nèi)部的一條編程規(guī)范。同時(shí),在編寫程序時(shí),如果我們需要判斷三個(gè)數(shù)是否相等,那么絕對(duì)不可以寫為55550abca==b&&b==c。下面來看一個(gè)例子?!纠?.10.1】關(guān)系運(yùn)算符的使用。#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>//不能用數(shù)學(xué)上的連續(xù)判斷大小來判斷某個(gè)數(shù)intmain(){inta;while(scanf("%d",&a)!=EOF){if(3<a<10){printf("a在3和10之間\n");}else{printf("a不在3和10之間\n");}}system("pause");}例2.10.1中程序的執(zhí)行結(jié)果如圖2.10.5所示。圖2.10.5例2.10.1中程序的執(zhí)行結(jié)果2.10.1a3a3101010aa310a>3&&a603和10之間”。邏輯運(yùn)算符與邏輯表達(dá)式102.10.2while循環(huán)。while循環(huán)后,我們演示了什么是短路運(yùn)算。j=1j==0表達(dá)式為假,因?yàn)橹虚gprintf函數(shù)表達(dá)式不會(huì)再執(zhí)行,因此看不到打印輸出;j=0時(shí),j==0printf函數(shù)得不到打印。工作if2.10.6所示。jj!j10取非,得到100?!纠?.10.2】邏輯運(yùn)算符的使用。#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>//邏輯與、邏輯或的短路運(yùn)算intmain(){inti=0,j;while(scanf("%d",&i)!=EOF){if(i%4==0&&i%100!=0||i%400==0){printf("iisleapyear\n");}else{printf("iisnotleapyear\n");}}j=1;//當(dāng)j不為0時(shí),j==0為假,后面一個(gè)表達(dá)式不會(huì)得到執(zhí)行j==0&&printf("systemiserror\n");j=0;//當(dāng)j為0時(shí),j==0為真,后面一個(gè)表達(dá)式不會(huì)得到執(zhí)行j==0||printf("systemiserror\n");j=10;//下面我們來看一下邏輯非運(yùn)算符i=!!j;printf("i的值=%d\n",i);system("pause");return0;return0;}圖2.10.6例2.10.2中程序的執(zhí)行結(jié)果思考題:如果希望打印邏輯與和邏輯或后面的"systemiserror",那么應(yīng)如何修改代碼?位運(yùn)算符位運(yùn)算符<<、>>、~、|、^、&依次是左移、右移、按位取反、按位或、按位異或、按位與。左移:02。工作中很多時(shí)候申請(qǐng)內(nèi)存時(shí)會(huì)用左移,例如要申請(qǐng)1GB大小的空間,可以使用malloc(1<<30)。malloc函數(shù)的使用將在后面的章節(jié)中介紹。2212。例如,-8>>1,得到的是,但-7>>1得到的并不是-3而是-4-1為-1。異或:相同的數(shù)進(jìn)行異或時(shí),結(jié)果為0,任何數(shù)和0異或的結(jié)果是其本身。按位取反:數(shù)位上的數(shù)是1變?yōu)?,0變?yōu)?。按位與和按位或:用兩個(gè)數(shù)的每一位進(jìn)行與和或。圖2.10.7所給出的例子的執(zhí)行結(jié)果如圖2.10.8所示,有興趣的讀者可以自己改動(dòng)一下。圖2.10.7位運(yùn)算符應(yīng)用實(shí)例圖2.10.8圖2.10.7中程序的執(zhí)行結(jié)果思考題:ab,在不使用第三個(gè)變量的情況下,通過異或操作來交換這兩個(gè)變量的值,這種交換相對(duì)于之前的加法交換有何優(yōu)勢(shì)?1(不可使用循環(huán)O(1)。3.C語言中未提供循環(huán)移位的運(yùn)算符,有興趣的讀者可以自行嘗試實(shí)現(xiàn)一個(gè)能夠循環(huán)移位的函數(shù)。賦值運(yùn)算符為了理解有些操作符存在的限制,必須理解左值(L-value)和右值(R-value)之間的區(qū)別。這兩個(gè)術(shù)語多年前由編譯器設(shè)計(jì)者創(chuàng)造并沿用至今,盡管它們的定義與C語言并不嚴(yán)格吻合。a=b+25;左值是那些能夠出現(xiàn)在賦值符號(hào)左邊的東西,右值是那些可以出現(xiàn)在賦值符號(hào)右邊的東西。例如,a=b+25;其中,a是一個(gè)左值,因?yàn)樗鼧?biāo)識(shí)了一個(gè)可以存儲(chǔ)結(jié)果值的地點(diǎn);b25是一個(gè)右值,因?yàn)樗付艘粋€(gè)值。它們可以互換嗎?比如下面這種寫法:b+25=a;b+25=a;a此時(shí)也可以作為右值;然而,b+25不能作為左值,因?yàn)樗⑽礃?biāo)識(shí)一個(gè)特定的位置(并不對(duì)應(yīng)特定的內(nèi)存空間語句是非法的。查看附錄B,可以看到賦值運(yùn)算符的優(yōu)先級(jí)是非常低的,僅高于逗號(hào)運(yùn)算符。如果我們要用getchar函數(shù)循環(huán)讀取并打印每個(gè)字符,那么應(yīng)如何做呢?我們來看例2.10.3?!纠?.10.3】賦值運(yùn)算符的使用。#include<stdio.h>#include<stdlib.h>intmain()#include<stdio.h>#include<stdlib.h>intmain(){charc;while((c=getchar())!=EOF){printf("%c",c);}system("pause");}09"結(jié)束輸入。圖2.10.9例2.10.3中程序的執(zhí)行結(jié)果c=getchar()EOF相等呢?因?yàn)橘x值運(yùn)算符的優(yōu)c01兩種情況。思考題:有興趣的讀者可以把括號(hào)去掉,單步觀察上面程序的打印輸出。接下來介紹復(fù)合賦值運(yùn)算符。iNum=iNum+5;iNum=iNum+5;iNum+=5;iNum5相加的結(jié)果。使用復(fù)合語句可以實(shí)現(xiàn)同樣的操作。例如,上面的語句可以修改為iNum+=5;賦值運(yùn)算符與復(fù)合賦值運(yùn)算符的區(qū)別如下:復(fù)合賦值運(yùn)算符簡(jiǎn)化了程序,可使程序精煉,提升閱讀速度。復(fù)合賦值運(yùn)算符提高了編譯效率。例2.10.4說明了加后賦值與乘后賦值的用法?!纠?.10.4】加后賦值與乘后賦值的用法。#include<stdio.h>#include<stdlib.h>intmain()#include<stdio.h>#include<stdlib.h>intmain(){intiNum,iResult;iNum=10;iResult=3;iNum+=5;iResult*=iNum;printf("iNum=%d\n",iNum);printf("iResult=%d\n",iResult);system("pause");}iNum5iNum為tm0圖2.10.10例2.10.4中程序的執(zhí)行結(jié)果條件運(yùn)算符與逗號(hào)運(yùn)算符C語言中唯一的一種三目運(yùn)算符。三目運(yùn)算符代表有三個(gè)操作數(shù);雙目運(yùn)算2.10.11所示,通過3if判斷。通過逗號(hào)運(yùn)算符,我們whilescanf("%d%d%d",&a,&b,&c)!=EOF這個(gè)關(guān)系表達(dá)式的真假。圖2.10.11條件運(yùn)算符應(yīng)用實(shí)例自增、自減運(yùn)算符及求字節(jié)運(yùn)算符1BCB圖2.10.12是自增、自減運(yùn)算符的應(yīng)用實(shí)例。圖2.10.12中程序的執(zhí)行結(jié)果如圖2.10.13所示。圖2ijii1加10和。圖2.10.12自增、自減運(yùn)算符應(yīng)用實(shí)例圖2.10.13圖2.10.12中程序的執(zhí)行結(jié)果練習(xí)題如何判斷兩個(gè)浮點(diǎn)數(shù)是否相等?從鍵盤上輸入字符,將小寫字母轉(zhuǎn)換成大寫字母,按組合鍵Ctrl+Z結(jié)束程序。如果有"inta=5,b=3",那么在執(zhí)行完"!a&&b++;"后,a和b的值是什么?進(jìn)制轉(zhuǎn)換。將十進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)制數(shù)。輸入十進(jìn)制數(shù),輸出對(duì)應(yīng)的二進(jìn)制數(shù),按組合鍵Ctrl+Z結(jié)束。將二進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù)。輸入二進(jìn)制數(shù),輸出對(duì)應(yīng)的十進(jìn)制數(shù),按組合鍵Ctrl+Z結(jié)束。將十進(jìn)制數(shù)轉(zhuǎn)換成十六進(jìn)制數(shù)。輸入十進(jìn)制數(shù),輸出對(duì)應(yīng)的十六進(jìn)制數(shù),按組合鍵Ctrl+Z結(jié)束。將十六進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù)。輸入十六進(jìn)制數(shù),輸出對(duì)應(yīng)的十進(jìn)制數(shù),按組合鍵Ctrl+Z結(jié)束。1的個(gè)數(shù)。輸入一個(gè)整數(shù)(可正可負(fù)1的個(gè)數(shù),按組合鍵Ctrl+Z結(jié)束。6(1)10150個(gè)數(shù)出現(xiàn)了兩次,1個(gè)數(shù)出現(xiàn)了一次,找出出現(xiàn)了一次的那個(gè)數(shù)。10250個(gè)數(shù)出現(xiàn)了兩次,2個(gè)數(shù)出現(xiàn)了一次,找出出現(xiàn)了一次的那兩個(gè)數(shù)。10350個(gè)數(shù)出現(xiàn)了兩次,3個(gè)數(shù)出現(xiàn)了一次,找出出現(xiàn)了一次的那三個(gè)數(shù)。答案解析1.見圖2.10.3。scanfaz32即可得到對(duì)應(yīng)的大寫字母。按組合鍵Ctrl+Z結(jié)束輸入。代碼如下:#include<stdio.h>#include<stdlib.h>#include<stdio.h>#include<stdlib.h>intmain(void){charc;while(scanf("%c",&c)!=EOF){if(c>='a'&&c<='z'){c=c-32;}printf("%c",c);}system("pause");return0;}因?yàn)槎搪愤\(yùn)算,所以ab53。4(1)2。詳細(xì)代碼如下:#include<stdio.h>#include<stdio.h>#include<stdlib.h>#defineN2intmain(){intm,r;intbinary[50];intdecimal;printf("輸入一個(gè)十進(jìn)制數(shù):(Ctrl+Z)結(jié)束\n");while(scanf("%d",&decimal)!=EOF){inti=0;m=decimal;while(m/N!=0){r=m%N;m=m/N;binary[i++]=r;}binary[i++]=m;for(intj=i-1;j>=0;j--)printf("%d",binary[j]);printf("\n");}return0;}#include<stdio.h>#include<stdlib.h>#defineN2intmain(){intdecimal=0;charb;intintbinary[50];inti=#include<stdio.h>#include<stdlib.h>#defineN2intmain(){intdecimal=0;charb;intintbinary[50];inti=0;while(scanf("%c",&b)!=EOF)if(b=='\n')continue;binary[i++]=b-'0';}for(intj=i-1;j>=0;j--)decimal+=binary[j]*bw;bw=bw*N;}printf("%d\n",decimal);return0;}同(1N16即可。#include<stdio.h>#include<stdlib.h>#defineN16intmain(){intdecimal=0;charb;intbw=1;intbinary[50];inti=0;#include<stdio.h>#include<stdlib.h>#defineN16intmain(){intdecimal=0;charb;intbw=1;intbinary[50];inti=0;while(scanf("%c",&b)!=EOF)if(b=='\n')continue;if(b>=65&&b<=70)binary[i++]=b-'A'+10;elsebinary[i++]=b-'0';}for(intj=i-1;j>=0;j--)for(intj=i-1;j>=0;j--)decimal+=binary[j]*bw;bw=bw*N;}printf("%d\n",decimal);return0;}#include<stdio.h>#include<stdlib.h>intmain(void){intn,a,con,i;#include<stdio.h>#include<stdlib.h>intmain(void){intn,a,con,i; //n存儲(chǔ)輸入值,a用于存儲(chǔ)n1按位與的結(jié)果,//con記錄1的個(gè)數(shù),i控制循環(huán)次數(shù)while(scanf("%d",&n)!=EOF){i=32;con=0;while(i--){a=n&1;n=if(1==a){con++;}}printf("%d\n",con);}system("pause");return0;}#include<stdio.h>#include<stdlib.h>#defineN101 //#include<stdio.h>#include<stdlib.h>#defineN101 //1111個(gè)數(shù)即可#defineM1intmain(){inta[N];intt=0;intt=0;for(inti=0;i<N;i++)scanf("%d",&a[i]);for(inti=0;i<N;i++){t=t^a[i];}printf("%d",t);printf("\n");return0;}首先將所有的數(shù)異或,因?yàn)橛袃蓚€(gè)數(shù)出現(xiàn)一次,所以最終得到的異或結(jié)果,實(shí)際上是兩個(gè)出現(xiàn)一1#include<stdio.h>#include<stdlib.h>#defineN6#defineM2#include<stdio.h>#include<stdlib.h>#defineN6#defineM2intmain(){inta[N];intt=intnum[M]=inti,pos;for(i=0;i<N;i++)scanf("%d",&a[i]);for(i=0;i<N;i++){t=t^a[i];}//得到所有數(shù)據(jù)的異或結(jié)果pos=t&(-1*t);//1,然后賦值給for(i=0;i<N;i++){if(a[i]&pos)num[0]=num[0]^a[i];//和pos按位與為真放在一堆,全部異或elsenum[1]=num[1]^a[i];//和pos按位與為假放在一堆,全部異或}for(i=0;i<M;i++)printf("%d ",printf("\n");system("pause");return0;}3個(gè)數(shù)字出現(xiàn)一次,其他數(shù)字均出現(xiàn)兩次,因此可以得到n一定為奇數(shù)。3bitbit等,但肯定至少存在某個(gè)bit3個(gè)數(shù)中,有兩個(gè)數(shù)的該bit,一個(gè)數(shù)的該bit兩個(gè)數(shù)的該bit0,一個(gè)數(shù)的該bit1。#include<stdio.h>#include<stdlib.h>intxorArr(int*arr,intlen){if(arr!=NULL&&len>0){intresult=arr[0];for(inti=1;i<len;i++){result^=arr[i];}returnresult;}}/*返回a#include<stdio.h>#include<stdlib.h>intxorArr(int*arr,intlen){if(arr!=NULL&&len>0){intresult=arr[0];for(inti=1;i<len;i++){result^=arr[i];}returnresult;}}/*返回a的最低位的1,其他各位都為0*/intfindFirstBit1Index(inta){returna&(-a);//}/*判斷a中特定的位是否為1,若特定的位為1,則返回true。b確定,b10FindFirstBit1a中要判斷的位便是b中這唯一的1所在的位是否為1。代碼如下:*/*/boolisBit1(inta,intb){returna&b;}//函數(shù)功能:找出數(shù)組中兩個(gè)只出現(xiàn)一次的數(shù)字。voidfindTwoNumInArrayOnlyOnce(int*arr,intlen,int*first,int*second){if(arr==NULL||len<2){return;}*first=0;*second=0;//第一步:將arr中所有的數(shù)異或intxorResult=xorArr(arr,len);//1的下標(biāo)intindex=findFirstBit1Index(xorResult);//第三步:根據(jù)index將arr分成兩個(gè)子數(shù)組,每個(gè)子數(shù)組中只有一個(gè)數(shù)字的次數(shù)為1,//其余都為兩次for(inti=0;i<len;i++){if(isBit1(arr[i],index)){*first^=arr[i];}else{*second^=arr[i];}}}//函數(shù)功能:檢測(cè)數(shù)字a的第iboolisBit1In_i(inta,inti){returna&(1<<i);//將1左移i再進(jìn)行與}//函數(shù)功能:檢測(cè)數(shù)字a是否為奇數(shù)boolisOdd(inta){returna%2;}voidfindThreeNumInArrayOnlyOnce(int*arr,intlen,int*first,int*second,int*third){if(arr==NULL||len<3){return;}*first=0;*second=0;*third=0;//將全部數(shù)據(jù)分為兩類,第一類bit=1,第二類bit=0intcountBit=sizeof(int)*8;//每個(gè)int型的整數(shù)所占的bit數(shù)intcount1,count0;//分別用來保存第一類和第零類中的元素個(gè)數(shù)inttemp1,temp0;//分別用來保存第一類和第零類中所有元素的異或結(jié)果for(inti=0;i<countBit;i++){count1=count0=temp1=temp0;//每次循環(huán)時(shí)清零for(intj=0;j<len;j++){if(isBit1In_i(arr[j],i)){//檢測(cè)arr[j]在第i位是否為1count1++;temp1^=arr[j];}else{count0++;temp0^=arr[j];}}if(isOdd(count1)){//count1為奇數(shù)時(shí)即出現(xiàn)第一種情況:有兩個(gè)出現(xiàn)一次的數(shù)字//該bit為0,一個(gè)為1的情況,或者全為1的情況if(temp0!=0){//說明有兩個(gè)出現(xiàn)一次的數(shù)字在bit=0的類中,另一個(gè)在bit=1//的類中,且值為temp1,否則什么也不做*first=temp1;//找到一個(gè)數(shù)之后,將該數(shù)放在數(shù)組的最后一個(gè)位置,然后在數(shù)組的前//n+1個(gè)元素中尋找,最后調(diào)用在數(shù)組中有兩個(gè)數(shù)字出現(xiàn)一次的函數(shù)//即可解決問題arr[len]=temp1;findTwoNumInArrayOnlyOnce(arr,len+1,second,third);return;//返回即可}}else{//count1為偶數(shù)時(shí)即出現(xiàn)第二種情況:有兩個(gè)出現(xiàn)一次的數(shù)字該bit為1,//一個(gè)為0的情況,或者全為0的情況if(temp1!=0){//說明有兩個(gè)出現(xiàn)一次的數(shù)字在bit=1的類中,另一個(gè)在//bit=0的類中,且值為temp0,否則什么也不做*first=temp0;arr[len]=temp0;findTwoNumInArrayOnlyOnce(arr,len+1,second,third);return;//返回即可}}}}intmain(void){intn;while(scanf("%d",&n)!=EOF&n>0){int*arr=(int*)malloc((n+1)*sizeof(int));//多開辟一個(gè)空間,將找到的第一個(gè)//數(shù)加入最后一個(gè)位置,使得這個(gè)數(shù)在數(shù)組中出現(xiàn)兩次,進(jìn)而方便尋找后面//兩個(gè)只出現(xiàn)一次的數(shù)字if(arr==NULL){exit(EXIT_FAILURE);}intval;for(intscanf("%d",&val);arr[i]=val;}intfirst,second,third;findThreeNumInArrayOnlyOnce(arr,n,&first,&second,&third);printf("%d%d%d\n",first,second,third);}return0;}第3章 選擇與循環(huán)(視頻講解:1.5小時(shí))C語
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 公司函告合同標(biāo)準(zhǔn)文本
- 供貨方木標(biāo)準(zhǔn)文本合同標(biāo)準(zhǔn)文本
- 人壽代理合同標(biāo)準(zhǔn)文本
- 事業(yè)合同樣本修改
- 主播解約經(jīng)紀(jì)合同樣本
- 任命合同標(biāo)準(zhǔn)文本
- 個(gè)體網(wǎng)絡(luò)借款合同標(biāo)準(zhǔn)文本
- 兒童勞動(dòng)合同標(biāo)準(zhǔn)文本
- 五技合同范例
- 養(yǎng)殖聯(lián)營(yíng)協(xié)議合同標(biāo)準(zhǔn)文本
- 清明節(jié)主題班會(huì)緬懷先烈致敬英雄愛國(guó)主義教育PPT課件(含完整內(nèi)容)
- 《病理學(xué)基礎(chǔ)》知識(shí)考核試題題庫(kù)與答案
- GB/T 22588-2008閃光法測(cè)量熱擴(kuò)散系數(shù)或?qū)嵯禂?shù)
- 定向井設(shè)計(jì)暨compass操作指南講解
- 慣性導(dǎo)航PPT匯總
- GB/T 1335.3-2009服裝號(hào)型兒童
- 中國(guó)近現(xiàn)代史綱要學(xué)習(xí)心得體會(huì)800字
- 2020年內(nèi)蒙古自治區(qū)高等職業(yè)院校對(duì)口招收中等職業(yè)學(xué)校畢業(yè)生單獨(dú)考試英語試卷及答案
- 《綠色建筑概論》整套教學(xué)課件
- 福利資本主義的三個(gè)世界課件
- 《電業(yè)安全工作規(guī)程》
評(píng)論
0/150
提交評(píng)論