1. 程式人生 > 實用技巧 >C語言一些筆記

C語言一些筆記

常用標頭檔案

math.h

常用函式

abs();		// 求絕對值  返回值int
sqrt();		// 求平方根  返回值double
sin()

stdio.h

printf();
scanf();
getc();

string.h

strlen();
strcpy();
strcmp();

無符號型別

unsigned

浮點數問題

浮點數無法精確儲存的原因

一個單精度的變數只能保證有效數位是7位。7位後面的數字是無意義的,並不準確表示該數

在C語言中儘量避免將一個很大的數和很小的數直接相加或相減,否則會丟失小數

輸出控制符

  • \t:製表符,輸出8個空格
  • \r:跳到一行初始位置

char型別的八進位制

char c = '\729';   // 錯誤的程式碼,以\開頭的是八進位制,而八進位制不能有9

%m.n問題

scanf()的問題

scanf("%2d %*3d %d", &a, &b);

如果輸入以下資訊:

12 345 67

系統會將12賦給a,在%*3d表示讀入3位整數,但不賦值給任何變數,所以跳過345,將67給b

switch

switchcase常量表達式只能是整數型別、字元型;

case只能是常量表達式

二維陣列

int a[3][4] = {0};   // 陣列的初始化,每個元素都為0
int a[][4] = {1, 2, 3, ...};  // 合法的,可以這麼玩

字元陣列

可以理解為字串,C語言中沒有字串型別,但是可以是字元陣列來模擬。

因此,每個字元陣列的最後一位是\0

字串的初始化

char ch[10] = {"xxx"};
char ch[] = "xxx";  // 和上面一樣都是等價的

// 只不過這樣的話,系統會自動在最後面加\0

字元陣列與printf應用

char * p = "%d %d"; 
int a = 10, b = 20;
printf(p, a, b);

字元處理函式

puts(str); // 將一個以'\0'結束的字串輸出的終端

gets(str); // 從終端輸入字串到str並返回str首地址

strcat(str1, str2); // 把str2中字串追加到str1後面,並刪除str1後的'\0'字元,並返回str1的首地址

strcpy(str1, str2); // 將str2中字元拷貝的str1中,最後的'\0'也會拷貝。前提是str1必須可以裝下str2
strcpy(str1, str2, size); // 將str2裝入str1中,指定複製的長度size

strcmp(str1, str2); // 按ASCII碼從左到右逐個比較字串內容,直到出現'\0',然後返回結構
	str1 == str2  返回值==0
    str1 > str2   返回值>0
    str1 < str2   返回值<0
        
strlen(str); //返回str的長度,不包括字串結束符'\0'

strlwr(str); // 將字串中大寫字母轉換為小寫字母
strupr(str); // 將字串中小寫字元轉換為大寫字母
    

變數修飾符

auto    : 定義變數預設就是這個
static  : 定義靜態變數
register: 使用該關鍵字,變數會存放在暫存器裡,有效提高運算速度
extern  : 外部變數,放在靜態儲存區,意思就是說別的.c檔案可以使用 預設函式就是該型別

巨集定義

無參

#define 巨集名 字串(常數,表示式)

在使用的時候,當編譯器掃描到巨集時,會直接替換

有引數

#define 巨集名(引數表) 字串
#define ADD(X, Y) (X+Y)
使用
int sum = ADD(5, 10);  展開後 int sum = (5, 10); // 注意替換的時候會有括號的,因為在定義時候就有括號

標頭檔案

<>:到存放C庫函式的標頭檔案所在目錄

"":現在當前目錄找,找不到時,回去C庫函式所在目錄找

條件編譯

滿足條件編譯,不滿足不編譯;條件編譯作用:直接在語法檢查的時候判斷是否編譯

使用格式一

#ifdef 識別符號
	程式段1
#endif

格式二:

#ifdef 識別符號
	程式段1
#else
    程式段2
#end

格式三:

#if 常量表達式
	程式段1
#else
    程式段2
#endif

函式指標

格式:
型別說明符   (* 指標名)();

型別說明符:函式返回型別
() 表示是一個函式指標

指標陣列

int * a[5]; 存放地址的陣列

陣列指標

指向陣列的指標
int (*pl)[5];

陣列關於陣列名和&陣列名

&a+1:是加整個陣列的大小

&a[0] + 1:是一個元素的大小

逗號表示式

int a = (2, 3, 4);
// 先計算左邊的運算元,再計算右邊的運算元
// 右邊的運算元的型別的值作為整個表示式的結果

scanf()問題

如果在scanf()中有非輸入控制符,要原樣輸入

如:

scanf("m%d", &a); // 要想使用先輸入m,再輸入要給a的值

三目運算子

格式:A?B:C
等價於
if(A)
    B;
else 
    C;

資料型別

intlong intshort intcharfloatdouble

位運算

運算子 操作 優先順序
~ 按位取反 1
<< 左移 2
>> 右移 2
& 按位與 3
^ 按位異或 4
| 按位或 5

注意事項:

  1. ~的運算運算元是1個,其餘都是兩個

  2. 可以與賦值結合

    <<=>>=&=^=|=

  3. 異或運算,相同為1,不同為0

<<左移

運算元直接左移,高位丟掉,低位補0

>>右移

如果無符號右移,空位直接補0

如果是有符號右移,

  1. 如果是正數,右移補0
  2. 如果是負數,
    • 左邊補1,稱為算數右移【實際上是使用這個】
    • 左邊補0,稱為邏輯右移

動態記憶體

malloc(size); // 在記憶體申請開闢長度為size的連續空間
calloc(n, size); // 在記憶體範圍n個長度為size的連續空間,函式返回初始地址,若分配失敗則返回NULL
free(p); 釋放p指向的記憶體

共用體

union 共用體名
{
    資料型別1 成員1;
    陣列型別2 成員2;
    ...
}

為共用體變數分為空間大小是以所有成員中佔用空間位元組數最大的成員為標準

如:

union Myunion
{
    int age;
    char names[20];
}
sizeof(union Myunion) == 20

共用體的初始化

  1. 只能對第一個成員初始化
  2. 共用體在使用的時候,會只保留最後一次對成員賦值的值

與結構體不同的是

  1. 只按空間最大的成員來分配空間
  2. 在同一時刻,只存放一個成員的值

列舉

enum 列舉名
{
    列舉元素
    ...    
}

typedef

typedef 起別名
typedef int Num[100];
Num a; // 那麼a就是一個數組,且元素有100個

檔案

輸入:資料從檔案到記憶體

輸出:資料從記憶體到檔案

檔案分類

按儲存介質分

  • 普通檔案
  • 裝置檔案:鍵盤、滑鼠

按資料組織分

  • 文字檔案:ASCII碼檔案
  • 二進位制檔案

C語言中檔案的操作型別FILE是C為我們定義好的檔案結構體

FILE * fp1, *fp2, *fp3;

檔案常用函式

fopen(); 開啟檔案
fclose(); 關閉檔案

系統自動開啟和關閉的三個標準檔案

標註輸入 --- 鍵盤 stdin

標準輸出 --- 顯示器 stdout

標出錯輸出 --- 顯示器 stdern

fopen作用

  1. 建立檔案資訊區
  2. 建立檔案緩衝區
FILE * fopen(char * name, char * mode);
name: 檔案路徑
mode: 開啟檔案方式
返回值:如果正常開啟檔案會返回檔案結構體地址,反之返回NULL

檔案的開啟方式

r 開啟檔案必須存在,且每次都會覆蓋 讀
w 沒有檔案立刻建立;有檔案覆蓋該檔案 寫
rb 二進位制
wb 二進位制
a 向檔案末尾新增新的資料,且檔案必須存在
ab 二進位制
r+ 既讀既寫,檔案必須存在
w+ 新建一個檔案,既讀既寫
a+ 原始檔不刪除,末尾新增資料,既讀既寫
rb+
ab+
wb+

文字檔案:回車 轉換為 換行符

二進位制檔案:不會轉換

讀寫函式-字元

讀取字元

  • fgetc(fp):從fp指向檔案讀入一個字元並返回,讀成功返回。讀失敗返回EOF-1
  • fputc(ch, fp):把字元ch寫到檔案指標變數,所指向的檔案中
    • 寫成功:返回輸出字元
    • 寫失敗:返回EOF-1
  • feof():對於二進位制檔案讀取時判斷檔案是否結束,返回值檔案結束為1,否則為0

讀取字串

  • fgets(str, n, fp):從fp檔案讀入長度為(n-1)的字串,存入str陣列中
    • 返回值:
      • 成功返回str首地址
      • 失敗返回NULL
    • 讀完n-1之前遇到\nEOF字元,讀入既結束,但也將\n按字元讀入
  • fputs(str, fp)str所指向的字元陣列寫入檔案中
    • 返回值:
      • 成功返回0
      • 失敗返回非零

讀寫函式-二進位制

  • fread(buffer, size, count, fp)
  • fwrite(buffer, size, count, fp)
    • buffer:要讀/寫首地址
    • szie:要讀/寫檔案大小(長度)
    • count:要讀/寫資料塊的個數
    • fp:檔案指標

隨機讀寫

  • rewind(fp):讓檔案指標重新指向檔案開頭
  • fseek(fp, 位偏移, 起始點)
    • 起始點:0:檔案開始位置;1:當前位置;2:檔案末尾
    • 位偏移:long型別加L
fseek(fp, 100L, 0); // 檔案開始偏移100個位元組
fseek(fp, -10L, 2); // 檔案末尾往前偏移10個位元組
  • ftell():獲取檔案標記當前指向的位置
  • ferror(fp):檔案讀寫的出錯檢測,0是沒有出錯,非0是出錯;每次讀寫時都會有新的ferror()函式
  • clearerr():使檔案錯誤標誌和檔案結束標誌為0

二進位制讀寫2個位元組

putw

getw

ASCII碼錶

優先順序表

https://blog.csdn.net/changexhao/article/details/82556761