C 語言教學 -- 1.0v :100: === ###### tags: `C` `筆記` `入門` `計算機程式設計` [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fhackmd.io%2F%40asddzxcc1857%2Fc-pre-111&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=%E4%BB%8A%E6%97%A5%E7%80%8F%E8%A6%BD%E6%AC%A1%E6%95%B8%2F%E7%B8%BD%E7%80%8F%E8%A6%BD%E6%AC%A1%E6%95%B8&edge_flat=false)](https://hits.seeyoufarm.com) --- :::danger > [name=王智弘] > [time=Wed, Aug 17, 2022 2:06 PM] > [TOC] ::: --- ## 教學文章說明 :::info #### 內容來自於學長覺得上課一定會用到的內容,如果有不懂的地方可以提問。 #### 下面的教學是根據教授上課的順序來寫,可以慢慢的看,我已經把多餘文字都盡量的減少了。 #### 算是一個基本又精簡的教學,如果要更進階的教學可以去網路上找影片來看或是問學長。 ::: :::info #### ---------------------------------------- #### 前三章的程式碼示範是用同一個程式碼檔案新增內容沿用下去, #### 所以前三章的程式內容會看起來比較冗長,只是內容都是重複的。 #### 後面的章節才有各自寫不同的程式碼檔案。 #### ---------------------------------------- #### [示範程式碼]是教學用 #### [練習題] 是可以嘗試練習的題目 #### [題目程式碼]是可以嘗試練習的題目的參考解答 #### ---------------------------------------- ::: --- ## 0. C 語言 :+1: --- ### 寫程式的工具安裝 :::spoiler **安裝過程** #### Dev-C++ #### 下載連結 https://sourceforge.net/projects/orwelldevcpp/ #### 步驟一 download ![](https://i.imgur.com/3r9MnVb.png) #### 步驟二 ok ![](https://i.imgur.com/FJeS2jH.png) #### 步驟三 agree ![](https://i.imgur.com/GoFwytD.png) #### 步驟四 next ![](https://i.imgur.com/J4HekKw.png) #### 步驟五 install ![](https://i.imgur.com/bXmITKV.png) #### 步驟六 Chinese-TW ![](https://i.imgur.com/oA17uSn.png) #### 步驟七 下一步 ![](https://i.imgur.com/okFn5c4.png) #### 步驟八 ok ![](https://i.imgur.com/ElbCgxd.png) #### 完成了 ![](https://i.imgur.com/xty6yEp.png) #### 開一個新程式檔案 ![](https://i.imgur.com/nWCW3c9.png) #### 可以開始寫程式囉!!....寫完之後... ![](https://i.imgur.com/6wR6aJ4.png) #### 最後一個步驟就是 執行+儲存 F11 或 Ctrl + s #### 恭喜您可以寫出自己的程式了 ::: --- ### C 簡介(大概看過就好) :::spoiler **可以跳過** ```C== C 語言是一種通用的高階語言,最初是由丹尼斯· 裡奇在貝爾實驗室為開發 UNIX 作業系統而設計的。 C 語言最開始是於 1972 年在 DEC PDP-11 計算機上被首次實現。 在 1978 年,布萊恩·柯林漢(Brian Kernighan)和丹尼斯·裡奇(Dennis Ritchie) 製作了 C 的第一個公開可用的描述,現在被稱為 K&R 標準。 UNIX 作業系統,C編譯器,和幾乎所有的 UNIX 應用程式都是用 C 語言編寫的。 由於各種原因,C 語言現在已經成為一種廣泛使用的專業語言。 (1)易於學習。 (2)結構化語言。 (3)它產生高效率的程式。 (4)它可以處理底層的活動。 (5)它可以在多種計算機平臺上編譯。 ``` ::: --- ### 程式語言運作概念 :::success #### 1. 程式語言 ``` 程式語言就像是「指令」,透過我們的設計來讓電腦執行我們想要做的事情。 不過,電腦沒有聰明到能直接讀懂C語言,所以我們必須通過編譯器來讓它讀懂並運行。 ``` #### 2. 編譯器 ``` 因為電腦沒辦法直接看懂程式語言,所以我們需要透過編譯器轉換成機器語言讓電腦能理解。 那我們常用到的C語言編譯器是gcc(GNU Compiler Collection): test.c(原檔案) -> (使用 gcc 指令編譯) -> 機器看得懂的語言 以上這行白話一點就是 test.c 檔案利用 gcc 編譯成機器能理解的語言。 ``` ```c= 首先先創建一個 test.c 的程式碼檔案 gcc test.c -o test //利用gcc編譯 test //執行test ``` ``` 以上動作從創建到執行dev c++工具, 已經把最後兩個步驟 編譯和執行 整合到它的功能之中, 所以執行的時候,只要存檔之後 按F11 就可以 編譯和執行 ``` ::: ### 示範 我的第一個 最簡易 C 程式 (入門) :::success #### 第一行 : ``` 只需要一個int main() 主函式 ``` #### 第二行到第四行 : ``` {}大括號包起來的是主函式的執行內容 ``` #### 第三行 : ``` 再來一個回傳 return 0; 代表程式結束 ``` ::: :::spoiler **示範程式碼** ```C= int main (void)//主函式 { return 0; // 結束程式 } ``` ::: --- ### 示範 我的第二個 C 程式 (入門) :::success #### 第一行 : ``` #include <stdio.h> 引入輸入輸出需要的功能 ``` #### 第二行 : ``` #include <stdlib.h> 引入暫停功能 ``` #### 第四行 : ``` 只需要一個int main() 主函式 ``` #### 第五行到第八行 : ``` {}大括號包起來的是主函式的執行內容 ``` #### 第六行 : ``` 可以讓程式暫停,讓你需要按任一個鍵盤按鍵再繼續... ``` #### 第七行 : ``` 再來一個回傳 return 0; 代表程式結束 ``` ::: :::spoiler **示範程式碼** ```C= #include <stdio.h> //輸入輸出 需要的東西 #include <stdlib.h> //一些功能 需要的東西 (ex: system("pause")暫停功能) int main (void) { system("pause"); //暫停 return 0; // 結束程式 } ``` ::: ### 註解(comment) :::success ``` 有兩種方式 // 單行註解 /**/ 多行註解 ``` ```c= // 這行是註解內容 /* 註解內容.... .... */ ``` ::: --- ## 1. 變數(Variable) --- **本章大綱** **1. 電腦儲存單位bit 2. 宣告變數 3. 初始值設定** --- ### 資料型態在電腦內的存儲大小(有概念就好) :::success 小知識 1-1 ### [電腦的儲存單位bit] ### 簡單介紹: ``` 電腦再一個程式執行當中,儲存資訊的方式簡單來說, 是暫時存放在記憶體當中。 然而,在記憶體中最小的存儲單位是 bit 1 bit 內可以儲存 0 或 1 兩種值 因為bit太小了,所以需要再大一點的單位出現,是所謂的 byte。 在更大一點就是kilobyte(KB)、metabyte(MB)、gigabyte(GB) ``` ### 定義: ``` 1 byte = 8 bit 1KB = 1024 bytes 1MB = 1024 KB 1GB = 1024 MB ``` ### 舉例: ``` (1) 8bit = 1byte (2) 16bit = 2byte (3) 32bit = 4byte (4) 64bit = 8byte ``` ``` (5) 下面的表中 short 資料型態 是 2個bytes = 16個bit , 所以short的一筆資料用了16個bit的記憶體空間 ``` ::: ```c= 資料型態 大小(bytes) 型態名稱 short 2 短整數 int 4 整數 long long 8 長整數 float 4 單精度浮點數 double 8 雙精度浮點數 char 1 字元 ``` --- ### 示範 (宣告資料型態) :::success 小知識 1-2 ### 宣告變數的方式: ``` [資料型態] [變數名稱]; ``` ### 舉例: ``` int number; // 宣告一個名稱為number的整數型態變數 ``` ::: :::danger [初始值的問題] 在還沒給予初始值之前,每一個宣告的資料都是未知的數, 像是宣告 int int_number; 儲存在int_number的值就是未知的值。 ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { //有號短整數 signed short integer // -32768 ~ 32767 short short_number; //有號整數 signed integer // -2147483648 ~ 2147483647 int int_number; //有號長整數 signed long integer // -9223372036854775808 ~ 9223372036854775807 long long long_long_int_number; //有號字元 signed character // -128 ~ 127 char character; //雙精度浮點數 Double-precision floating-point format // 5.563 x 10^−309 ~ 1.798 x 10^+308 double double_number; //單精度浮點數 Single-precision floating-point format // 2.939 x 10^−38 ~ 3.403 x 10^+38 float float_number; system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/jv7CmFg.png) ::: --- ### 示範 (前一個範例 + 賦予初始值) :::success 小知識 1-3 ### 賦予變數值的方式: ``` [變數名稱] = 值; // 把值存給變數 ``` ### 宣告變數 + 賦予變數值的方式: ``` [資料型態] [變數名稱] = 值; // 先做宣告的動作,再把值存給變數 ``` ### 舉例: (1)整數賦值 ``` int a = 101; // 是把101存給a ,這麼一來 a 裡面就是儲存101了 a = 101; // 是把101存給a ,這麼一來 a 裡面就是儲存101了 ``` (2)浮點數賦值 ``` double a = 101.101; // 是把101.101存給a ,這麼一來 a 裡面就是儲存101.101了 a = 101.101; // 是把101.101存給a ,這麼一來 a 裡面就是儲存101.101了 ``` (3)字元賦值 ``` char ch = 'a'; // 字元的範圍是 -128 ~ 127 那麼他每個數字代表的字元是怎麼看呢 // 簡單來說是有一張表叫做ASCII他規定了每一個字元的對應數字 unsigned ch = 'a' // 字元的範圍是 0 ~ 255 就是把負數的128種搬過來正數,所以可以多表示128種 ``` ### ASCII 表 (只需要記得 'a' 'A' '0' 的值就好) ![](https://i.imgur.com/jqpNPxi.png) ``` 從這裡可以看出 'a' 是對應 97 也就是說 'a' 等於 97 '0' 是對應 48 也就是說 '0' 等於 48 以此類推... ``` ### unsigned(沒有正負號)(無號數) ```c= //如果只是要用到正數,沒有用到負數的範圍,就可以改用unsigned unsigned int number1 // 0 ~ 4294967295 unsigned long long int number2 // 0 ~ 18446744073709551615 unsigned char number3 // 0 ~255 ``` ::: :::danger [初始值的問題] 賦予初始值之後那筆資料內的值就是確定的。 ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { //有號短整數 signed short integer // -32768 ~ 32767 short short_number = 101; //有號整數 signed integer // -2147483648 ~ 2147483647 int int_number = 101; //有號長整數 signed long integer // -9223372036854775808 ~ 9223372036854775807 long long long_long_int_number = 101; //有號字元 signed character // -128 ~ 127 char character = 'a'; //雙精度浮點數 Double-precision floating-point format // 5.563 x 10^−309 ~ 1.798 x 10^+308 double double_number = 101.101; //單精度浮點數 Single-precision floating-point format // 2.939 x 10^−38 ~ 3.403 x 10^+38 float float_number = 101.101; system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/VKSCDg9.png) ::: --- ## 2.格式化輸入輸出 --- **本章大綱** **1. scanf函數 2. printf函數 3. sizeof(data type)函數** --- ### 示範 (前一個範例 + 輸入資料) :::success 小知識 1-4 ### [scanf輸入函式] ### 介紹: ``` 輸入函式是C語言內建(寫)在<stdio.h>這個標題檔中的一個函式(後面會教)。 ``` ### 輸入的標準用法: ```c= scanf("(文字) + 被輸入的資料名稱的格式",&被輸入的資料名稱1,&被輸入的資料名稱2,...) // 兩個兩個資料之間用,隔開 // ex : scanf("%d / %d",&a,&b); // 要打上 12 / 3 才能輸入成功 scanf("文字"); //他會先讀取你指定要輸入的這些文字 // ex : scanf("abcd"); // 要打上 abcd 才能輸入成功 ``` ### 一般格式用法: ```c= %hd 輸入短整數(short) %d 輸入整數(int) %lld 輸入長整數(long long) %f 輸入單精度浮點數(float) %e 輸入單精度浮點數(float) %lf 輸入雙精度浮點數(double) %e 輸入雙精度浮點數(double) ``` ### 舉例: ```c= scanf("%d",&number); // 輸入一個整數 // ex : 123 scanf("%lld",&long_long_number) //輸入一個長整數 // ex : 9100000000 scanf("%f",&float_number) //輸入一個浮點數 // ex : 123.25 ``` ### 特殊格式用法: ```c= %x 輸入(不帶/帶前綴)且(小/大寫)十六進位制的整數 (ex: 2f,2F,0x2f,0X2f,0x2F,0X2F) // 十六進位的 2F = 十進位的 47 // 十六進位 0~9 A(=10)~F(=15) // 十進位 0~9 // 八進位 0~7 %o 輸入(不帶/帶前綴)八進位制的整數(ex: 17) (ex: 17,017) %u 輸入無正負號的數 (ex: 1234) ``` ### 舉例: ```c= scanf("%o",&num) //輸入帶前綴八進位制的整數 // ex : 017 scanf("%x",&num) //輸入帶前綴且小寫十六進位制的整數 // ex : 0x2f ``` ### 有些用法不能全部混再一起用,你們可以嘗試看看!! ### 以下範例只使用一般的格式來輸入。 ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { //有號短整數 signed short integer // -32768 ~ 32767 short short_number = 101; scanf("%hd",&short_number); // scanf("%hi",&short_number); // 短整數的輸入方式 //有號整數 signed integer // -2147483648 ~ 2147483647 int int_number = 101; scanf("%d",&int_number); // scanf("%i",&int_number); // 整數的輸入方式 //有號長整數 signed long integer // -9223372036854775808 ~ 9223372036854775807 long long long_long_int_number = 101; scanf("%lld",&long_long_int_number); // scanf("%lli",&long_long_int_number); // 長整數的輸入方式 //有號字元 signed character // -128 ~ 127 char character = 'a'; scanf(" %c",&character);//字元的輸入方式 //雙精度浮點數 Double-precision floating-point format // 5.563 x 10^−309 ~ 1.798 x 10^+308 double double_number = 101.101; scanf("%lf",&double_number);//小數的輸入方式 //單精度浮點數 Single-precision floating-point format // 2.939 x 10^−38 ~ 3.403 x 10^+38 float float_number = 101.101; scanf("%f",&float_number);//小數的輸入方式 system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/e4bHQuf.png) ::: --- ### 示範 (前一個範例 + 輸出資料) :::success 小知識 1-5 ### [printf輸出函式] ### 簡單介紹: ``` 輸入函式是C語言內建在<stdio.h>這個標題檔中的。 ``` ### 輸出的標準用法: ```c= printf("(文字) + 被輸出的資料名稱的格式",被輸出的資料名稱1,被輸出的資料名稱2,...) // 兩個兩個資料之間用,隔開 // ex : printf("%d / %d",a,b); // 會輸出像是 12 / 3 printf("文字"); // ex : printf("abcd"); // 會輸出像是 abcd ``` ### 一般格式用法: ```c= %hd 輸出短整數(short) %d 輸出整數(int) %lld 輸出長整數(long long) %f 輸出單精度浮點數(float) %e 輸出單精度浮點數(float) %lf 輸出雙精度浮點數(double) %e 輸出雙精度浮點數(double) ``` ### 舉例: ```c= printf("%d",num); // 輸出一個整數 // ex : 123 printf("%lld",long_long_number) //輸出一個長整數 // ex : 9100000000 printf("%f",float_num) //輸出一個浮點數(預設有小數點後6位) // ex : 123.250000 ``` ### 特殊格式用法: ```c= %.2f 輸出小數點後兩位 (ex: 100.25) %.5f 輸出小數點後五位 (ex: 100.25000) %x 輸出(不帶前綴)且(小寫)十六進位制的整數(ex: 2f) %X 輸出(不帶前綴)且(大寫)十六進位制的整數(ex: 2F) %#x 輸出(帶前綴)且(小寫)十六進位制的整數(ex: 0x2f) %#X 輸出(帶前綴)且(大寫)十六進位制的整數(ex: 0X2F) // 十六進位的 2F = 十進位的 47 // 十六進位 0~9 A(=10)~F(=15) // 十進位 0~9 // 八進位 0~7 %o 輸出(不帶前綴)八進位制的整數(ex: 17) %#o 輸出(帶前綴)八進位制的整數(ex: 017) %u 輸出無正負號的數 (ex: 1234) %10d 輸出向右靠齊寬度為10的整數 (ex: ++++++++10) + 是示意符號,真正輸出是空格 %-10d 輸出向左靠齊寬度為10的整數 (ex: 10++++++++) + 是示意符號,真正輸出是空格 %+10d 輸出有正負號寬度為10的整數 (ex: _______-10 or _______+10) ``` 有些用法不能全部混再一起用,你們可以嘗試看看!! 再來看些特殊格式的寫法 ### 舉例: ```c= printf("%.2f",float_num) //輸出一個小數點後2位的浮點數 // ex : 123.25 printf("%#x",num) //輸出帶前綴且小寫十六進位制的整數 // ex : 0x2f printf("%8d",num) //輸出向右靠齊寬度為8的整數(※寬度超過8格的整數輸出還是會超過8格); printf("%-8d",num) //輸出向左靠齊寬度為8的整數(※寬度超過8格的整數輸出還是會超過8格); ``` ### 有些用法不能全部混再一起用,你們可以嘗試看看!! ### 以下範例只使用一般的格式來輸出。 ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { //有號短整數 signed short integer // -32768 ~ 32767 short short_number = 101; scanf("%hd",&short_number); // scanf("%hi",&short_number); // 短整數的輸入方式 printf("%hd\n\n",short_number); // printf("%hi\n\n",short_number); // 短整數的輸出方式 //有號整數 signed integer // -2147483648 ~ 2147483647 int int_number = 101; scanf("%d",&int_number); // scanf("%i",&int_number); // 整數的輸入方式 printf("%d\n\n",int_number); // printf("%i\n\n",int_number); // 整數的輸出方式 //有號長整數 signed long integer // -9223372036854775808 ~ 9223372036854775807 long long long_long_int_number = 101; scanf("%lld",&long_long_int_number); // scanf("%lli",&long_long_int_number); // 長整數的輸入方式 printf("%lld\n\n",long_long_int_number); // printf("%lli\n\n",long_long_int_number); // 長整數的輸出方式 //有號字元 signed character // -128 ~ 127 char character = 'a'; scanf(" %c",&character);//字元的輸入方式 printf("%c\n\n",character); //字元的輸出方式 //雙精度浮點數 Double-precision floating-point format // 5.563 x 10^−309 ~ 1.798 x 10^+308 double double_number = 101.101; scanf("%lf",&double_number);//小數的輸入方式 printf("%lf\n\n",double_number); //小數的輸出方式 scanf("%e",&double_number);//小數的輸入方式 printf("%e\n\n",double_number); //科學符號的輸出方式 //單精度浮點數 Single-precision floating-point format // 2.939 x 10^−38 ~ 3.403 x 10^+38 float float_number = 101.101; scanf("%f",&float_number);//小數的輸入方式 printf("%f\n\n",float_number); //小數的輸出方式 scanf("%e",&float_number);//小數的輸入方式 printf("%e\n\n",float_number); //科學符號的輸出方式 system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/uquHcnG.png) ::: ### 練習題 :::info [NCHU 10001 連結](https://nchuoj.ee.nchu.edu.tw/problem/10001) [NCHU 10002 連結](https://nchuoj.ee.nchu.edu.tw/problem/10002) [NCHU 10003 連結](https://nchuoj.ee.nchu.edu.tw/problem/10003) ::: --- ### 示範 (前一個範例 + 輸出bytes) :::success 小知識 1-6 ### sizeof(資料型態) ### 簡單介紹: ``` 可以得到某個資料型態用了多少bytes(記憶體) ``` ### 查詢bytes使用大小的方式: ``` sizeof(資料型態); ``` ### 舉例: ```c= printf("%d",sizeof(int)); 輸出 int 資料型態需要使用多少bytes printf("%d",sizeof(long long)); 輸出 long long 資料型態需要使用多少bytes int number1; printf("%d",sizeof(number1)); 輸出 number1 用了多少bytes double number2; printf("%d",sizeof(number2)); 輸出 number2 用了多少bytes ``` ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { //有號短整數 signed short integer // -32768 ~ 32767 short short_number = 101; scanf("%hd",&short_number); // scanf("%hi",&short_number); // 短整數的輸入方式 printf("%hd\n\n",short_number); // printf("%hi\n\n",short_number); // 短整數的輸出方式 printf("short_number bytes = %d\n\n",sizeof(short_number));//輸出short_number的是用了多少bytes //有號整數 signed integer // -2147483648 ~ 2147483647 int int_number = 101; scanf("%d",&int_number); // scanf("%i",&int_number); // 整數的輸入方式 printf("%d\n\n",int_number); // printf("%i\n\n",int_number); // 整數的輸出方式 printf("int_number bytes = %d\n\n",sizeof(int_number));//輸出int_number的是用了多少bytes //有號長整數 signed long integer // -9223372036854775808 ~ 9223372036854775807 long long long_long_int_number = 101; scanf("%lld",&long_long_int_number); // scanf("%lli",&long_long_int_number); // 長整數的輸入方式 printf("%lld\n\n",long_long_int_number); // printf("%lli\n\n",long_long_int_number); // 長整數的輸出方式 printf("long_long_int_number bytes = %lld\n\n",sizeof(long_long_int_number));//輸出long_long_int_number的是用了多少bytes //有號字元 signed character // -128 ~ 127 char character = 'a'; scanf(" %c",&character);//字元的輸入方式 printf("%c\n\n",character); //字元的輸出方式 printf("character bytes = %d\n\n",sizeof(character));//輸出character的是用了多少bytes //雙精度浮點數 Double-precision floating-point format // 5.563 x 10^−309 ~ 1.798 x 10^+308 double double_number = 101.101; scanf("%lf",&double_number);//小數的輸入方式 printf("%lf\n\n",double_number); //小數的輸出方式 scanf("%e",&double_number);//小數的輸入方式 printf("%e\n\n",double_number); //科學符號的輸出方式 printf("double_number bytes = %d\n\n",sizeof(double_number));//輸出double_number的是用了多少bytes //單精度浮點數 Single-precision floating-point format // 2.939 x 10^−38 ~ 3.403 x 10^+38 float float_number = 101.101; scanf("%f",&float_number);//小數的輸入方式 printf("%f\n\n",float_number); //小數的輸出方式 scanf("%e",&float_number);//小數的輸入方式 printf("%e\n\n",float_number); //科學符號的輸出分式 printf("float_number bytes = %d\n\n",sizeof(float_number));//輸出float_number的是用了多少bytes system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/TsEKwbF.png) ::: --- ## 3.運算子 --- **本章大綱** **1. 算數運算子(+ - \* / %) 2. 移位運算子(>> <<) 3. 位元運算子(& | ^ ~) 4. 遞增和遞減運算子及前後置式(++ --) 5. 負號和加號運算子(+ -) 6. 轉換運算子((data_type)) 7. size運算子(sizeof) ( 前面 章節有示範) 8. 否定運算子(!) ( 選擇敘述 章節會示範) 9. 邏輯運算子(!= == > >= < <=) ( 選擇敘述 章節會示範) 10. 間接和傳址運算子(\* &) ( 指標 章節會示範)** --- ### 示範 (前一個範例 + 加號運算子) :::success 小知識 1-7 運算子分類有三種 ``` 1. 算數運算子(+ - * / %) 2. 移位運算子(>> <<) 3. 位元運算子(& | ^) 4. 遞增和遞減運算子及前後置式(++ --) 5. 負號和加號運算子(+ -) 6. 轉換運算子((data_type)) 7. size運算子(sizeof) ( 前面 章節有示範) 8. 補數運算子(~ !) ( 選擇敘述 章節會示範) 9. 邏輯運算子(!= == > >= < <=) ( 選擇敘述 章節會示範) 10. 間接和傳址運算子(* &) ( 指標 章節會示範) ``` ### [加號運算子] (+) ``` 複習一下賦予變數值的方式 a = 101; // 是把101存給a 再來是把某個變數值存給另一個變數的方式 a = b; // 是把b存給a 再來是把某兩個變數相加的結果存給某個變數 a = a + b; // 是把 a + b 存給 a 再來是跟上面是一樣的意思,只是寫法比較簡潔 a += b; // 也是把 a + b 存給 a ``` ### 舉例 ``` int a = 2, b = 3; a += b; a 會變成 5 b 還是 3 ``` ### [減號運算子] (-) ``` 把某兩個變數相減的結果存給某個變數 a = a - b; // 是把 a - b 存給 a 這是跟上面是一樣的意思,只是寫法比較簡潔 a -= b; // 也是把 a - b 存給 a ``` ### 舉例 ``` int a = 2, b = 3; a -= b; a 會變成 -1 b 還是 3 ``` ### [乘法運算子] (*) ``` 把某兩個變數相乘的結果存給某個變數 a = a * b; // 是把 a * b 存給 a 這是跟上面是一樣的意思,只是寫法比較簡潔 a *= b; // 也是把 a * b 存給 a ``` ### 舉例 ``` int a = 2, b = 3; a *= b; a 會變成 6 b 還是 3 ``` ### [除法運算子] (/) ``` 把某兩個變數相除的商存給某個變數 a = a / b; // 是把 a / b 存給 a 這是跟上面是一樣的意思,只是寫法比較簡潔 a /= b; // 也是把 a / b 存給 a ``` ### 舉例 ``` int a = 2, b = 3; a /= b; a 會變成 0 b 還是 3 ``` ### [餘數運算子] (%) ``` 把某兩個變數相除的餘數存給某個變數 a = a % b; // 是把 a % b 存給 a 這是跟上面是一樣的意思,只是寫法比較簡潔 a %= b; // 也是把 a % b 存給 a ``` ### 舉例 ``` int a = 2, b = 3; a %= b; a 會變成 2 b 還是 3 ``` ### [左移位元運算子] (<<) ``` 把某個變數往左移動幾個bits再存給變數 a = a << 1; // 是把 a 的所使用的 bits 往左移動 1 bit 這是跟上面是一樣的意思,只是寫法比較簡潔 a <<= 1; ``` ### 舉例 ``` 左移位元運算說明: 1 << 1 等於 2 //(0001) => (0010) 1 << 2 等於 4 //(0001) => (0100) 0 << 1 等於 0 //(0000) => (0000) 0 << 2 等於 0 //(0000) => (0000) ``` ``` int a = 2, b = 1; // 二進位的 a = 010 , b = 001 a <<= b; a 會變成 4 (100) b 還是 1 (001) ``` ### [右移位元運算子] (>>) ``` 把某個變數往右移動幾個bits再存給變數 a = a >> 1; // 是把 a 的所使用的 bits 往右移動 1 bit 這是跟上面是一樣的意思,只是寫法比較簡潔 a >>= 1; ``` ### 舉例 ``` 右移位元運算說明: 3 >> 1 等於 1 //(0011) => (0001) 3 >> 2 等於 0 //(0011) => (0000) 5 >> 1 等於 2 //(0101) => (0010) 5 >> 2 等於 1 //(0101) => (0001) ``` ``` int a = 2, b = 1; // 二進位的 a = 010 , b = 001 a >>= b; a 會變成 1 (001) b 還是 1 (001) ``` ### [AND 運算子] (&) ``` 把某兩個變數的bits AND運算的結果存給某個變數 a = a & b; // 是把 a & b 存給 a 這是跟上面是一樣的意思,只是寫法比較簡潔 a &= b; // 也是把 a & b 存給 a ``` ### 舉例 ``` AND運算說明: 1 & 1 等於 1 1 & 0 等於 0 0 & 1 等於 0 0 & 0 等於 0 1001 & 0011 = 0001 ``` ``` int a = 2, b = 1; // 二進位的 a = 10 , b = 01 a &= b; a 會變成 0 b 還是 1 ``` ### [OR 運算子] (|) ``` 把某兩個變數的bits OR運算的結果存給某個變數 a = a | b; // 是把 a | b 存給 a 這是跟上面是一樣的意思,只是寫法比較簡潔 a |= b; // 也是把 a | b 存給 a ``` ### 舉例 ``` OR運算說明: 1 | 1 等於 1 1 | 0 等於 1 0 | 1 等於 1 0 | 0 等於 0 1001 | 0011 = 1011 ``` ``` int a = 2, b = 1; // 二進位的 a = 10 , b = 01 a |= b; a 會變成 3 // a = 11 b 還是 1 ``` ### [XOR 運算子] (^) ``` 把某兩個變數的bits XOR運算的結果存給某個變數 a = a ^ b; // 是把 a ^ b 存給 a 這是跟上面是一樣的意思,只是寫法比較簡潔 a ^= b; // 也是把 a ^ b 存給 a ``` ### 舉例 ``` XOR運算說明: 1 ^ 1 等於 0 1 ^ 0 等於 1 0 ^ 1 等於 1 0 ^ 0 等於 0 1001 ^ 0011 = 1010 ``` ``` int a = 2, b = 1; // 二進位的 a = 10 , b = 01 a ^= b; a 會變成 3 // a = 11 b 還是 1 ``` ### [補數運算子] (~) ``` 把某兩個變數的bits XOR運算的結果存給某個變數 a = ~a; // 是把 a的1's補數 存給 a ``` ### 舉例 ``` 補數運算說明: ~1 -> 0 ~0 -> 1 ~0110 -> 1001 ``` ``` int a = 2, b = 3; // 二進位的 a = 10 , b = 11 a = ~b; // (~b 是把 11 -> 00) a 會變成 0 // a = 00 b 還是 3 ``` ### [遞增運算子][++] ``` ++前置式說明: ++num; // + 1 到 num 的值 int v = ++num; // 會在整個運算式執行完之前 + 1,所以v拿到的值是遞增之後的值 ++後置式說明: num++; // + 1 到 num 的值 int v = num++; // 會在整個運算式執行完之後 + 1,所以v拿到的值是遞增之前的值 ``` ### 舉例 ``` int a_1 = 2; int b_1 = ++a_1; int a_2 = 2; int b_2 = a_2++; a_1 會變成 3 b_1 會存到 3 // 前置式 a_2 會變成 3 b_2 會存到 2 // 後置式 ``` ### [遞減運算子][-\-] ``` --前置式說明: --num; // - 1 到 num 的值 int v = --num; // 會在整個運算式執行完之前 - 1,所以v拿到的值是遞減之後的值 --後置式說明: num--; // - 1 到 num 的值 int v = num--; // 會在整個運算式執行完之後 - 1,所以v拿到的值是遞減之前的值 ``` ### 舉例 ``` int a_1 = 2; int b_1 = --a_1; int a_2 = 2; int b_2 = a_2--; a_1 會變成 1 b_1 會存到 1 // 前置式 a_2 會變成 1 b_2 會存到 2 // 後置式 ``` ### [正號運算子][+] ### 舉例 ``` int a = +101; 存給 a 的值是 101 的正數 ``` ### [負號運算子][-] ### 舉例 ``` int a = -101; 存給 a 的值是 101 的負數 ``` ### [轉換運算子][(data_type)] ### 舉例 ``` int a = 110,b = 50; double d = a / b; 因為110 / 50 會得到 2 的結果存給 d, 所以不會把 110 / 50 = 2.2 的結果 2.2 存給 d ---------------------------------------- double d = (double) a / b; 會把 110 / 50 = 2.2 的結果 2.2 存給 d ``` ### 以下只示範加法運算子怎麼用,請自己試看看其他的唷!! ::: :::danger ### [浮點數和整數除法的特別之處] #### ※ 除法比較需要注意浮點數和整數的結果問題!! [整數/整數 或 浮點數/浮點數] double a = 59/30; // => 整數59遇到整數30資料型態一樣進行運算 => 整數 / 整數 => 結果是捨去小數部分 printf("%f",a); // 結果會是 1.000000 double a = (double)59/30; => (double)將整數59轉換(cast)成浮點數 => 浮點數 / 整數 => 整數遇到浮點數因為資料型態不一致自動轉換(cast)成浮點數 => 浮點數 / 浮點數 => 浮點數59遇到浮點數30資料型態一樣進行運算 => 浮點數 / 浮點數 => 結果是保留小數部分 printf("%f",a); // 結果會是 1.966667 ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { //1. 算數運算子(+ - * / %) //2. 移位運算子(>> <<) //3. 位元運算子(& | ^) //4. 遞增和遞減運算子及前後置式(++ --) //5. 負號和加號運算子(+ -) //6. 轉換運算子((data_type)) //[加號運算子] (+) //複習一下賦予變數值的方式 //a = 101; // 是把101存給a // //再來是把某個變數值存給另一個變數的方式 //a = b; // 是把b存給a // //再來是把某兩個變數相加的結果存給某個變數 //a = a + b; // 是把 a + b 存給 a // //再來是跟上面是一樣的意思,只是寫法比較簡潔 //a += b; // 也是把 a + b 存給 a int a = 2, b = 3; a += b; //a 會變成 5 //b 還是 3 //[減號運算子] (-) //把某兩個變數相減的結果存給某個變數 //a = a - b; // 是把 a - b 存給 a // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a -= b; // 也是把 a - b 存給 a //舉例 a = 2, b = 3; a -= b; //a 會變成 -1 //b 還是 3 //[乘法運算子] (*) //把某兩個變數相乘的結果存給某個變數 //a = a * b; // 是把 a * b 存給 a // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a *= b; // 也是把 a * b 存給 a //舉例 a = 2, b = 3; a *= b; //a 會變成 6 //b 還是 3 //[除法運算子] (/) //把某兩個變數相除的商存給某個變數 //a = a / b; // 是把 a / b 存給 a // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a /= b; // 也是把 a / b 存給 a //舉例 a = 2, b = 3; a /= b; //a 會變成 0 //b 還是 3 //[餘數運算子] (%) //把某兩個變數相除的餘數存給某個變數 //a = a % b; // 是把 a % b 存給 a // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a %= b; // 也是把 a % b 存給 a //舉例 a = 2, b = 3; a %= b; //a 會變成 2 //b 還是 3 //[左移位元運算子] (<<) //把某個變數往左移動幾個bits再存給變數 //a = a << 1; // 是把 a 的所使用的 bits 往左移動 1 bit // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a <<= 1; //舉例 //左移位元運算說明: //1 << 1 等於 2 //(0001) => (0010) //1 << 2 等於 4 //(0001) => (0100) //0 << 1 等於 1 //(0000) => (0001) //0 << 2 等於 2 //(0000) => (0010) a = 2, b = 1; // 二進位的 a = 10 , b = 01 a <<= b; //a 會變成 4 //b 還是 3 //[右移位元運算子] (>>) //把某個變數往右移動幾個bits再存給變數 //a = a >> 1; // 是把 a 的所使用的 bits 往右移動 1 bit // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a >>= 1; //舉例 //左移位元運算說明: //3 >> 1 等於 1 //(0011) => (0001) //3 >> 2 等於 0 //(0011) => (0000) //5 >> 1 等於 2 //(0101) => (0010) //5 >> 2 等於 1 //(0101) => (0001) a = 2, b = 1; // 二進位的 a = 10 , b = 01 a >>= b; //a 會變成 1 //b 還是 3 //[AND 運算子] (&) //把某兩個變數的bits AND運算的結果存給某個變數 //a = a & b; // 是把 a & b 存給 a // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a &= b; // 也是把 a & b 存給 a //舉例 //AND運算說明: //1 & 1 等於 1 //1 & 0 等於 0 //0 & 1 等於 0 //0 & 0 等於 0 a = 2, b = 1; // 二進位的 a = 10 , b = 01 a &= b; //a 會變成 0 //b 還是 3 //[OR 運算子] (|) //把某兩個變數的bits OR運算的結果存給某個變數 //a = a | b; // 是把 a | b 存給 a // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a |= b; // 也是把 a | b 存給 a //舉例 //OR運算說明: //1 & 1 等於 1 //1 & 0 等於 1 //0 & 1 等於 1 //0 & 0 等於 0 a = 2, b = 1; // 二進位的 a = 10 , b = 01 a |= b; //a 會變成 3 // a = 11 //b 還是 3 //[XOR 運算子] (^) //把某兩個變數的bits XOR運算的結果存給某個變數 //a = a ^ b; // 是把 a ^ b 存給 a // //這是跟上面是一樣的意思,只是寫法比較簡潔 //a ^= b; // 也是把 a ^ b 存給 a //舉例 //XOR運算說明: //1 & 1 等於 0 //1 & 0 等於 1 //0 & 1 等於 1 //0 & 0 等於 0 a = 2, b = 1; // 二進位的 a = 10 , b = 01 a ^= b; //a 會變成 3 // a = 11 //b 還是 3 //[補數運算子] (~) //把某兩個變數的bits XOR運算的結果存給某個變數 //a = ~a; // 是把 a的1's補數 存給 a //舉例 //補數運算說明: //1 -> 0 //0 -> 1 //(ex: 0110 -> 1001) int a = 2, b = 3; // 二進位的 a = 10 , b = 11 a = ~b; // (~b 是把 11 -> 00) //a 會變成 0 // a = 00 //b 還是 3 //[遞增運算子][++] int a_1 = 2; int b_1 = ++a_1; // int a_2 = 2; int b_2 = a_2++; //a_1 會變成 3 //b_1 會存到 3 // 前置式 // //a_2 會變成 3 //b_2 會存到 2 // 後置式 //[遞減運算子][--] a_1 = 2; b_1 = --a_1; // a_2 = 2; b_2 = a_2--; // //a_1 會變成 1 //b_1 會存到 1 // 前置式 // //a_2 會變成 1 //b_2 會存到 2 // 後置式 //[正號運算子][+] a = +101; //存給 a 的值是 101 的正數 //[負號運算子][-] a = -101; //存給 a 的值是 101 的負數 //[轉換運算子][(data_type)] a = 110,b = 50; double d = a / b; // //因為110 / 50 會得到 2 的結果存給 d, //所以不會把 110 / 50 = 2.2 的結果 2.2 存給 d // //---------------------------------------- // d = (double) a / b; // //會把 110 / 50 = 2.2 的結果 2.2 存給 d } ``` ```c= #include <stdio.h> #include <stdlib.h> int main (void) { //有號短整數 signed short integer // -32768 ~ 32767 short short_number1 = 101,short_number2 = 102; printf("short_number1 : "); scanf("%hd",&short_number1); // scanf("%hi",&short_number1); // 短整數的輸入方式 printf("short_number2 : "); scanf("%hd",&short_number2); // scanf("%hi",&short_number2); // 短整數的輸入方式 printf("\n----------------------\n"); printf("short_number1 = %hd\n\n",short_number1); // printf("%hi\n\n",short_number1); // 短整數的輸出方式 printf("short_number2 = %hd\n\n",short_number2); // printf("%hi\n\n",short_number2); // 短整數的輸出方式 printf("short_number1 bytes = %d\n\n",sizeof(short_number1));//輸出short_number1的是用了多少bytes printf("short_number2 bytes = %d\n\n",sizeof(short_number2));//輸出short_number1的是用了多少bytes short_number1 += short_number2; // short_number1 = short_number1 + short_number2 printf("short_number1 = %hd",short_number1); printf("\n----------------------\n"); //有號整數 signed integer // -2147483648 ~ 2147483647 int int_number1 = 101,int_number2 = 102; printf("int_number1 : "); scanf("%d",&int_number1); // scanf("%i",&int_number1); // 整數的輸入方式 printf("int_number2 : "); scanf("%d",&int_number2); // scanf("%i",&int_number2); // 整數的輸入方式 printf("\n----------------------\n"); printf("int_number1 = %d\n\n",int_number1); // printf("int_number1 = %i\n\n",int_number1); // 整數的輸出方式 printf("int_number2 = %d\n\n",int_number2); // printf("int_number2 = %i\n\n",int_number2); // 整數的輸出方式 printf("int_number1 bytes = %d\n\n",sizeof(int_number1));//輸出int_number1的是用了多少bytes printf("int_number2 bytes = %d\n\n",sizeof(int_number2));//輸出int_number2的是用了多少bytes int_number1 += int_number2; // int_number1 = int_number1 + int_number2 printf("int_number1 = %d",int_number1); printf("\n----------------------\n"); //有號長整數 signed long integer // -9223372036854775808 ~ 9223372036854775807 long long long_long_int_number1 = 101,long_long_int_number2 = 102; printf("long_long_int_number1 : "); scanf("%lld",&long_long_int_number1); // scanf("%lli",&long_long_int_number1); // 長整數的輸入方式 printf("long_long_int_number2 : "); scanf("%lld",&long_long_int_number2); // scanf("%lli",&long_long_int_number2); // 長整數的輸入方式 printf("\n----------------------\n"); printf("long_long_int_number1 = %lld\n\n",long_long_int_number1); // printf("%lli\n\n",long_long_int_number1); // 長整數的輸出方式 printf("long_long_int_number2 = %lld\n\n",long_long_int_number2); // printf("%lli\n\n",long_long_int_number2); // 長整數的輸出方式 printf("long_long_int_number1 bytes = %lld\n\n",sizeof(long_long_int_number1));//輸出long_long_int_number1的是用了多少bytes printf("long_long_int_number2 bytes = %lld\n\n",sizeof(long_long_int_number2));//輸出long_long_int_number2的是用了多少bytes long_long_int_number1 += long_long_int_number2; // long_long_int_number1 = long_long_int_number1 + long_long_int_number2 printf("long_long_int_number1 = %lld",long_long_int_number1); printf("\n----------------------\n"); //有號字元 signed character // -128 ~ 127 char character = 'a'; printf("character : "); scanf(" %c",&character);//字元的輸入方式 printf("\n----------------------\n"); printf("character = %c\n\n",character); //字元的輸出方式 printf("character bytes = %d\n\n",sizeof(character));//輸出character的是用了多少bytes character += 1; // character = character + 1; printf("character = %c",character); printf("\n----------------------\n"); //雙精度浮點數 Double-precision floating-point format // 5.563 x 10^−309 ~ 1.798 x 10^+308 double double_number1 = 101.101,double_number2 = 102.102; printf("double_number1 : "); scanf("%lf",&double_number1);//小數的輸入方式 printf("double_number2 : "); scanf("%lf",&double_number2);//小數的輸入方式 printf("\n----------------------\n"); printf("double_number1 = %lf\n\n",double_number1); //小數的輸出方式 printf("double_number2 = %lf",double_number2); //小數的輸出方式 printf("\n----------------------\n"); printf("double_number1 : "); scanf("%e",&double_number1);//小數的輸入方式 printf("double_number2 : "); scanf("%e",&double_number2);//小數的輸入方式 printf("double_number1 = %e\n\n",double_number1); //科學符號的輸出方式 printf("double_number2 = %e",double_number2); //科學符號的輸出方式 printf("\n----------------------\n"); printf("double_number1 bytes = %d\n\n",sizeof(double_number1));//輸出double_number1的是用了多少bytes printf("double_number2 bytes = %d",sizeof(double_number2));//輸出double_number2的是用了多少bytes printf("\n----------------------\n"); //單精度浮點數 Single-precision floating-point format // 2.939 x 10^−38 ~ 3.403 x 10^+38 float float_number1 = 101.101,float_number2 = 102.102; printf("float_number1 : "); scanf("%f",&float_number1);//小數的輸入方式 printf("float_number2 : "); scanf("%f",&float_number2);//小數的輸入方式 printf("\n----------------------\n"); printf("float_number1 = %f\n\n",float_number1); //小數的輸出方式 printf("float_number2 = %f",float_number2); //小數的輸出方式 printf("\n----------------------\n"); printf("float_number1 : "); scanf("%e",&float_number1);//小數的輸入方式 printf("float_number2 : "); scanf("%e",&float_number2);//小數的輸入方式 printf("\n----------------------\n"); printf("float_number1 = %e\n\n",float_number1); //科學符號的輸出方式 printf("float_number2 = %e",float_number2); //科學符號的輸出方式 printf("\n----------------------\n"); printf("float_number1 bytes = %d\n\n",sizeof(float_number1));//輸出float_number1的是用了多少bytes printf("float_number2 bytes = %d",sizeof(float_number1));//輸出float_number2的是用了多少bytes printf("\n----------------------\n"); system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/7uc1dHl.png) ![](https://i.imgur.com/7u1bQ3T.png) ::: ### 練習題 :::info [NCHU 10005 連結](https://nchuoj.ee.nchu.edu.tw/problem/10005) [NCHU 10007 連結](https://nchuoj.ee.nchu.edu.tw/problem/10007) [NCHU 10008 連結](https://nchuoj.ee.nchu.edu.tw/problem/10008) [NCHU 10009 連結](https://nchuoj.ee.nchu.edu.tw/problem/10009) [NCHU 10010 連結](https://nchuoj.ee.nchu.edu.tw/problem/10010) [NCHU 10012 連結](https://nchuoj.ee.nchu.edu.tw/problem/10012) [NCHU 10013 連結](https://nchuoj.ee.nchu.edu.tw/problem/10013) [NCHU 10014 連結](https://nchuoj.ee.nchu.edu.tw/problem/10014) ::: --- ## 4.選擇敘述 --- **本章大綱** **1. if...else選擇敘述... 2. switch…case…選擇敘述** --- ### 示範 (if...else... + switch...case...) :::success 小知識 1-8 ### [if...else...] 第一種寫法 ``` 有兩種可能 (1)如果條件式成立就執行if的內容,完成之後離開if (2)如果不成立就執行else的內容,完成之後離開else ``` 第二種寫法 ``` 有三種可能 (1)如果條件一成立,就執行if的內容,完成之後離開if (2)如果條件一不成立,就判斷條件二是否成立,如果成立就執行if的內容,完成之後離開if (3)如果條件一不成立,就判斷條件二是否成立,如果不成立就執行else的內容,完成之後離開else ``` ```c= if(條件式) { 內容... } else { 內容... } -------------------------- if(條件一) { 內容... } else if(條件二) { 內容... } else { 內容... } ``` ### 邏輯運算子[ != == > >= < <= ] ``` 判斷式 | true | false a != b 不相等 相等 a == b 相等值 不相等 a > b 當a大於b a小於等於b a >= b 當a大於等於b a小於b a < b 當a小於b a大於等於b a <= b 當a小於等於b a大於b !a 當a是0或false 當a是非0或true ``` ### 舉例: #### 目的 : ``` 100 / 20 = 5 判斷會執行哪一個 ``` #### 結果 : ``` 會執行第一個if的內容,else不會被執行 ``` ```c= int a = 100,b = 20; if(a / b == 5) //如果相等就執行if { printf("a / b = %d\n",a / b); } else //不相等則執行else { printf("a / b != 5\n"); } ``` ### [switch...case..] 第一種寫法 ``` 運算式的結果從條件一到條件三依序往下判斷是否符合條件, 如果符合就進入某條件的內容,完成之後離開switch。 ``` 第二種寫法 ``` default:是在如果每一個條件都不符合的狀態下最後一定會做的內容(可以不寫default)。 ``` ```c= switch(運算式) { case 條件一: 內容... break; case 條件二: 內容... break; case 條件三: 內容... break; } -------------------------- switch(運算式) { case 條件一: 內容... break; case 條件二: 內容... break; case 條件三: 內容... break; default: 內容... break; } ``` ### 舉例: #### 目的 : ``` 80 / 20 = 4 判斷會執行哪一個 ``` #### 結果 : ``` 先判斷case1、case2、case3都不符合,直到case 4:符合條件, 接下來執行case 4:的內容,最後離開switch判斷式,後面的case 5:直接跳過。 ``` ```c= int a = 80,b = 20; a = 80; switch(a / b) { case 1: printf("case 1 : a / b = %d\n",a / b); break; case 2: printf("case 2 : a / b = %d\n",a / b); break; case 3: printf("case 3 : a / b = %d\n",a / b); break; case 4: printf("case 4 : a / b = %d\n",a / b); break; case 5: printf("case 5 : a / b = %d\n",a / b); break; } ``` ### 以下只示範簡易的if...else... 和 switch...case...怎麼用,請自己試看看他怎麼運用在題目!! ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main(void) { //if...else.. int a = 100,b = 20; if(a / b == 5) { printf("a / b = %d\n",a / b); } else { printf("a / b != 5\n"); } //switch...case a = 80; switch(a / b) { case 1: printf("case 1 : a / b = %d\n",a / b); break; case 2: printf("case 2 : a / b = %d\n",a / b); break; case 3: printf("case 3 : a / b = %d\n",a / b); break; case 4: printf("case 4 : a / b = %d\n",a / b); break; case 5: printf("case 5 : a / b = %d\n",a / b); break; } return 0; } ``` **執行結果** ![](https://i.imgur.com/LkCuDGW.png) ::: ### 練習題 :::info [NCHU 10004 連結](https://nchuoj.ee.nchu.edu.tw/problem/10004) [NCHU 10006 連結](https://nchuoj.ee.nchu.edu.tw/problem/10006) [NCHU 10015 連結](https://nchuoj.ee.nchu.edu.tw/problem/10015) [NCHU 10016 連結](https://nchuoj.ee.nchu.edu.tw/problem/10016) [NCHU 10017 連結](https://nchuoj.ee.nchu.edu.tw/problem/10017) [NCHU 10018 連結](https://nchuoj.ee.nchu.edu.tw/problem/10018) [NCHU 10019 連結](https://nchuoj.ee.nchu.edu.tw/problem/10019) ::: --- ## 5.迴圈 --- **本章大綱** **1. for迴圈 2. while迴圈 3. do...while迴圈** --- ### 示範 (for + while + do...while) :::success 小知識 1-9 ### [for] #### 執行順序 ``` (1)初始值 -> (2)條件式 -> (3)內容 -> (4)運算式 -> (2)條件式 -> (3)內容 -> (4)運算式 ``` ``` 初始值只有一次,接下來就是(2)(3)(4)接著(2)(3)(4)一直重複跑到(2)條件式不成立,離開for迴圈 ``` ```c= for(初始值;條件式;運算式) { 內容... } ``` ### [while] #### 執行順序 ``` (1)條件式 -> (2)內容 -> (1)條件式 -> (2)內容 ``` ``` 沒有初始值,就是(1)(2)接著(1)(2)一直重複跑到(1)條件式不成立,離開while迴圈 ``` ```c= while(條件式) { 內容... } ``` ### [do...while] #### 執行順序 ``` (1)內容 -> (2)條件式 -> (1) 內容 -> (2)條件式 ``` ``` 沒有初始值,就是(1)(2)接著(1)(2)一直重複跑到(2)條件式不成立,離開do...while迴圈 ``` do...while 與 while差別在於 先執行再判斷 和 先判斷再執行 ```c= do{ 內容... }while(條件式); ``` ### 以下只示範簡易的 for 和 while 和 do...while 怎麼用,請自己試看看他怎麼運用在題目!! ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main(void) { int a,i; //for 版本 a = 0; for(i = 1 ; i <= 100 ; i+=2) // 從 1 到 100 的每一個奇數都跑過一次 { a += i; } printf("for : %d\n",a);//輸出從 1 到 100 的所有奇數總和 a //while 版本 a = 0; i = 1; while(i <= 100)// 從 1 到 100 的每一個奇數都跑過一次 { a += i; i+=2; } printf("while : %d\n",a);//輸出從 1 到 100 的所有奇數總和 a //do...while 版本 a = 0; i = 1; do{// 從 1 到 100 的每一個奇數都跑過一次 a += i; i+=2; }while(i <= 100); printf("do...while : %d\n",a);//輸出從 1 到 100 的所有奇數總和 a system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/PUP4A8M.png) ::: ### 練習題 :::info [NCHU 10006 連結](https://nchuoj.ee.nchu.edu.tw/problem/10006) [NCHU 10011 連結](https://nchuoj.ee.nchu.edu.tw/problem/10011) [NCHU 10020 連結](https://nchuoj.ee.nchu.edu.tw/problem/10020) [NCHU 10021 連結](https://nchuoj.ee.nchu.edu.tw/problem/10021) [NCHU 10029 連結](https://nchuoj.ee.nchu.edu.tw/problem/10029) **題目 : 計算1 ~ n的總和** 1 <= n <= 100 ``` input_1: 100 output_1: sum = 5050 ``` ``` input_2: 32 output_2: sum = 528 ``` ::: :::spoiler **題目程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { int number; scanf("%d",&number); int sum = 0,i; for(i = 1 ; i <= number ; i++) { sum += i; } printf("sum = %d",sum); } ``` **執行結果** ![](https://i.imgur.com/uwftzXR.png) ::: --- ## 6. 函式與儲存類別 --- **本章大綱** **1. 有值回傳的函數 2. 沒有值回傳的函數 3. 區域變數 4. 全域變數** --- ### 示範 (函式 + 區域變數 + 全域變數) :::success 小知識 1-10 ### [函數宣告方式] ```c= [資料型態] [函數名稱](需傳入的參數) { 內容... 最後要回傳資料型態; } ``` ### 舉例: #### 目的 : ``` (1)我要一個三倍的數字 (2)印出一排星號 ``` ```c= ---------------以下是(有回傳) vs (沒有回傳)-------------- // int 型態的函數(有回傳值,要int型態) int three_times(int num) { return num * 3; } // void 型態的函數(沒有回傳值) void print_star() { printf("*************"); return;//可以寫或不寫(盡量寫出來,代表要離開函數的地方) } ``` 再看一個例子 #### 目的 : ``` (1)我要得到兩個數的和(int函數) (2)我要得到兩個數的和(void函數) ``` ```c= ---------------以下是兩種同樣動作(小細節上是不一樣運作方式)-------------- // int 版本 int getSum(int a,int b) { return a + b; } // void 版本 // (上面int版本的另一種寫法)(這邊要等學完指標再來看) void getSum2(int *sum,int a,int b) { *sum = a + b; return; } int main() { int sum; int number1 = 10,number2 = 20; sum = getSum(number1,nubmer2); // 上下兩種寫法都是讓sum得到10+20的結果 // 上面寫法先學好,等到指標學完再來看下面的做法 getSum2(&sum,number1,nubmer2); } ``` ### [區域變數、全域變數] #### 區域變數: ``` 簡單來說,就是每個一般的變數都有他的生命,再int main()裡面宣告的變數, 只要main執行完畢,擬就拿不到那個變數了, 更進一步說一個for或while裡面宣告的變數, 只要再for或while執行完畢就會失去那些變數。 然而,這邊的主題是要說,再函數內宣告的參數, 其實是分配新的記憶體給那些參數,然後將傳入的值複製過去。 所以更改他的值不會對原本傳入的變數影響到。 ``` #### 全域變數: ##### (只要宣告的地方(不在任何函數內)就是全域變數) ``` 簡單來說,就是在int main()外宣告的變數, 可以再整個程式中任何一個地方使用那個變數的值。 #include <stdio.h> #include <stdlib.h> int number; //全域變數 int main () { return 0; } ``` ```c= [資料型態] [函數名稱](需傳入的參數) { 更改傳入參數的值 } ``` ### 舉例: #### 目的 : ``` (1)修改a的值(f1)(成功) (2)修改a的值(f2)(沒有成功) ``` ```c= int f1(int number) { number = number + 5; return number; } void f2(int number) { number = number + 5; return; } int main() { int a = 100; ans = f1(a); // 有回傳一個值給ans儲存; f2(a); // 沒有回傳 //雖然兩個都沒有更改到a的值, //但是一個是有得到修改後的105,另一個是沒有得到新的值,只有執行完函式而已 } ``` 再看一個類似的例子 #### 目的 : ``` (1)修改a的值(addfive1)(成功) (2)修改a的值(addfive2)(沒有成功) ``` ```c= int addfive1(int a) { a += 5; return a; } void addfive2(int a) { a += 5; } int main(void) { int a = 100,b = 100; int ans; addfive2(a); printf("a = %d\n",a); //結果式100因為更改的是在函式內的區域變數 a = addfive1(a); printf("a = %d\n",a); //結果式105因為更改的是在函式內的區域變數,但是他有回傳一個105給ans system("PAUSE"); return 0; } ``` ### 以下只示範簡易的函式、區域變數怎麼用,請自己試看看怎麼運用在題目唷!! ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int getSum(int a,int b) { return a + b; } int addfive1(int a) { a += 5; return a; } void addfive2(int a) { a += 5; } void printstar() { printf("*************\n"); } int main(void) { printstar(); int a = 100,b = 100; int ans = getSum(a,b); printf("ans = %d\n",ans); addfive2(a); ans = a; printf("ans = %d\n",ans); //結果式100因為更改的是在函式內的區域變數 ans = addfive1(a); printf("ans = %d\n",ans); //結果式105因為更改的是在函式內的區域變數,但是他有回傳一個105給ans printstar(); system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/FOC3YMM.png) ::: ### 練習題 :::info [NCHU 10037 連結](https://nchuoj.ee.nchu.edu.tw/problem/10037) ![](https://i.imgur.com/6UsTIMt.png) ![](https://i.imgur.com/zHiveV1.png) ::: --- ## 7. 陣列 --- **本章大綱** **1. 一維陣列宣告、輸入、輸出 2. 二維陣列宣告、輸入、輸出** --- ### 示範 (整數陣列) :::success 小知識 1-11 ### 一維陣列的宣告方式 ``` (資料型態) (變數名稱)[陣列長度] //陣列長度左右要有中括號 ``` 記憶體 ![](https://i.imgur.com/fC5yKpJ.png) ### 舉例: #### 目的: ``` 示範 (1)宣告 (2)輸入 (3)輸出 ``` ```c= int arr1[100]; // 宣告長度為100個整數的陣列 arr1 double arr2[100] // 宣告長度為100個浮點數的陣列 arr2 int i; //輸入陣列每一個值 for(i = 0 ; i < 100 ; i++) // 跑陣列長度 1~100 { scanf("%d",&arr1[i]); //輸入第 i 個值 } //輸出陣列每一個值 for(i = 0 ; i < 100 ; i++) // 跑陣列長度 1~100 { printf("%d",arr1[i]); //輸出第 i 個值 } ``` ### 二維陣列的宣告方式 ``` (資料型態) (變數名稱)[陣列寬度][陣列長度] //陣列寬度、陣列長度左右要有中括號 ``` 記憶體 ![](https://i.imgur.com/ixMT7Ro.png) 長方形 ![](https://i.imgur.com/tgAt847.png) ### 舉例: #### 目的: ``` 示範 (1)宣告 (2)輸入 (3)輸出 ``` ```c= int arr1[100][100]; // 宣告寬度為100、長度為100個整數的陣列 arr1 double arr2[100][100] // 宣告寬度為100、長度為100個浮點數的陣列 arr2 int i,j; //輸入陣列每一個值 for(i = 0 ; i < 100 ; i++) // 跑陣列寬度 1~100 { for(j = 0 ; j < 100 ; j++) // 跑陣列長度 1~100 { scanf("%d",&arr1[i][j]); //輸入第 i 個陣列中的第 j 個值 } } //輸出陣列每一個值 for(i = 0 ; i < 100 ; i++) // 跑陣列寬度 1~100 { for(j = 0 ; j < 100 ; j++) // 跑陣列長度 1~100 { printf("%d",arr1[i][j]); //輸出第 i 個陣列中的第 j 個值 } } ``` ### 以下只示範簡易的一維陣列怎麼用,請自己試看看怎麼運用在題目唷!! ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main(void) { //宣告一個長度為 100 的整數陣列 int a[100]; for(int i = 0 ; i < 100 ; i++)// 從陣列第 1 個跑到第 100 個 { a[i] = i;//每個都存 自己的index (ex: a[0] = 0 a[1] = 1 ......) } int sum = 0; for(int i = 0 ; i < 100 ; i++)// 從陣列第 1 個跑到第 100 個 { sum += a[i]; // 把陣列的每一個值加到總和裡 } printf("sum = %d\n",sum); //輸出陣列每一個值的總和 system("PAUSE"); return 0; } ``` **執行結果** ![](https://i.imgur.com/rRPOYOG.png) ::: ### 練習題 :::info [NCHU 10033 連結](https://nchuoj.ee.nchu.edu.tw/problem/10033) **題目 : 計算n個數字的總和(請使用陣列)** 給定一個 n (1 <= n <= 20) 接下來有 n 筆數字 請計算這 n 筆數字的總和,然後將它輸出。 ``` input_1: 10 1 2 3 4 5 6 7 8 9 10 output_1: sum = 55 ``` ``` input_2: 12 11 20 3 44 51 6 79 8 91 10 24 34 output_2: sum = 381 ``` ::: :::spoiler **題目程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { int number; scanf("%d",&number); int sum = 0,i; int c[number]; for(i = 0 ; i < number ; i++) { scanf("%d",&c[i]); } for(i = 0 ; i < number ; i++) { sum += c[i]; } printf("sum = %d",sum); } ``` **執行結果** ![](https://i.imgur.com/pjFWfaE.png) ::: --- ## 8. 指標 --- **本章大綱** **1. 指標宣告及取址和間接運算子 2. 指標存取陣列位址 3. 指標與陣列關係** --- ### 示範 (整數陣列 + 整數指標) :::success 小知識 1-12 ### 取址運算子(&) ``` printf(%#x,&a); //會輸出a的記憶體位置 ``` ### 間接運算子 (*) ``` int *p = &a; //讓p指標存取a的記憶體位置 printf(%#x,*p); // 透過*會讓p指向的記憶體位置(a)的值被取出來 // 也就是輸出 a 的值 ``` ### 指標的宣告方式 ``` [資料型態]* [指標名稱] ``` ### 指標的存取陣列的位址的方式 ``` [指標名稱] = &變數名稱 ``` ### 指標的宣告 + 存取陣列的位址的方式 ``` [資料型態]* [指標名稱] = &變數名稱 ``` ### 舉例: ```c= //宣告一個100個整數的陣列 和 1個指標 int arr[100]; int *ptr = arr; // 也可以寫 int *ptr = &arr[0]; //指向陣列arr的第一個位置 ``` ### 以下只示範簡易的指標怎麼用,請自己試看看他怎麼運用在題目!! ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> /* 示範 陣列 + 指標 + 雙重指標 三者之間的關係(上課只會用到 陣列 與 指標) */ int main(void) { int arr[5] = {1,2,3,4,5}; int *ptr1 = arr; int **ptr2 = &ptr1; printf("\n--------------------arr[0]----------------------\n\n"); printf("%10d = value of arr[0] = arr[0]\n",arr[0]); // 取 arr[0] 的值 //加上 & 代表取記憶體位址 printf("%#10x = address of arr[0] = &arr[0]\n",&arr[0]); // 取 arr[0] 的記憶體位置 printf("\n---------------------ptr1-----------------------\n\n"); printf("%#10x = value of ptr1 = ptr1\n",ptr1); // 取 arr[0] 的記憶體位置 //加上 * 代表取值(內容) printf("%10d = point of ptr1 = *ptr1\n",*ptr1); // 取 arr[0] 的記憶體位置的值 //加上 & 代表取記憶體位址 printf("%#10x = address of ptr1 = &ptr1\n",&ptr1); // 取 ptr1 的記憶體位置 printf("\n---------------------ptr2-----------------------\n\n"); printf("%#10x = value of ptr2 = ptr2\n",ptr2); // 取 ptr1 的記憶體位置 //加上 * 代表取值(內容) printf("%#10x = point of ptr2 = *ptr2\n",*ptr2); // 取 ptr1 的記憶體位置的值 //加上 ** 代表連續取值兩次 printf("%10d = point of point of ptr2 = **ptr2\n",**ptr2); // 取 ptr1 的記憶體位置的值(記憶體位址)的值 //加上 & 代表取記憶體位址 printf("%#10x = address of ptr2 = &ptr2\n",&ptr2); // 取 ptr2 的記憶體位置 printf("\n------------------------------------------------\n\n"); return 0; } ``` ```c= #include <stdio.h> #include <stdlib.h> /* 陣列 與 指標之間可以互相交換使用 */ int main(void) { //宣告一個100個整數的陣列 和 1個指標 int arr[100]; int *ptr = arr; // 也可以寫 int *ptr = &arr[0]; //指向陣列arr的第一個位置 for(int i = 0 ; i < 100 ; i++) //從第 1 個位置到第 100 個位置 { *(arr + i) = i; // 也可以寫 arr[i] = i; 或 *(ptr + i) = i; 或 ptr[i] = i; } int sum = 0; for(int i = 0 ; i < 100 ; i++) //從第 1 個位置到第 100 個位置 { sum += *(ptr + i); // 也可以寫 sum += ptr[i]; 或 sum += arr[i]; 或 sum += *(arr + i); } printf("sum = %d\n",sum); //輸出1 ~ 100的總和 system("PAUSE"); return 0; } ``` ::: ### 練習題 :::info **題目 : 計算n個數字的的總和(請使用指標)** 給定一個 n (1 <= n <= 20) 接下來有 n 筆數字 請計算這 n 筆數字的總和,然後將它輸出。 ``` input_1: 10 1 2 3 4 5 6 7 8 9 10 output_1: sum = 55 ``` ``` input_2: 12 11 20 3 44 51 6 79 8 91 10 24 34 output_2: sum = 381 ``` ::: :::spoiler **題目程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { int number; scanf("%d",&number); int sum = 0,i; int c[number]; int *ptr = &c[0]; for(i = 0 ; i < number ; i++) { scanf("%d",(ptr + i)); } for(i = 0 ; i < number ; i++) { sum += *(ptr + i); } printf("sum = %d",sum); } ``` **執行結果** ![](https://i.imgur.com/Ja2vuDq.png) ::: --- ## 9. 字串 --- **本章大綱** **1. 字串宣告方式** --- ### 示範 (字元陣列) :::success ### 字串的宣告方式 ``` char (變數名稱)[陣列長度] ``` ### 舉例: ```c= char arr[100]; // 宣告長度為100個字元陣列arr,也就是字串 scanf("%s",arr); // 當您輸入 abcd , // 在arr字元陣列(字串)當中儲存的內容為abcd\0,下兩行為內容示意。 // arr[0] arr[1] arr[2] arr[3] arr[4] arr[5] ... // a b c d \0 ------------------------------------------------------ char arr[100]; // 宣告長度為100個字元陣列arr,也就是字串 for(int i = 0 ; i < 4 ; i++) //輸入 4 個字元 (ex: abcd) { scanf("%c",&arr[i]); } // 在arr字元陣列(字串)當中儲存的內容為abcd,下兩行為內容示意。 // arr[0] arr[1] arr[2] arr[3] arr[4] arr[5] ... // a b c d // 這裡少了(\0)代表沒有結束字元(\0) printf("%s",arr) //%s沒有讀取到\0會造成輸出沒有明確停止的點 //可能輸出 (ex: abcd or abcdxxxxxx...) ``` ### 以下只示範簡易的字串怎麼用,請自己試看看他怎麼運用在題目!! ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> int main (void) { //宣告長度為10的字串 char str[10]; //輸入字串 printf("input string: "); scanf("%s",str); //輸出字串 printf("sum = %s\n",str); system("pause"); return 0; } ``` **執行結果** ![](https://i.imgur.com/cWsuyuY.png) ::: ### 練習題 :::info **題目 : 判斷檔案名稱是否含有副檔名.c** 每資料有一個檔案,要判斷他的副檔名是不是.c (檔案名稱長度 <= 100) ``` input_1: test.cpp output_1: no ``` ``` input_2: practice.c output_2: yes ``` ::: :::spoiler **題目程式碼** ```c= #include <stdio.h> #include <string.h> int main() { char name[105]; scanf("%s", name); if(name[strlen(name)-1] == 'c' && name[strlen(name)-2] == '.') { printf("yes"); } else { printf("no"); } system("pause"); return 0; } ``` **執行結果** ::: --- ## 10. 結構與聯集 --- **本章大綱** **1. struct結構 2. typedef關鍵字** --- ### 示範 (結構) :::success ### struct的宣告方式 ``` struct [結構名稱1]{ [資料型態1] [變數名稱1]; [資料型態2] [變數名稱2]; [資料型態3] [變數名稱3]; ... }(變數名稱); ``` 有兩種寫法,後面的變數可以宣告或不宣告。 ```c= struct person{ int id; int money; }; --------------------------- struct person{ int id; int money; }p1; // 宣告 1 個人為struct person資料型態 int main (void) { struct person a[5]; // 宣告5個人為struct person資料型態 } ``` 再來看一個更簡潔的方式。 可以將strcut [結構名稱1] 簡寫成 [結構名稱2] ``` typedef struct [結構名稱1]{ [資料型態1] [變數名稱1]; [資料型態2] [變數名稱2]; [資料型態3] [變數名稱3]; ... }[結構名稱2]; ``` 如此一來宣告的時候就可以用結構名稱2宣告變數,下方是他的例子。 ### 舉例: 宣告一個struct person為一結構資料型態,他的成員有整數型態的 id 和 money, 後面定義了[結構名稱2]為P。所以可以用P來宣告p1變數為struct person的結構資料型態。 ```c= typedef struct person{ int id; int money; }P; int main () { P p1; //宣告一個p1為struct person結構的資料 } ``` ### 以下只示範簡易的結構怎麼用,請自己試看看他怎麼運用在題目!! ::: :::spoiler **示範程式碼** ```c= #include <stdio.h> #include <stdlib.h> typedef struct person{ int id; int money; }P; int main (void) { P a[5]; // 宣告5個人為struct person資料型態 for(int i = 0 ; i < 5 ; i++) //輸入5個人的資料 { printf("input person %d id & money : ",i + 1); scanf("%d%d",&a[i].id,&a[i].money); } int sum = 0; for(int i = 0 ; i < 5 ; i++) //5個人的錢總合起來 { sum += a[i].money; } for(int i = 0 ; i < 5 ; i++) //輸出5個人的資料和錢的總和 { printf("person %d id : %d\n",i + 1,a[i].id); } printf("sum = %d\n",sum); system("pause"); return 0; } ``` **執行結果** ![](https://i.imgur.com/rJI9KKr.png) ::: ### 練習題 :::info **題目 : 計算n筆貨物的資料** 每筆貨物有id和price 請計算出每最貴的price貨物,然後輸出他的id。 (1 <= n <= 10) ``` input_1: 6 1 5 2 9 3 10 4 6 5 11 6 16 output_1: maxprice_id = 6 ``` ``` input_2: 10 1 100 2 90 3 102 4 60 5 110 6 106 7 290 8 400 9 160 10 195 output_2: maxprice_id = 8 ``` ::: :::spoiler **題目程式碼** ```c= #include <stdio.h> #include <stdlib.h> typedef struct object{ int id; int price; }O; void bubble_sort(O array[], int n){ for (int i=0; i<n-1; i++){ for (int j=0; j<n-i-1; j++){ if (array[j].price > array[j+1].price){ O temp1 = array[j]; array[j] = array[j+1]; array[j+1] = temp1; } } } } int main(){ int num; scanf("%d", &num); O obj[num]; for(int i = 0; i < num; i++){ scanf("%d%d", &obj[i].id, &obj[i].price); } bubble_sort(obj, num); printf("maxprice_id = %d", obj[num-1].id); system("pause"); return 0; } ``` **執行結果** ::: --- ## 11. 檔案(引用網路的文章) --- **本章大綱** **1. fopen開啟函式 2. fclose關閉函式 3. fputc寫入函式 4. fputs寫入函式 5. fgetc讀取函式 6. fgets讀取函式** --- ### 示範 (開啟/關閉、讀取/寫入檔案的功能) :::success ### 開啟檔案 您可以使用 fopen( ) 函式來建立一個新的檔案或者開啟一個已有的檔案,這個呼叫會初始化型別 FILE 的一個物件,型別 FILE 包含了所有用來控制流的必要的資訊。下面是這個函式呼叫的原型: #### FILE *fopen( const char * filename, const char * mode ); ``` 在這裡,filename 是字串,用來命名檔案,訪問模式 mode 的值可以是下列值中的一個: ``` ### 模式 描述 ```c= r 開啟一個已有的文字檔案,允許讀取檔案。 w 開啟一個文字檔案,允許寫入檔案。如果檔案不存在,則會建立一個新檔案。在這裡,您的程式會從檔案的開頭寫入內容。如果檔案存在,則該會被截斷為零長度,重新寫入。 a 開啟一個文字檔案,以追加模式寫入檔案。如果檔案不存在,則會建立一個新檔案。在這裡,您的程式會在已有的檔案內容中追加內容。 r+ 開啟一個文字檔案,允許讀寫檔案。 w+ 開啟一個文字檔案,允許讀寫檔案。如果檔案已存在,則檔案會被截斷為零長度,如果檔案不存在,則會建立一個新檔案。 a+ 開啟一個文字檔案,允許讀寫檔案。如果檔案不存在,則會建立一個新檔案。讀取會從檔案的開頭開始,寫入則只能是追加模式。 如果處理的是二進位制檔案,則需使用下面的訪問模式來取代上面的訪問模式: "rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b" ``` ### 關閉檔案 為了關閉檔案,請使用 fclose( ) 函式。函式的原型如下: #### int fclose( FILE *fp ); ``` 如果成功關閉檔案,fclose( ) 函式返回零,如果關閉檔案時發生錯誤, 函式返回 EOF。這個函式實際上,會清空緩衝區中的資料,關閉檔案, 並釋放用於該檔案的所有記憶體。EOF 是一個定義在標頭檔案 stdio.h 中的常量。 ``` C 標準庫提供了各種函式來按字元或者以固定長度字串的形式讀寫檔案。 ### 寫入檔案 下面是把字元寫入到流中的最簡單的函式: #### int fputc( int c, FILE *fp ); ``` 函式 fputc() 把引數 c 的字元值寫入到 fp 所指向的輸出流中。 如果寫入成功,它會返回寫入的字元,如果發生錯誤,則會返回 EOF。 ``` 您可以使用下面的函式來把一個以 null 結尾的字串寫入到流中: #### int fputs( const char *s, FILE *fp ); ``` 函式 fputs() 把字串 s 寫入到 fp 所指向的輸出流中。 如果寫入成功,它會返回一個非負值,如果發生錯誤,則會返回 EOF。 您也可以使用 int fprintf(FILE *fp,const char *format, ...) 函式把一個字串寫入到檔案中。 ``` ```c= #include <stdio.h> int main() { FILE *fp = NULL; fp = fopen("test.txt", "w+"); fprintf(fp, "This is testing for fprintf...\n"); fputs("This is testing for fputs...\n", fp); fclose(fp); } ``` 當上面的程式碼被編譯和執行時,它會在目錄中建立一個新的檔案 test.txt,並使用兩個不同的函式寫入兩行。接下來讓我們來讀取這個檔案。 ### 讀取檔案 下面是從檔案讀取單個字元的最簡單的函式: #### int fgetc( FILE * fp ); ``` fgetc() 函式從 fp 所指向的輸入檔案中讀取一個字元。 返回值是讀取的字元,如果發生錯誤則返回 EOF。 ``` 下面的函式允許您從流中讀取一個字串: #### char *fgets( char *buf, int n, FILE *fp ); ``` 函式 fgets() 從 fp 所指向的輸入流中讀取 n - 1 個字元。 它會把讀取的字串複製到緩衝區 buf,並在最後追加一個 null 字元來終止字串。 如果這個函式在讀取最後一個字元之前就遇到一個換行符 '\n' 或檔案的末尾 EOF, 則只會返回讀取到的字元,包括換行符。 您也可以使用 int fscanf(FILE *fp, const char *format, ...) 函式來從檔案中讀取字串, 但是在遇到第一個空格和換行符時,它會停止讀取。 ``` ```c= #include <stdio.h> int main() { FILE *fp = NULL; char buff[255]; fp = fopen("/tmp/test.txt", "r"); fscanf(fp, "%s", buff); printf("1: %s\n", buff ); fgets(buff, 255, (FILE*)fp); printf("2: %s\n", buff ); fgets(buff, 255, (FILE*)fp); printf("3: %s\n", buff ); fclose(fp); } ``` 當上面的程式碼被編譯和執行時,它會讀取上一部分建立的檔案,產生下列結果: ``` 1: This 2: is testing for fprintf... 3: This is testing for fputs... ``` ::: --- ## 12.程式解題入門 [入門篇(一)](https://hackmd.io/@asddzxcc1857/code_teaching001) ---