---
# System prepended metadata

title: 學習筆記

---

# 學習筆記

# 函式
使用函數的目的，**利用模組化來簡化主程式**

---
**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

---


