# 學習筆記 # 函式 使用函數的目的,**利用模組化來簡化主程式** --- **num( )函數原型的宣告格式:** ``` 函數名稱 函數不須有引數傳入 | | void num (void); | 函數沒傳回值 ``` **num( )函數的定義格式:** ``` void num(void) { printf("....."); return; } ``` --- **add( )函數的原型宣告:** ``` 傳回值型態是整數 | int ass(int,int); | | 函數名稱 有兩個引數傳入add()函數,型態均為int ``` **add( )函數的定義格式:** ``` int add(int num1,int num2) { int sum; sum=num1+num2; return sum; } ``` --- # 指標 1 資料的地址就是指標 `int b=2;` 以上面的程式碼為例,在宣告好變數、程式開始執行後,會去記憶體中要一塊儲存空間,然後把 2 這個資料丟進去。 想像記憶體是一個大櫃子,每一格都有相對應的位址,2 的位址就在記憶體中的某個地方 一個格子= 1 byte ---- # 指標變數 **指標**:某變數的位址 **指標變數**:用來存放指標的變數 舉例: ``` int *n; int b; int 2; n=&b; ``` --- **int * n ;** 這個的意思是,跟記憶體要一塊區域稱為n,這塊區域專門放指向int型變數的指標(位址) **int b ;** 這個的意思是,跟記憶體要一塊區域稱為 b,這塊區域專門放 int 型變數 **b=2 ;** 這個的意思是,把 2 這個值給變數 b **n=&b ;** 這個的意思是,把變數 b 的地址值給 n (&的意思是,取得變數在記憶體中被配置的位址) --- # 使用void型別的指位器 --- 指位器只能指向同型別的變數位址,舉例: ``` char *n; int y=3; n=&y; ``` 這個是錯誤的,因為字元型別的指位器只能指向字元型別的指標 如果要讓指位器指向不同型別的指標,可以宣告 void 型別的指位器,舉例: ``` void *box; int i= 1; box=&i; printf("%d ",* ( int* ) box ) ``` 將 box 由 (void*) 型別轉型為(int*)型別,再用 * 取值 --- # 陣列和指位器 --- ``` int number[3]; int *box=&number[0]; *(box)=0; //number[0]=0; *(box+1)=10; //number[1]=10; *(box+2)=20; //number[2]=20; ``` 因此,可以發現指位器材和陣列非常相似,所以也可以說「 陣列變數就是指位器 」,舉例: ``` int arr[10]={0}; int *ptr=arr; //不必使用 &,因為 arr 本身就是指位器,其值就是陣列存放的地址 int arr[10]={0}; *(arr)=0; //arr[0]=0; *(arr+1)=1;//arr[1]=1; ``` ---- # 動態記憶體配置 --- 動態記憶體配置是什麼呢?在這之前先來了解 什麼是靜態記憶體配置: 像是定義整數或字元、陣列都是靜態,也就是說開始執行程式時,就已經預備好所要用到的空間,就算臨時想更改空間大小也不行。 而動態記憶體配置就能解決「 臨時 」要更改空間大小的窘境,文言一點,就是「當程式執行到一半,發現它需要一塊記憶體空間來存放資料,才向系統索取一塊沒有被其他程式使用的記憶體空間。」 向系統索取記憶體區塊主要透過 malloc( )函式來做,使用到的標頭檔是 stdlib.h 語法使用: `( 資料型別 * ) malloc ( sizeof ( 資料型別 ) * 個數);` 資料型別:新配置空間的型別 個數:新配置多少型別的變數空間 舉例: ``` int *box=( int * ) malloc ( sizeof ( int ) * 10 ) ; 動態配置 10 個 int 型別的記憶體空間,配置成功後,使用 box 時,就像使用 box [ 10 ]一樣,可以在其中任意儲存資料 ``` 動態配置的空間使用完畢後,必須用free( )函式將配置的記憶體釋放 舉例:將box給釋放 : `free ( box );` 完整動作: ``` int *box ; . . . box= ( int * ) malloc ( sizeof ( int ) * 10 ) ; . . . free( box ) ; ``` --- # 字串 --- 字串和字元的差別:差在記憶體所佔的空間 字串: "c" => 'c' \0 佔 2 bytes 字元: ’c’ => 'c' 佔 1 byte --- **\0 是什麼呢?** 它是在 C 語言中,處理各種字串時,就是以 \0 作為結束字元來1判斷字串的1結尾 --- **宣告字串:** `char 字串名稱 [ 陣列容量 ] = ”字串內容 ”;` --- **陣列容量:** * 通常會依初始值設定的字串長度( 字元數 + 1 )來設定陣列容量 * 由“ 標準輸入”輸入字串 * 標準輸入:在電腦上就是鍵盤 可使用 scanf 配合 %s 的格式,或者呼叫 gets ( ) 函式 舉例: ``` char str1 [ 64 ]={0} ; char str2 [ 64 ]={0} ; scanf ( " %s" ,str1 ) ; // 將標準輸入的字串存到 str1 陣列 gets ( str2 ) ; // 將標準輸入的字串存到 str2 陣列 ``` scanf 和 gets 的差別:差在遇到空白字元時處理的方式不同 **scanf ( )** 函式取得輸入時,遇到空白字元時,就視為字串結束,所以空白字元後還有東西,也不會被讀到 **gets ( )** 函式取得輸入時,不會視空白字元為字串結束,而是必須明確出現換行字元( 例如Enter 鍵 )或檔案結束字元,才會視為結束字串 --- # 計算字串的長度: --- * strlen ( 字串 ) 函式 * 標頭檔 string.h --- **字串複製:如果想將字串a的內容給字串b,可以用這個方式進行,舉例:** ``` char * strcpy ( 目的陣列 ,來源陣列 ) ; // strcpy會將來源陣列的內容“ 複製 ”到目的陣列 ``` 但是,如果“ 來源陣列 ”的字串內容超過“ 目的陣列 ”的容量限制的話,程式會出錯 所以,如果只想複製來源陣列裡其中的部分到目的陣列的話,可以用這個,舉例: `char * strncpy ( 目的陣列 ,來源陣列 ,複製字元數 ) ;` --- # 字串比對 --- strcmp ( ) 函式可以用來比對兩個字串的內容 舉例: `int strcmp ( 字串1 , 字串2 ) ;` strncmp ( ) 跟 strcmp ( ) 一樣都是比對字串,差別在它是可以指定字串的第幾個字元比較 舉例: `strncmp ( 字串1, 字串2, 比對字元數 )` --- # 字串串接 --- strcat ( ) 將兩個字串進行串接 舉例: `char * strcat(目的陣列 , 來源陣列);` 假設來源陣列 :djsls ,目的陣列 :kdmkmr 會變成: kdmkmrdjsls strncat() 跟 strcat() 很像,差在它可以指定來源陣列中,最前面的字元數量 舉例: // `char * strncat(目的陣列 , 來源陣列, 串接字元數);` ``` char box_1[] = "jscd" ; char box_2[] = "jdcns" ; strncat (box_1, box_2, 2) ; ``` 會變成 :jscdjd --- # 字串轉換 --- **字串轉整數** `int atoi(字串)` 記得,它只是將字串裡的數字轉成整數型別的整數喔,像是:"123" 只要一遇到非數字就會停止,如果都是非數字的話,傳回 0 **字串轉浮點數** `double atof(字串)` 記得,atof()的傳回值為 double 型別,跟 atoi()很像,一樣遇到不是 '.' 或 'e' 或 'E' 的話,就停止。如果都是不是浮點樹相關的字元,傳回 0.0 ---