Upload
-
View
207
Download
4
Embed Size (px)
Citation preview
看似比較簡單的推坑教學~~C語言崩潰到崩潰EX(一)~~
編者:lian0123學歷:南大資工學生 大安高工畢業
本文採用CC授權協定
更新日期:2017/04/03 維護期限:2017/09/01版本編號1.1.9+
前言
•本人的歷鍊還不夠,所以文章有地方錯,歡迎各位大神指出,感謝
•我會嘗試以最簡單方式去進行教學,讓大部分的人能聽的懂。所以拜託大神們在打臉我時,請不要打的太大力
•以下文章有參照:• ISO 9899:2011(C11)公開版本的"WG14 N1570"文件
撰寫此文章的原因(一)
•過去我曾看過金門大學的陳鍾誠教授的十分鐘系列與成功大學的jserv的你所不知道的C語言系列與眾多網路開源的教學文章,我也想為程式界做出一些貢獻,所以撰寫了此類型的文章
•雖然看起來有點簡陋的程式教學,但這也算是我努力寫出來的,但由於要寫多,所以可能會有錯誤或漏寫與打錯字的地方,請見諒或通知我
撰寫此文章的原因(二)
•基於大部分非資工科系但對程式有興趣的學生、部份資工科系但程式能力不強的學生、還有之後入學的新生們.....
•建議去讀一本計算機概論(中文或英文都可以),會比較好閱讀
•前一版,我其實是剛一邊看完C語言的書一邊完成的,所以本次進行了添增了大量補充、修正、ISO9899條文
•我到底該不該去寫個gitbook呢?(猶豫中)
專有名詞一覽表
•ANSI:早期北美的標準公約•ISO:訂製國際標準的組織•ISO 9899:2011:ISO組織第9899號規範,2011年版本•編譯:重新將程式碼編寫成電腦看得懂的語言(機器語言)•IDE:程式編輯器的簡稱•CMD:命令提示字元的簡稱•DOS指令:微軟賣給IBM的DOS系統中所用的指令今windows上仍然能使用
•Unicode:又稱萬國碼,一種文字的編碼方式•副程式:等同於自訂函數,是撰寫者自訂的函數
致新手的話
Debug是很重要的
•Debug不要受到挫折(習慣就好):• 即使你每次寫程式都出現一堆Bug,記得!習慣就好,沒有歷練就不會
有進步
•DeBug也需要一些技巧:• 善用中斷點檢查• 如:注意錯誤訊息欄位的訊息
新手常犯的錯誤
新手常犯的錯誤:分號沒加
• 分號是在大部分程式語言中會出現的符號,除了VB與python等..
• 分號的用途用在每一行程式碼的結束符號,除了"include"、"define"、"基本的 主程式{...}/自訂函數{...}/函數{...}"
• 在分號沒加的情況下,部份編譯器會跳錯誤時會顯示行號,檢查那附近幾行
新手常犯的錯誤:打錯字
• 打錯字算是滿正常的,但在visual Studio的環境下應該不太容易打錯
• 如果你是用其他編輯器,要多注意這個問題
• 但基本上大多數的編譯器會告訴你打的錯字沒有找到之類的錯誤狀況
新手常犯的錯誤:誤刪括號/多打括號
• 以下的所提的括號包含:()、[]、{}
• 有時候delete與backspace時,太順手可能會把其他行的括號刪除,或是多打一個括號
• 基本上,Visual Studio會在括號以紅色波浪的底線去提醒程式設計者這括號有問題,所以依照這個線索去找出是哪一個括號出了問題
新手常犯的錯誤:大小寫錯誤
• 基於程式語言基本上都有分大小寫的,請注意
• 如:int A與int a是不同的東西
新手常犯的錯誤:運算子優先權判斷
•大多數程式語言都有運算子的優先順序,所以程式設計者需配合程式的規範
•解決方法:• 1.用背的• 2.用括弧
新手常犯的錯誤:宣告錯誤
• 變數宣告時:保留字不能拿來宣告成變數(int return = 0;)、不能以數字開頭(int 1a =0;)、不能用特殊符號(int ^% =0;)、不能有空白(int an apple =0;)
• 而我們經常會用"_"來連接變數的單詞,如:int an_apple =0;
• 或者使用大小寫AnApple
• 基本上系統在編譯時,會提醒程式設計者有這個宣告問題
新手常犯的錯誤:邏輯錯誤
• 這基本上是程式設計者本身設計的想法與實際執行情形不同,而產生結果上的差距
• 遇到這情況,最佳的解決辦法就是多練習,以增加自己對程式認知
新手常犯的錯誤:函數錯誤
• 也是同一句話:遇到這情況,最佳的解決辦法就是多練習,以增加自己對程式認知
新手常犯的錯誤:副程式未定義
•通常我們第一個執行的程式是叫main function(主程式),但我們能在所有的function中去呼叫其他的副程式,但是需要先宣告副程式
目錄
目錄
•總共有20章,但看來本篇只提到第10章:• Class 0 C語言的重要技術資料• Class 1 Visual Studio介紹• Class 2 C語言的用途/編譯方式• Class 3 註解、基本變數宣告、運算子• Class 4 基本的I/O• Class 5 判斷式• Class 6 其他的常用函數• Class 7 迴圈• Class 8 自訂函數• Class 9 遞迴• Class 10 陣列
Class 0 C語言的重要技術資料
偉大的C語言開發者們
•丹尼斯·里奇(Dennis Ritchie) 1941~2011•肯·湯普遜(Ken Thompson) 1943~今
C語言的歷史(一)
•C語言基於B語言,B語言為肯·湯普遜設計的程式語言,後來丹尼斯·里奇與肯·湯普遜合作,創造出C語言
•而開發主要的原因是要讓UNIX系統運行在PDP-11上,所設計的程式語言
※在PDP-7上,UNIX系統是由組合語言去撰寫※UNIX是一個很著名的系統,Linux、BSD、MAC OS X的起源※PDP系列的電腦算是在1960左右,頗受當代黑客歡迎的電腦
C語言的歷史(二)
•1967年左右開始設計實作
•1973年,Unix作業系統的核心正式使用C語言去改寫
•1975年,C語言開始移植到其他機器上使用,史蒂芬·強生製作的"可移植編譯器"
•1978年,丹尼斯·里奇和布萊恩·柯林漢合作出版了《C程式設計語言》的第一版,奠定日後C語言規範的基礎
C語言的歷史(三)
•1989年,C語言被美國國家標準協會(ANSI)標準化,史稱:C89、ANSI C、ISO/IEC 9899:1989
•1990年,國際標準化組織(ISO)規定國際標準的C語言,並稍微修改C89的規範,史稱:C90、ISO/IEC 9899:1990
•1999年,更正與修改C89的規範,史稱:C99、ISO/IEC 9899:1999
•2011年,ISO正式發布了新的C語言標準,並提高對C++的相容性,史稱:C11、ISO/IEC 9899:2011
以上純屬廢話
•實際上只要去讀:ISO/IEC 9899:2011(9899:201X)的相關技術資料
•網址:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
著名的C語言 編譯器
•GCC:• 自由軟體基金會(GNU)
•Visual C++:• 微軟(MS)
初學者在使用Visual C++與GCC的差異
•Visual C++:• s_scanf:使用安全化掃描資料,以避免溢位的安全問題• s_get:使用安全化讀取資料,以避免溢位的安全問題• 著名IDE:Visual Studio、Visual C++
•GCC:• gcc編譯時你可以用至選項,自由度較高• 有些函式庫要自己引入• 著名IDE:Dev-C++
Class 1 Visual Studio介紹
何為Visual Studio?
•微軟所開發的IDE ,並分成商用版與社群版
•而我們基本上是使用社群版,而記得下載後,只能試用30天
•所以記得要去註冊微軟的帳號,才能延長使用使用期
•請將Visual Studio 與 Visual Studio Code 視為不一樣的東西
目前Visual Studio有支援的平台
•Windows•Mac OS X(測試版)
為什麽可以用Visual C++專案 撰寫C語言?
•基於Visual Studio是使用Visual C++的編譯器去執行(Visual C++可相容執行C語言)
•所以我們可以在Visual C++專案上去撰寫C語言的程式
如何下載?
•請到:https://www.visualstudio.com/zh-hant/
第一步 到官網點下載
第二步 下載你需要的版本
Visual Studio寫C/C++語言的環境
Class 2 C語言的用途/編譯方式
為什麽要用學C語言
•C語言是一個歷史悠久的程式語言,而在今日,部分的語言是由C語言演化過來的
•著名的有:C,C++,C#,JAVA等......,當然也有一些語言融入了C語言的設計概念
著名的C語言作品
•UNIX、Linux、Mac OSX、Windows 內核等系統核心
•部份驅動程式
•原因:可以去撰寫低階語言、記憶體存取的特性
早期C語言的符號對應表
•因為早期的電腦操作沒有向現在一樣的字元編碼,所以有此表:• ??= 對應於 "#"• ??) 對應於 "]"• ??! 對應於 "|"• ??( 對應於 "["• ??' 對應於 "^"• ??> 對應於 "}"• ??/ 對應於 "/"• ??< 對應於 "{"• ??~ 對應於 "~"
※雖然現代應該也很少人會看到這東西吧......
Class 3 註解、基本變數宣告、運算子
3.1何謂註解?
註解的意思
•意指:註釋與解釋,基於有些東西可能看的懂的人不多,而我們要讓那些人看懂我們弄的東西,所以才要寫註解去向那些看不懂的人解釋
C語言的註解
•而在C語言中的註解分成兩種:•/*文字*/•//文字
•而在你程式碼中的註解不會被編譯,所以你要寫什麼就寫什麽麽•雖然說C99(ISO9899:1999)後支持Unicode編碼(萬國碼)
"/*文字*/" 註解
•這是C99(ISO9899:1999)規格前,唯一一種的註解寫法•而在ISO9899:2011 6.4.9 Comments -1中所提到:
• a string literal, or a comment, the characters /* introduce a comment. The contents of such a comment are examined only to identify multibyte characters and to find the characters */ that terminate it.
• 意指:我們能夠在符號/*到符號*/之間去撰寫程式碼的註解
•而我們在維護C89或更早的程式碼時就能夠注意到只有這種註解
"//文字" 註解
•這是C99(ISO9899:1999)規格後,新的註解寫法•而在ISO9899:2011 6.4.9 Comments -2中所提到:
• Except within a character constant, a string literal, or a comment, the characters //introduce a comment that includes all multibyte characters up to, but not including, thenext new-line character.
• 意思是指://為單行註解,一個//註解範圍只能存在單一一行
•請注意如果你是使用C89或更早的編譯器時,請注意這是1999年後才出現的新規範
3.2變數的型態宣告?
何謂型態?(一)
•所謂的型態就如同:• 你在飲料店買到500 c.c的飲料,這飲料最大也就只有500c.c的容量• 即500c.c的飲料不管是什麼飲料它最大都是500c.c• 而1000c.c的飲料不管是什麼飲料它最大都是1000c.c
•意思就是:• 飲料的容量就是型態,而裡面放的東西就是內容• 而我們的內容物大小只能在型態規範內,否則會飲料會溢出來
何謂型態?(二)
•接著我們做個連接:• 飲料的容量(500c.c)對應於各變數宣告型態配置的記憶體空間(Byte)• 而飲料的內容物也對應於我們配置記憶體中存的東西• 而飲料的溢出也對應程式術語的overflow
•也就是這個動作: int a = 10;
宣告的型態 被宣告的變數 指派 變數內的內容
變數資料型態宣告
•我們所命名的變數前都會有變數的型態宣告,如:int 、float、double、char 等.......
•根據ISO9899:2011 5.2.4.2 Numerical limits-1 中所提:• An implementation is required to document all the limits
specified in this subclause,which are specified in the headers <limits.h> and <float.h>. Additional limits are specified in <stdint.h>.
• 這些型態宣告的範圍限制<limits.h>、<float.h>中指定。 而其他限制是在<stdint.h>中指定。
•我們在此介紹<limits.h>中部份的資料與稍微帶過浮點數的定義
浮點數的型態(一)
•在電腦中,這些浮點數的型態是由數學公式去實做的:
•數學公式:⎧ p log10 b if b is a power of 10⎨⎩ ⎡ 1 + p log 10 b ⎤ otherwise
•對應於:• FLT_DECIMAL_DIG 6• DBL_DECIMAL_DIG 10• LDBL_DECIMAL_DIG 10
浮點數的型態(二)
•數學公式:⎧ p max log 10 b if b is a power of 10⎨⎩ ⎡ 1 + p max log 10 b ⎤ otherwise
•對應於:• DECIMAL_DIG 10
浮點數的型態(三)
•數學公式:⎧ p log 10 b if b is a power of 10⎨⎩ ⎣ ( p − 1) log 10 b ⎦ otherwise
•對應於:• FLT_DIG• DBL_DIG• LDBL_DIG
浮點數的型態(四)
•定義:• maximum representable finite floating-point number:
• (1 − b −p )b e max
•對應於:• FLT_MAX 1E+37• DBL_MAX 1E+37• LDBL_MAX 1E+37
浮點數的型態(五)
•定義:• the difference between 1 and the least value greater than 1
that is representable in thegiven floating point type, b 1−p
•對應於:• FLT_EPSILON 1E-5• DBL_EPSILON 1E-9• LDBL_EPSILON 1E-9
浮點數的型態(六)
•定義:• minimum normalized positive floating-point number, b e min −1
•對應於:• FLT_MIN 1E-37• DBL_MIN 1E-37• LDBL_MIN 1E-37
筆者看到此公式,大腦以停止運轉直接放圖表
續上頁
再續上頁
3.2.1變數與記憶體
記憶體大小(一)
•1bit:• 僅能存1或是0,有1個格子能存1或0
•1Byte:• 等同於8bit,有8個格子能存1或0
•1KB:• 等同於1024Byte,可以存218-1的正整數
※1TB=1024MB,1GB=1024MB,1MB=1024KB,以此類推※我們且能從這裡發現到到這一切都是由2進制
記憶體大小(二)
•符號表示法:• 我們運用1101與0101來示範,將最高位元用來決定他的正負號,1101
符號表示法即為-5,0101符號表示法即為+5,所以我們若用0000~1111取符號表示法:
• 可以-7~+7(-2n-1位元~+2n-1位元-1)
•1的補數表示法:• 我們使用1的補數(0的補數就是1,1的補數就是0)來表示正負號,顧
名思義:一切都取1的補數,最高位元來決定他的正負號:1101取1的補數會變成0010即-2、0101取1的補數會變成1010即+2所以我們若用0000~1111取1的補數:
• 可以-7~+7(-2n-1位元~+2n-1位元-1)
記憶體大小(三)
•2的補數表示法:• 因為我們想要讓變數命名能有最有效實施,於是我們運用了2的補數的特
性,將"符號表示法"與"1的補數表示法"中的正負0的問題解決。因為在數學上,0是沒有正負號的
• 我們用取1的補數+1的概念去實施,可以避免正負0的問題發生,將最高位元用來決定他的正負號,如:1000與0000,會先轉成0111與1111,在進行+1,變成1000與0000,即-8與0,所以我們若用0000~1111取2的補數
• 可以-8~+7(-2n-1位元~+2n-1位元-1)
變數宣告與記憶體
•當我們在變數時,我們的變數所使用的記憶體空間:• 在考慮負數的情況下,我們會用2的補數表示,故我們能用的值:• -2n-1位元~+2n-1位元-1
• 但其實我們也可以強制讓程式變數設定成恆正值:• 0~2n位元
3.2.2在<limts.h>底下的規範
<limts.h>檔案的內容(一)
針對於字元(char)做定義:1.將字元定義成8bit的大小2.字串字元最小值為-1283.字串字元最大值為1274.Unicode的上限值255 假如說我們沒有將字元定義成
無號正數時:1.定義字串最小值定義為-1282.定義字串最小值定義為127(↑即2的補數表示法)
假如說我們有將字元定義成無號正數時:1.定義字串最小值定義為 02.定義字串最小值定義為 255
<limts.h>檔案的內容(二)
基本的變數最大最小值:short、int、long等......
對於8位元的:1.對小值定義2.最大值定義3.無號的最大值定義
對於16位元的:1.對小值定義2.最大值定義3.無號的最大值定義
對於32位元的:1.對小值定義2.最大值定義3.無號最大值定義
<limts.h>檔案的內容(三)
對於64位元的:1.對小值定義2.最大值定義3.無號的最大值定義
對於大於128位元的:1.對小值定義2.最大值定義3.無號的最大值定義
<limts.h>檔案的內容(四)
假如還沒定義SIZE_MAX時,如果是windows的64位元版本,就定義64位元系統所能配置的最大值,如果沒有就用預設的32位元的配置最大值方式
整數:int (一)
•在標頭檔<limts.h>中就有定義到,在對32位元的電腦編譯int型態,有號整數的情況下的範圍為:
• -2147483647-1~2147486647(二的補數表示法)• -(231-1) ~ 231次方
•而在無號整數的情況下,則為:• 0~0xffffffff(此指16進位)• 也就是0~169-1
整數:int (二)
•而我們在宣告時:• 預設為有號整數:• 但如果使用unsigned int 將會宣告成無號整數:
•其實我們可以注意到再三十二位元的電腦上:• 我們會有32位元的位址匯流排來傳送值,即32位數的二進制(232),
但當我們使用二的補數表示法時,實際上會有一位元會拿去表示正負號,故在有號整數宣告的int型態時,會是-(231-1)~ 231
• 反之,無號整數宣告int型態時,範圍則是0~232
其他變數型態
•請參閱此網站(交大):http://yes.nctu.edu.tw/vc/ref/basicdatatype.htm
3.2.3區域變數
變數的有效範圍
•程式當我們在命名變數時,可能會有一定的有效使用範圍限制:• 在宣告變數前,不能使用• 區域變數的區域外,不能使用
變數能使用的區域
•假如我們寫了一個程式,每一個變數都有能存取他的範圍,例如:• 主程式內的變數,如果不傳到其他函數中,那他只能在主程式中被存取• for、while迴圈中宣告的變數,也只能用於此迴圈範圍內
全域變數
•在宣告後,可在下方任何一個的地方進行讀取的變數:• 全域變數的宣告方式:在主程式前進行變數宣告• 因為會破壞程式的結構性,所以不建議使用※建議使用常數,不要進行更改才不會有破壞程式結構性的問題
區域變數與全域變數(一)
#include<stdio.h>int m=0;//此處宣佈的變數為全域變數(不是很好的寫法,改用#define定義m會比較好)int main(void){
int a=10; //a為區域變數,只能在main(void)內去呼叫使用for(int b=0;b<10;b++){//int b為區域變數只能在for迴圈內呼叫使用
int c; //c為區域變數只能在for迴圈內呼叫使用printf("%d ",a);
}return 0;
}
區域變數與全域變數(二)
#include<stdio.h>int m=0;int main(void){
int a=10; for(int b=0;b<10;b++){
int c; printf("%d ",a);
}return 0;
}/*全域變數m 可有效使用的範圍(這樣設定全域變數不是一個好寫法)*/
區域變數與全域變數(三)
#include<stdio.h>int m=0;int main(void){
int a=10; for(int b=0;b<10;b++){
int c; printf("%d ",a);
}return 0;
}/*區域變數a 可有效使用的範圍*/
區域變數與全域變數(四)
#include<stdio.h>int m=0;int main(void){
int a=10; for(int b=0;b<10;b++){
int c; printf("%d ",a);
}return 0;
}/*區域變數 b 可有效使用的範圍*/
區域變數與全域變數(五)
#include<stdio.h>int m=0;int main(void){
int a=10; for(int b=0;b<10;b++){
int c; printf("%d ",a);
}return 0;
}/*區域變數 c 可有效使用的範圍*/
常數
•所謂的常數即:我們將一個很常使用的數值資料轉成一種名稱,使程式將我們設定的常數轉成數值資料
• 位置:前處理器的位置• 語法:#define 名稱 數值資料• 範例:#define DOGS 87
• 此時程式中有DOGS的字詞時,會被解釋成數值87
•指定資料型態為唯讀,類似常數的概念:• const int a=10;
• 當該程式碼執行時,a會被設定為10,且之後無法變動
3.3 運算子
何謂運算子
•當我們再寫程式時,可以用一些符號來進行運算,而那些符號就被稱作運算子,如:
• a = 1+1;的等於與加號• b = 2*5;的等於與乘號• c = a&b;的等於與AND邏輯運算子的符號
等於?指派?
•當我們在寫C語言時,符號"等於"不會等同於數學上相等的意思• 就如同x=x+1,在數學上不成立• 但在程式上x=x+1,是指將變數x+1的值指派到變數x上
•再來是有關==的符號,由於我們在程式中已將'= '作為指派符號,而我們在寫C語言時,會用"== "的符號來判別事物是否相等
※在javascript類的語言中還會用"=== "的符號來判斷型態、資料是否都相等
數學運算子
•+ 加 EX:c=a+b•- 減 EX:c=a-b•* 乘 EX:c=a*b•/ 除 EX:c=a/b•% 取餘數 EX:c=a%b
關係運算子
a>b //a大於ba<b //a小於ba>=b //a大於等於ba<=b //a小於等於ba==b //a等於ba !=b //a不等於b
邏輯運算子
A B A&&B A||B !A
0 0 0 0 1
0 1 0 1 1
1 0 0 1 0
1 1 1 1 0
若讀者看不懂,請將0視為假,並將1視為真並參閱以前讀過的數學課本聯集與交集部份
位元運算子
•當我們輸入數字125與65時,會轉為二進制1111101與1000001
•&:執行AND的1位元運算(凡0即0)•|:執行OR的1位元運算(凡1即1)•^:執行XOR的1位元運算(基數1為1,偶數1為0)•~:執行NOT的1位元運算(單一二進位變數1/0互換)•>>:右移位元,該數值二進制的值向右移一位•<<:左移位元,該數值二進制的值向左移一位
11111011000001 (XOR----------------0111100
1位元運算
替代運算子
•在ISO9899 : 2011 7.9 Alternative spellings <iso646.h> -1 有提到:
• The header <iso646.h> defines the following eleven macros (on the left) that expand to the corresponding tokens
• 即以下提到的<iso646.h>定義的11個替代運算子:• and "&&"、and_eq "&="• bitand "&"、bitor "|"• not "!"、not_eq "!="• or "||"、or_eq "|="• xor "^"、xor_eq "^="• compl "~"
•以下我們只談一小部分
運算子執行優先權
•C語言運算子都被C++語言支援。C語言不支援運算子過載:• 請參閱:
https://zh.wikipedia.org/wiki/C%E5%92%8CC%2B%2B%E9%81%8B%E7%AE%97%E5%AD%90
Class 3.5 語法糖概念
何謂語法糖?
•英文名稱:Syntactic sugar,程式專有術語(方法名稱),當我們在寫程式時,不一定只有一種的表示法:
• 有時原本的程式語法太過複雜,可能會降低程式的可讀性,而語法糖就是一個提升程式閱讀性的東西
• 即另一種寫法等效於原寫法,並有易讀性• 且語法經常會在我們的程式裡出現,但初學者可能會不知道有這個東西
語法糖在程式中的應用(一)
•for迴圈在執行上,就等同於while迴圈的執行模式,以下程式碼是相同功能的:
for迴圈的寫法 while迴圈的寫法
for (i = 0; i < 10; i++){ //P}
i = 0;while (i < 10){ //P i++;}
語法糖在程式中的應用(二)
•在a+=1與a=a+1這兩個公式,a+=1也是意謂著a=a+1,故兩者也是有著相同功能的:
a+=1的寫法 a+=1的寫法
a=a+1; a+=1;
語法糖在程式中的應用(三)
•在a[3]與*(a+3),而後面所提的陣列也是一種語法糖的概念,故兩者亦是有著相同功能的:
a[3]宣告的寫法 *(a+3)宣告的寫法
a[3]={0,1,2,3}; *(a)=0;*(a+1)=1;*(a+2)=2;*(a+3)=3;
Class 3.6 你不能不記得的基本概念
字元與字串
•這是字元:"a"、"b"、"c"
•這是字串:"It is a"、"because ..."、"cat"
•這是換行符號:"\n"
•這是字串結尾符號:"\0"※有'\0'的才能被稱是字串,否則稱作字元陣列
C 語言的格式化符號
•請參閱此網站(金門大學的陳鍾誠教授寫的<C 語言的格式化符號>): http://ccckmit.wikidot.com/cp:format
0與空值
•這是0:"0"
•這是空值:""
Class 3.7 圖形化的解釋
變數、常數、記憶體
•當我們執行「int a=10;」時,以最簡單的方式來說
•我們命名的變數a是一個盒子•而我們的int 就是在宣告盒子的類型與大小•地板是記憶體的位置,會因為盒子的類型與 大小而會用到不同大小的地板空間•常數10是我們丟下去的東西•而當我們下次要用10時就去找a的盒子
a
10
Class 4 基本的I/O
掃描輸入資料"scanf函數"•存放的標頭檔名稱:<stdio.h>
•意思:scan+function(掃描的方程式)
•使用方法:scanf("格式化符號 ",&變數名稱 );
•解說:該函數會抓取你輸入的資料,並寫到變數的記憶體位置上, 所以要用&指到你變數的記憶體位置上
輸出程式資料"printf函數"•存放的標頭檔名稱:<stdio.h>
•意思:print+function(印出的方程式)
•使用方法:printf("格式化符號 ",變數名稱 );
•解說:該函數會抓取你輸入的資料,並寫到變數的記憶體位置上
使用scanf抓字串時,無法抓到空白字元?
•確實,scanf的函數會把"空白字元"判斷為結尾符號,所以如果想輸入"含空格的字串"又要怎麼做呢?
•Ans:使用get函數
輸出程式資料"get函數"•存放的標頭檔名稱:<stdio.h>
•意思:get(取得)
•使用方法:get(變數名稱 );
•解說:此函數會將你所輸入的所有東西(直到換行用的\n)都會抓下來儲存
輸出程式資料"put函數"•存放的標頭檔名稱:<stdio.h>
•意思:put(放入)
•使用方法:put(變數名稱 );
•解說:將整句字串進行輸出
但是.......•我們在Visual Studio上用scanf與get時,會跳出錯誤
•這實際上,是微軟為了防止資料溢位的資安問題,所做出的防護
•為此,微軟特別設定的一個函數s_scanf與s_get來解決此問題
•假若我們要關掉這個安全機制,請在程式的首行加入:• #define _CRT_SECURE_NO_DEPRECATE
掃描輸入資料"s_scanf函數"•存放的標頭檔名稱:<stdio.h>
•意思:safe+scan+function(安全掃描的方程式)
•使用方法:s_scanf("資料型態 ",&變數名稱 );
•解說:此函數專門用於Visual Studio的IDE上,該函數會抓取你 輸入的資料,並寫到變數的記憶體位置上
輸出程式資料"s_get函數"•存放的標頭檔名稱:<stdio.h>
•意思:safe+get(安全取得)
•使用方法:s_get(變數名稱 );
•解說:此函數專門用於Visual Studio的IDE上,此函數會將你所輸入的所有東西(直到換行用的\n)都會抓下來儲存
class 4.5 分析一個程式要有什麽?
分析程式的架構
•一個程式可分為三個部份:• 前處理器• 主程式• 副程式
•而我們能探討的有:• 記憶體(規劃)• 變數(控制)• I/O(輸出)
分析:前處理器
•在此處(前處理器)會去宣告所引用的函式庫與常數定義,就基本的<stdio.h> 與<stdilb.h>而言:
• <stdio.h>中,也幫你弄好的基本的I/O函數• <stdlib.h>中則幫你弄好了基本的函數
分析:主程式(一)
•main( )為主程式,而在執行時,會先執行main( ){ }內的主程式
•所以主程式一定要命名為"main( )",否則在編譯時會跳錯誤
•我們通常在宣告main( )前會用int,這其實是對應結束的return值
分析:主程式(二)
•據國際 ISO9899:2011文件中 5.1.2.2.3 Program startup -1 提到:
• The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:
• int main(void) { /* ... */ }
• or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):
• int main(int argc, char *argv[]) { /* ... */ }
分析:主程式(三)
•上述的內容,即:• 我們在宣告主程式的時候有兩種宣告方式:
• 1.規範使用int型態,並不傳入值,回傳int的返回值:• 也就是我們執行程式結束時,就要回傳給電腦return的值
• 2.規範使用int型態,並傳入值int argc與char argv[],回傳int的返回值• 這則是規範我們在用指令執行程式時,可以在給予程式一句字串的資料,argc對應輸入
字串索引值(總字數-1,因為由0開始計數),argv[]則對應於輸入的每一個字元,其餘部份就如同上述的程式結束時,也要回傳給電腦return的值
分析:主程式(四)
•主程式中的return函數,據國際 ISO9899:2011文件中 5.1.2.2.3 "Program termination"所提到:
• that terminates the main function returns a value of 0• 主程式(main function)結束時要返回0
※既然是國際的規範,那我們也只能接受了......
分析:副程式
•我們所提的副程式即為我們自己去製作的"自訂函數",他就像一般函數一樣,有輸入、有處理、有輸出
•而我們對副程式的的宣告會引響回傳值的型態,除非使用指標回傳否則還是要遵從副程式的的宣告型態
Class 5 判斷式
何謂基本函數
•別人已經幫你寫好的函數,只要呼叫標頭檔(***.h)就可以使用的函數,如先前所提到的"sacnf"、"printf"、"get"、"put"等......
•而本章節將提到,主要的基本函數中的判斷式
基本函數 "if"函數
•範例:if("判斷事件是否成立 "){
"假如判斷成立時,執行的程式碼 "}
講解 "if"函數
•if 用於基本的判斷式:• 假如if( )內的判斷為真,程式將會執行if後面的大括弧{ }內的程式碼• 而if( )內的判斷不為真,則大括弧{ }內的程式碼會被跳過
"if"函數的流程圖
判斷
執行事件
成立
不成立
邏輯範例 "if"函數
if("我中午餓了"){"我就去吃午餐"
}
•也就是:• 假如你中午餓了,你就會吃午餐,則中午不餓的話,就不會去吃午餐
實做 "if"函數(一)
實做 "if"函數(二)
基本函數"if...else"•範例:
if("判斷事件是否成立 "){"假如判斷成立時,執行的程式碼 "
}else{"當上面的判斷不成立時,所執行的程式碼 "
}
講解 "if...else"函數
•if...else用於基本的判斷式:• 假如if( )內的判斷為真,程式將會執行if後面的大括弧{ }內的程式碼• 而if( )內的判斷不為真,會執行else後面的大括弧{ }內的程式碼
•在此情況下,if、else其中一項必然會發生
"if...else"函數的流程圖
判斷
事件A 事件B
成立
不成立
邏輯範例 "if...else"函數
if("我中午餓了"){"我就去吃飯"
}else{"喝冬瓜茶"
}
•也就是:• 假如你中午餓了,你就會吃午餐,則中午不餓的話,就會去喝冬瓜茶
實做 "if...else"函數(一)
實做 "if...else"函數(二)
基本函數"if...else if ...else"•範例:
if("判斷事件是否成立 "){"假如判斷成立時,執行的程式碼 "
}else if("當上述判斷未成立時,再判斷另一事件是否成立 "){"原判斷未成立而另一事件成立時,所執行的程式碼 "
}else{"若上述的事件都為成立時,所執行的程式碼 "
}
講解 "if...else if...else"函數
•if...else if...else用於連續判斷的判斷式:• 假如if( )內的判斷為真,程式將會執行if後面的大括弧{ }內的程式碼• 而if( )內的判斷不為真,就會執行else if( )內的判斷• 如果elseif( )內的判斷為真,就會else if( )後面的大括弧{ }內的程式碼• 如果不為真,程式會繼續向下判斷,找下個else if( )或else( )• 如果上面都沒有判斷為真的話,會執行else後面的大括弧{ }內的程式碼
•在這種連續判斷時,能接多個else if,但只能有一個if 與else•在此情況下,if、else if、else的其中一項必然會發生
邏輯範例 "if...elseif...else..."函數
if("大樂透中了6碼"){"1yee元"
}elseif("大樂透中了5碼""){"1000萬元"
}......(中略)else{
"什麼都沒有"}•也就是:不斷往下去判斷是否中獎
"if...else if...else"函數的流程圖
判斷
事件A
事件C
成立
不成立
判斷不成立
事件B
成立
實做 "if...else if...else"函數(一)
實做 "if...else if...else"函數(二)
基本函數"switch...case..."•範例:
switch("字元或數值的變數 "){case "字元或整數 ":
"要執行的程式碼 "break;
default:"要執行的程式碼 "
}
講解 "switch...case..."函數
•switch...case...用於連續判斷的判斷式:• 此函數基本上是用於連續多選項變數判斷的情況• 首先程式會先讀取switch( )內的變數,變數只能是"字元"或"整數"• 接著程式會向下逐一去尋找對應的case "字元或整數"• 當找到對應的case時,就會執行下方的所有的程式碼,直到switch結束• 而我們為了避免程式會不斷往下執行的狀況,我們會用brack;進行跳出• 而break;的意思則是指跳出的意思,執行時將會跳出到switch結束• 在所有的case都沒被找到的情況下,將會執行default:的程式碼• 在default後的程式碼執行完後,程式就會跳出switch...case...的判斷
邏輯範例 "switch...case..."函數
switch("我的期末考成績"){case "總成績是A ":
"平均下來,勉強及格 "break;
case "總成績是B ":"恭喜我被當掉了QAQ "break;
default:"這是三小成績 "
}
實做switch(...) (一)
實做switch(...) (二)
實做switch(...) (三)
Class 6 其他的常用函數
主程式的"main function"•根據ISO9899:2011 5.1.2.2.3 Program termination-1
中所提:• If the return type of the main function is a type compatible
with int,...(中略)...terminates the main function returns a value of 0. If the return type is not compatible with int, the termination status returned to the host environment is unspecified.
• 亦即,我們在使用int兼容的型態去做main function的宣告時,正常結束時要return 0來回傳;而使用void的時,則回傳是不確定的(不用回傳)
其他函數"system(...);"•範例:
system("DOS指令 ");
講解 "system(...)"函數
•該函數位於<stdilb.h>函式庫中•system(...)的函數用於執行命令提示字元(CMD)中的DOS指
令•而我們最常會使用system("PAUSE");,暫停我們執行的程式
簡單的說明一下DOS指令
•cd:• 用法:cd "資料夾名稱",意指移動你所在位置到某資料夾上
•DIR:• 顯示當前所在的資料夾中所存在的東西
•PAUSE:• 暫停,我們經常使用的system("PAUSE");是指暫停程式並按任意鍵繼
續•START:
• 啟動程式,•shutdown:
• 關機指令,後面需要加參數,請自行摸索
邏輯範例 "system(...)"函數
system("我要電腦去啟動惡意程式.exe");
•也就是:如果電腦真的找到那個惡意程式.exe,那真的會去執行• 當然是在沒有防毒軟體擋下的情況下
其他函數 "exit(...);"•範例:
exit("回傳值 ");
講解 "exit(...);" 函數
•在ISO9899:2011 7.22.4.4 The exit function-2 中提到:• The exit function causes normal program termination to occur.• 即在使用exit( );函數時,系統會將所有這程式相關的東西都關掉
•而基於先前所提到的國際ISO9989:2011中已規範正常結束的值建議是0,此情況用來中斷的exit( );就不建議回傳0,建議是回傳-1
•當然,在void的主程式則需使用exit;,不去回傳值(畢竟是void)
邏輯範例 "exit(...)" 函數
•exit(87 );
•亦即執行到這裡時,強制跳出程式,並回傳87給系統
其他函數"break;"•範例:
break;
其他函數"goto;"•這函數能直接跳到你指定的行數,但會破壞程式的架構,盡可能
不要使用
•用法:goto 行數 ;•範例:goto 11;
其他函數"continue;"•當你的迴圈執行到continue時,會直接回到迴圈的開頭,在繼續
執行執行
講解 "break;" 函數
•在ISO9899:2011 6.8.6.3 The break statement -中提到:• 1. A break statement shall appear only in or as a switch body
or loop body.• 2. A break statement terminates execution of the smallest
enclosing switch or iteration statement.
• 1.即我們使用break;時,只能在switch(選擇)或loop(迴圈)這兩類函數之中 [也就是指switch、for、do-while、while的函數]
• 2.而在執行 break;時,則會強制跳出switch或loop的函數
邏輯範例 "break;" 函數
switch ("我的成績"){case "成績是A":
"我及格了,不會被二一了!";break;
case "成績是B":"在讀一年!QAQ"break;
}•亦即執行到break;時,強制跳出程式,也是跳到 ' } ' 後
其他函數 "return(...)"•範例:
return "函數的型態 ";
講解 "return(...)" 函數
• 當我們執行每一個函數時,除了void函數外的函數都會要求你給return的值,而該return的值與宣告函數時的回傳型態定義相關:
• 假如宣告一個int的函數,那函數只能return int範圍內的整數• 假如宣告一個double的函數,那函數只能return double範圍內的浮點數• 假如宣告一個char的函數,那函數只能return 一個字元• 假如宣告一個char*的函數,那函數就能return 一個字串
• 但在void來宣告函數的情況下,由於賦予該函數的資料型態為空值,故也沒有回傳值
其他函數 "abs(...)"•範例:
"接收abs(...)中return 結果的變數 "=abs("正/負整數 ");
講解 "abs(...)" 函數
•需引用<stdlib.h>•在ISO9899:2011 7.22.6.1 The abs, labs and llabs functions -2 -3 提到:
• 2.The abs, labs, and llabs functions compute the absolute value of an integer j. If the result cannot be represented, the behavior is undefined.
• 3.The abs, labs, and llabs, functions return the absolute value.• 意思是指在使用abs(...)、labs(...)、 llabs(...)時,會計算整數的絕對值
(基於上面的範例我沒複製過來,所以j其實是在括號內的整數變數),且會回傳絕對值
※labs(...)是用於計算long int 的絕對值變數時※llabs(...)則是用於計算long long int 的絕對值變數時
邏輯範例 "abs(...)" 函數
"你的女友對你的好感度 "="-3";"你的女友對你的好感度 "=abs("你的女友對你的好感度 ");
•亦即執行完後,你的女友對你的好感度就會從-3變成+3了,是不是很開心啊?(才怪,我根本沒有女友,那是幻覺 QAQ)
實做 abs(...) (一)
實做 abs(...) (二)
其他函數 "fabs(...)"•範例:
"接收fabs(...)中return結果的變數 "=fabs("正/負浮點數 ");
講解 "fabs(...)" 函數
•需引用<math.h>函式庫
•在ISO9899:2011 7.12.7.2 The fabs functions -2 -3 中提到:• 2.The fabs functions compute the absolute value of a floating-point
number x.• 3.The fabs functions return | x |.• 意指:我們使用fabs(...)是用來計算浮點數的絕對值,且會回傳絕對值
•此函數基本上是用來計算浮數類型的數值的絕對值
邏輯範例 "fabs(...)" 函數
"你的段考成績 "="-10.5";"你的段考成績 "=fabs("你的段考成績 ");
•亦即執行完後,你段考成績就會從-10.5變成+10.5了,是不是很開心啊?(才怪,還不是被當掉了TAT)
實做 fabs(...) (一)
實做 fabs(...) (二)
為什麽會有 abs(...),llabs(...),fabs(...)等...?•這也牽扯到一個很有趣的問題,每個函數都是自訂函數定出來的,
所以使得不同型態的變數要使用函數時,會用不同的函數去執行
•就如同對自訂函數的宣告:• int Myfunction(...) ,return 回傳的值是4Byte整數(因為預設是long int)• long long int Myfunction(...) ,return 回傳的值是8Byte的整數• double Myfunction(...) ,return 回傳的值是8Byte的雙精準浮點數
•也就是計算用的自訂函數會因為我們的數值不同而用不同宣告函數型態、計算方式,所以才會有這些支援不同型態的函數出現
其他函數 "ceil(...)"•範例:
"接收 ceil(...)中 return結果 的變數 "=ecil("浮點數 ");
講解 "ceil(...)" 函數
•需引用<math.h>函式庫
•在ISO9899:2011 7.12.9.1 The ceil functions -2 -3 中提到:
• 2.The ceil functions compute the smallest integer value not less than x.
• 3.The ceil functions return ⎡ x ⎤ , expressed as a floating-point number.
• 也就是指ceil(...)時,該函數會回傳 將輸入數值的小數點無條件進位• 而返回的數值型態依然是浮點數的型態
邏輯範例 "ceil(...)" 函數
"你的期末總平均成績 "="49.213";"你的期末總平均成績 "=ceil("你的期末總平均成績 ");
•亦即執行完後,你段考成績就會從49.213變成50了,是不是很開心啊?(才怪,你又被當掉了OAO)
ceil(...) 參照:
•#include <math.h>• double ceil(double x);• float ceilf(float x);• long double ceill(long double x);
實做 ceil(...) (一)
實做 ceil(...) (二)
其他函數 "floor(...)"•範例:
"接收 floor(...)中 return結果 的變數 "=floor("浮點數 ");
講解 "floor(...)" 函數
•需引用<math.h>函式庫
•在ISO9899:2011 7.12.9.2 The floor functions -2 -3 中提到:
• 2. The floor functions compute the largest integer value not greater than x.
• 3. The floor functions return ⎣ x ⎦ , expressed as a floating-point number.
• 也就是指floor(...)時,該函數會回傳 將輸入數值的小數點無條件捨去• 而返回的數值型態依然是雙倍精準浮點數(double)的型態
邏輯範例 "floor(...)" 函數
"你的期末總平均成績 "="59.9999";"你的期末總平均成績 "=floor("你的期末總平均成績 ");
•亦即執行完後,你段考成績就會從59.9999變成59了,是不是很開心啊?(天殺的!我不是要變成60分嗎!?)
•迷之音:「因為你是用floor(...)啊!怪我嘍?」
實做 floor(...) (一)
實做 floor(...) (二)
floor(...) 相關函數參照
•#include <math.h>• 型別 函數名稱• double floor(double x);• float floorf(float x);• long double floorl(long double x);
Class 7 迴圈
何謂迴圈?
•在滿足一定的條件情況下會重複執行的函數,我們在C語言中會碰到三個著名的迴圈函數:
• while迴圈• do-while迴圈• for迴圈
•而我們如果在迴圈底下的大括弧中宣告變數,而那個變數只能存在於大括弧內,一旦結束迴圈後就不能在去取得該變數,除非:
• 將該變數值傳給其他變數• 宣告成全域變數
while(...)迴圈
•範例:while("判斷式 "){
//"當判斷式成立時所執行的程式碼 "}
講解 "while(...)" 迴圈
•在ISO9899:2011 6.8.5.1 The while statement -1 提到:• The evaluation of the controlling expression takes place before
each execution of the loop body.• 也就是說我們會先判斷while括弧中的邏輯是否為真,如果為真,將會執
行底下{......}的內容,如果不是則會跳出迴圈
•而我們在用while迴圈時,為了避免無限迴圈,需要在內部實做一個控制變數或"break;",使得while迴圈不會變成無限迴圈
• 無限迴圈的寫法:while(1){ //.......}
實做while(...){...} (一)
實做while(...){...} (二)
do{...}while(...)迴圈
•範例:do{
//"會先執行一遍的程式碼,而判斷式成立後會繼續執行此段 "}while("判斷式 ");
講解 "do{...}while(...)" 迴圈
•在ISO9899:2011 6.8.5.2 The do statement -1 提到:• The evaluation of the controlling expression takes place after
each execution of the loop body.• 也就是說我們會先執行do大括弧中的東西,在去執行while來判斷是否
要繼續執行迴圈
•即:do大括弧中的東西,一定會被執行一次•請注意,此處的while需要加分號
實做 do{...}while(...); (一)
實做 do{...}while(...); (二)
for(...)迴圈
•範例:for("底下的區域變數宣告 ";"判斷式 ","程式執行完後的動作 "){
"判斷式成立時所執行的程式 ";}
講解 "for(...)" 迴圈
•在ISO9899:2011 6.8.5.3 The for statement -2 中提到:• Both clause-1 and expression-3 can be omitted.• 也就代表我們可以省略區域變數宣告與內部結束後的動作• (事實上這只是規範,實做上可以製作出for( ; ; )的無限迴圈)
•所謂的for( ; ; )為無限迴圈,無限迴圈意指無限執行不會停止的迴圈,除非你用break;、return 0;、exit(-1);等方式離開例外
•但基本上,只要永遠滿足判斷條件邏輯的就能被稱作無限迴圈
邏輯範例 "for(...)" 迴圈
for("我的年紀=18歲";"今年我還活著";"我的年紀增加一歲"){"吃飯";"工作";"肝指數增加";
}
實做 for(...)迴圈 (一)
實做 for(...)迴圈 (二)
此外,基於有太多的函數
•所以,以下省略:• 筆者過去還曾看過有一本書是都在講C語言的函數• 函數真的很多,有興趣的讀者也可以去找此類的書籍
Class 8 自訂函數
還記得稍早所提到的abs(...)類的函數吧?
•其實這些函數都是別人幫你寫好的,並且也幫你封裝好了• 而我們也只是在使用其他的先烈寫好的函數,那如果我想寫一個從來沒
有人寫過的副程式的話呢?
當我們打開<stdlib.h>的標頭檔時(一)
有稍微看出一些端疑嗎?不同型態的絕對值的型態確認
當我們打開<stdlib.h>的標頭檔時(二)
因為接受的型態不同才使得我們要用不同的函數
Class 8.5 自訂函數與一般函數的關聯性
這是一個構成自訂函數的要件
•輸入資料的型態(可以是void)•函數執行的內容(當然也可以不寫)•函數返回的值(如果是void的宣告可不用回返任何值)
※那這樣自訂函數有什麼意義?※當你想做一個龐大複雜的程式時,自然就會用到了
自訂函數的宣告
•宣告位置:• 在前處理器與主程式的中間的位置
•宣告語法:• "函數回傳型態 " "函數名稱 " ( "輸入內容型態 ","輸入內容型態 ",... );
•宣告範例:• int Myfunction(int a,int b);
自訂函數的呼叫
•呼叫位置:•在主程式或副程式中
•呼叫語法:• "函數名稱 " ( "輸入內容 ","輸入內容 " );
•呼叫範例:• Myfunction(c,d);
自訂函數的設定
•呼叫位置:•在主程式後,自訂函數自己的位置
•呼叫語法:• "函數回傳型態 " "函數名稱 " ( "輸入內容型態+變數名稱 " , ... ){ "內容 "};
•呼叫範例:• int Myfunction(int a,int b){
return a*b; };
自訂函數的範例(一)
自訂函數的範例(二)
Class 9 遞迴
何謂遞迴
•遞迴是一種方法,我們做好一個副程式,然後讓去不斷副程式去呼叫自己,最後去找到我們要的東西,這算是一種比較易讀的解題方法
•但使用此方法需有一定的規劃,且要真的了解遞迴的運作方式
•前提是我們不能讓他去無限呼叫自己,所以一定要限制他的執行次數
•著名的應用:費波那契數列、河內塔解題
Class 10 陣列
何謂陣列?
•所謂的陣列,是指在連續記憶體上配置的空間的數據,我們可以由第一筆資料所存放的位置去逐步尋找該連續記憶體上的東西
•而我們所看到的a[10]則是從a[0]的記憶體位置去向後移動十個記憶體位置,使我們去讀取該記憶體位置上儲存的變數
陣列與語法糖(一)
•在指標中我們是可以去宣告指標的,而在宣告指標的情況下我們也是可以對該指標設定變數:
• 而宣告指標 int *a, *(a+1); 時:• 也就是指將某一個記憶體位置宣告成a,並且在加一個宣告型態大小(int 4Byte)
記憶體空間上• *a的1000~1003加上4Byte會變成*(a+1)的1004~1007• 就上述得知我們所加的常數是宣告型別所佔的大小
• 而在宣告成int a[2];時:• 因為int a[2]是指宣告兩個陣列,所以這時我們也宣告的a[0]與a[1],a[0]是開頭
(索引),而a[1]是a[0]後增加一個型態大小(int 4Byte)的值• 也就是a[0],a[1]的寫法就來源於*a, *(a+1),兩個都是指相同東西
單維陣列
•一維陣列,即一段連續記憶體空間儲存變數的位址• 而以下所提到的二維與三維陣列的概念也是出自於一維陣列的概念• 宣告語法:"型態宣告 " "陣列名 "[總行數]• 宣告範例:int a[6];• 呼叫時,請參閱下方,由0開始:"陣列名 "[行索引值]
資料0 資料1 資料2 資料3 資料4 資料5陣列0 陣列1 陣列2 陣列3 陣列4 陣列5
行→
二維陣列
•二維陣列為一維陣列的延伸:• 將一維陣列的概念,從線轉成座標:• 宣告語法:"型態宣告 " "陣列名 "[總列數][總行數]• 宣告範例:int a[2][6];• 呼叫時,請參閱下方,由0開始:"陣列名 "[列索引值][行索引值]
資料1,0 資料1,1 資料1,2 資料1,3 資料1,4 資料1,5陣列1,0 陣列1,1 陣列1,2 陣列1,3 陣列1,4 陣列1,5
資料0,0 資料0,1 資料0,2 資料0,3 資料0,4 資料0,5
陣列0,0 陣列0,1 陣列0,2 陣列0,3 陣列0,4 陣列0,5
行→
列↓
三維陣列
•簡單上來說,就是由二維陣列的平面轉成三維的圖形陣列• 基於圖形表示起來有點麻煩,暫略
範例(一)
•定義 陣列名[宣告數字] = 寫入陣列0的資料,寫入陣列1的資料.......
•int a[5]= {10,20,30,40,50}; 宣告陣列與其存放的數值
•注意!從0開始編號,5只是宣告的數量
• 給你們看一個有趣的東西: https://www.wetalk.tw/thread-35858-1-1.html
0 1 2 3 4
10 20 30 40 50
範例(二)
int a[5]= {10,20,30,40,50}; 宣告陣列與其存放的數值
在這樣設定後,若我們去呼叫陣列:呼叫a[0]回傳10呼叫a[1]回傳20呼叫a[2]回傳30呼叫a[3]回傳40呼叫a[4]回傳50
範例(三)
•當然我們能在程式中,對單一陣列內部的值去修改,如:a[3]=75
0 1 2 3 4
10 20 30 75 50
範例(四)
•一維陣列: int a[5];
•二維陣列:int a[2][5]
0 1 2 3 4
0 0 1 2 3
1 0 1 2 3
4
4
類似子集合的概念
陣列與副程式
•由於陣列的本身是索引的指標概念,故可直接傳入副程式,並可以直接在副程式中修改其值
字元陣列與字串
•字元陣列與字串的差別:• 字串有'\0'做結尾• 字元則無
•字元陣列與字串不能用"=="來判斷;• 要用strcmp(a,b);來判斷
字串處理函數
•strlen(a); 計算a字串的長度•strcmp(a,b); 比較a,b字串,相同回傳0,a>b回傳1,b>a回傳-1•strncmp(n,a,b); 比較a,b字串,只比較n字元•strcpy(a,b); 複製b字串到a•strncpy(a,b); 複製b字串n個字到a
引用資料來源一覽
引用資料來源一覽(一)
•C語言歷史:https://zh.wikipedia.org/wiki/C语言
•部份的C語言資訊:jserv的 "你所部知道的C語言" 系列
•ISO9899:2011的相關文件