課程內容#
C 語言概述#
- 為什麼要學 C 語言?
匯編語言 | C 語言(編譯型語言、高級語言) |
---|---|
強依賴於硬體設備 - 寄存器 | 可移植性 |
直接與寄存器等溝通,代碼複雜,效率更高 | 簡單、可讀、開發效率高 |
舉例:想與外國人交流 | |
學英語 | 找翻譯 |
-
C 的重要性
- 先有 C,再有 Linux
- 操作系統 Unix 收費,所以有 Linux,李納斯開發的
- Linux 底層是用 C 語言實現的
- Java、C++、Python 底層都是 C
PS:Mac OS 是基於 Unix 的
- 先有 C,再有 Linux
-
學習思維邏輯、編程範式
- 而不僅僅是語法
- C 語言只支持一種:面向過程
- C++ 支持四種:面向過程、面向對象、泛型編程、函數式編程
輸入與輸出函數#
類比人的聽、說
- 輸出函數:printf
頭文件 | stdio.h | |
---|---|---|
⭐原型 | int printf(const char *format, ...); | 輸出的都是字符 |
返回值,int,成功輸出的字符數 | '\n' 是一個字符 | |
參數 1,format,格式控制字符串 | ||
可變參數列表,... | 合法語句,可以通過編譯 |
- 輸入函數:scanf
頭文件 | stdio.h | |
---|---|---|
⭐原型 | int scanf(const char *format, ...); | |
返回值,int,成功讀入的參數個數 | <0,不合法;≥0,合法(包括 0) | |
while(scanf(...) != EOF) | -1 <=> EOF (隱藏的文件描述符) |
- 鍵盤輸入文件結束符 EOF:
-
- Unix:Ctrl+D
-
- Windows:Ctrl+Z
-
- 也可以使用 Ctrl+C 中斷循環
C 語言文檔與編碼規範#
-
利用維基百科查看函數
-
cpp reference 權威文檔
- 可參考海賊寶藏官網
-
編碼規範(more code, more bug)谷歌是爸爸
- 百度 + 谷歌
- 阿里 + 谷歌
- 降低 bug 率
-
工具書(1 個月足矣;該書為跨界編寫)
-
隨堂練習#
-
- 不用 while 函數,可以直接使用 printf 的返回值
- printf () 嵌套
- 代碼

- %[^\n]s
// 目的:
char str[100] ={0};
scanf ("% s", str); // 遇到空格等分隔符就會進入下一個參數的賦值
scanf ("%[^\n] s", str); // 可以把空格當做字符讀取,[] 後的 s 可有可無
|[]| 字符匹配集 |
|:----:|:----|:----:|:----|
|^| 取非 / 除了 |
|\n | 換行符 |
- 當循環讀入時,會有問題
while (scanf("%[^\n]s", str) != EOF) {
...
}
- 輸入 Hello World,輸出不會停止,一直循環輸出 Hello World
- 因為 \n 被當做分隔符進入下一個參數的賦值,但 \n 不會被吞掉
- 參考開課吧 QA--10 月 13 號 C 語言課程有關 scanf 的問題:之所以會卡在 '\n' 是因為 %[] 不能吃掉前導空白符
自己的理解思路,與上面有點出入
-
將 scanf 的輸出顯示,可以看到只有第一次成功讀入了 1 個參數,後面全是 0
-
-
按照我的理解,\n 如果在正則裡被【取非】了後,就無法把 \n 讀進去了,但是會當成分隔符,所以進入輸出語句,但一直讀不進,所以又卡在那循環讀入;
-
而沒有正則的時候,\n 被當做分隔符讀入,且繼續讀取下一個字符,所以停止了,只是遇到空格就會進入到下一個參數的賦值。
-
-
使用 getchar (),可以吞掉一個字符,比如 \n
- 打印 getchar () 的值,可以發現吞掉的是 \n,這樣繼續讀取下一行了
-
-
紅框為輸出被吞掉的字符:\n,可見下圖代碼的 15~20 行
-
也許也可以通過循環讀取 char 的方式來讀取包含空格的字符串,使用二維字符數組,遇到 \n 就進入下一行。
-
另一個角度的思考,參考scanf 中的 \n 問題-CSDN
-
代碼
-
亮點筆記#
- scanf 利用分隔符(空格、換行等)來分隔幾個變量輸入
- 赋值運算符(=,-= 等)的優先級很低(結合方向:右到左),低於 == 運算符
- 赋值運算符形成的表達式的值就是所賦的值
int ret;
printf("%d\n", ret = 3);
// 輸出 3
-
./a.out > output 可以將輸出放在 output 文件裡(覆蓋原文件),而不顯示在終端
- > 的含義是標準輸出重定向
-
vim 基本操作,可進行 vimtutor 練習,見石墨文檔 -Linux 下常用命令:Vim
-
printf () 的格式控制字符串中,如果不用 \n,末尾有個 %
- 這個百分號是 shell 給你加的,因為你自己沒有輸入換行。
想想如果你沒輸入換行的話,shell 後面的那個提示符它是不是應該緊接著你的輸出 (如 hello word) 去寫,顯得亂
- 注意:% c 慎用,什麼都會讀進去
代碼演示#
printf 函數#
printf 家族基礎知識#
- printf:打印到標準輸出(stdout)
- spirnf:打印到字符串(string)
- 可用於字符串拼接
- sprintf(str, "", ...);
- fprintf:打印到文件中(file)
- 先打開文件,fopen:w 寫,r 讀,a 追加
- 返回 FILE 類型的指針
- fprintf (FILE 指針,"", ...);
- “...”:讀變參列表變量的地址
- 字符串變量本身傳的就是其首地址
- 先打開文件,fopen:w 寫,r 讀,a 追加

int main()
{
FILE* fp;
int i = 617;
char* s = "that is a good new";
fp = fopen("text.dat", "w");
fprintf (fp, "% d\n", i); // 傳變量名即可,不用傳地址
fprintf(fp, "%s", s);
fclose (fp); // 記得與 fclose 呼應,關閉文件
return 0;
}
練習#
- 根據 n 的末尾三位二進制的值,給 str 分別加不同類型的括號
-
-
n 的定義在 printf 開頭部分
-
使用宏定義方式定義 swap 函數
-
-
__typeof 獲取變量類型,直接用來聲明中間變量的類型
-
sprintf 的兩個參數不能一樣?
- 💡名字不能一樣?
- 如果前後參數都用 str,見下:
- 💡名字不能一樣?
-
-
結果如下:其中,() 裡的值長度與原值一樣,輸出的內容 ()似乎會覆蓋原來的內容
- 一定要用指針的方式傳地址?
- 如果直接使用變量,可以,見下:
-
-
-
-
- 但是有多個條件判斷,琢磨琢磨不用指針的話,交換字符數組好弄嗎???
- ❓其實字符數組的變量名代表的就是字符數組首地址,可以直接交換地址?失敗告終,應該是不行的,畢竟數組怎麼會輕易移動,但可以移動指向數組的指針
- 所以還是學會用指針~
- fprintf 的 FILE 指針也可以是 stdout 和 stderr
- 但是有多個條件判斷,琢磨琢磨不用指針的話,交換字符數組好弄嗎???
-
-
-
- 最後輸出如下:
-
-
-
- stdout 和 stderr 有什麼區別呢?
- 可以使用 > 將標準輸出 stdout重定向,對於 stderr 不會重定向,見下:
- stdout 和 stderr 有什麼區別呢?
-
⭐:可以單獨看 error 信息,而屏蔽掉大量的正常輸出
-
-
-
- 同樣,也可以使用 2> 只將錯誤輸出重定向,見下:
-
-
附加知識點#
- 文件描述符
- stdin:標準輸入處
- stdout:標準輸出處
- stderr:標準錯誤輸出處
- EOF:-1
- 文件權限
- Linux 中一切皆文件~
- ls -al .:可顯示文件權限
- rwx 可讀可寫可執行
- 數組初始化的三種常用方法({0}, memset, for 循環賦值)-CSDN
思考點#
- 為什麼 scanf 中參數列表要傳地址?
- scanf 需要修改參數的值,如果傳值的話,將無法改變其值