二維陣列 字串 指標
IOS學習第12天
二維陣列
- 二維陣列在記憶體中的儲存
1.二維陣列在記憶體中也是”從高到低申請連續記憶體的”,一共有行 * 列 * sizeof(單個元素的資料型別)
2.第0行是在”低”位元組
- 二維陣列的地址和行列計算
1.二維陣列的地址 == 二維陣列名 == 二維陣列的低地址 == 二維陣列中第0行的地址 == 二維陣列中第0行第0個元素地址
== 二維陣列第0行的低位元組地址
2.二維陣列的長度以及行列計算
長度:二維陣列的總位元組數 / 單個元素的位元組數
sizeof(二維陣列名) / sizeof(單個元素的位元組數)
行數:二維陣列的總位元組數 / 每一行的位元組數
sizeof(二維陣列名) / sizeof(二維陣列名[0])
列數:每一行的位元組數 / 單個元素的位元組數
sizeof(二維陣列名[0]) / sizeof(單個元素的位元組數)
- 二維陣列與函式
1.當二維陣列作為函式的引數的時候,會丟失這個二維陣列的行數和列數
2.當而為駐足作為函式的引數的時候,行數可以省略,要保證實參二維陣列的列數必須要和形參二維陣列的列數相同
3.寫引數的時候,可以先寫行數和列數,最後再寫二維陣列,然後二維陣列的列數用引數的列數來決定
void fuZhi(int row,int col,int nums[][col])
{
//函式體:給nums這個陣列中的每一個元素賦值
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
//nums[i][j]
nums[i][j] = i*j+10;
}
// printf("\n");
}
}
字串
- 原理
將字串資料的每1個字元儲存到字元資料中,並在後面追加1個’\0’來表示儲存完畢
- 格式
1>最基本的方式:
char name[10] = {'a','b','c','\0'};
2 >最簡單的方式:
char name[30] = {"abc"};//看成 字串 "abc" 是四個字元 分別是'a''b''c''\0'
字串可見長度:3
字串實際長度:4
陣列的長度: 30
一般來說 如果問 一個字串的長度是多少?那麼就是指的 實際長度
3>最常用的方式:
char name[] = "abc";
"字串可以看成一個字元陣列 "abcd"
"但是 字元陣列 不一定是字串
char name[4];
name[0] = 'a';
name[1] = 'b';
name[2] = 'c';
name[3] = 'd';
一個小題:
char name[20] = {'j','a','c','k'}; 可以看成字串 "jack"
char name[20] = {'j','a','\0','k'}; 可以看成字串 "ja"
char name[10];
name[0] = 'j';
name[1] = 'a';
name[2] = 'c';
name[3] = 'k';
不能,因為k後面雖然後字元,但是不一定是'\0'
char name[4] = {'j','a','c','k'};不能,末尾沒有'\0'
char name[4] = {"jack"}; 不能,末尾的'\0'已經超出了陣列範圍
```
* 使用字元陣列儲存字串注意的地方
1.如果沒有指定的長度,給陣列賦值一個字串的時候,那麼陣列的長度是字串的可見長度+1
2.如果指定的字元陣列的長度小於等於了字串的長度,這個時候就會有問題
3.C語言中一箇中文字元佔3個位元組
* 使用%s輸出儲存在字元陣列中的字元資料
使用%s格式控制符,就可以輸出儲存在字元陣列中的字串資料
原理:從給定的地址開始,1個位元組1個位元組的輸出,指導遇到'\0'為止
缺點:
1.如果你要列印的字串中間有'\0',那麼只會列印'\0'前面的部分
2.輸入的字串中間不能有空格,如果有空格,只能儲存"空格"之前的字串
* 字串長度的計算
int len = 0;
char str[] = “aasdladjkwe”
while(str[len] != ‘\0’)
{
len++;
}
printf(“字串的長度為”)
* 與字串相關的函式
| 函式名 | 引數 | 作用 |
| -- | -- | -- |
| puts() | const char * | 輸出字串 |
| gets() | char * | 控制檯獲取輸入的字串 |
|strlen() | const char * | 計算字串的可見長度 |
| strcmp() | const char *, const char * | 比較兩個字串的大小 |
| strcpy()| char *, const char *| 拷貝字串 |
| strcat() | char *, const char * | 連線兩個字元陣列 |
### 指標
* 指標變數的宣告
1.什麼叫指標變數
一個變數,用來儲存另外一個變數的地址
如果一個指標變數p 儲存了 另外一個變數num的地址
那麼我們稱 這個指標變數 指向了 num變數
儲存了誰的地址 就指向了誰
2.指標變數有啥用?
可以通過指標變數,間接 訪問/修改/獲取 它所指向的變數中資料
3.如何宣告一個指標變數?**
語法:資料型別 * 指標變數名
int * p1;定義了一個指標變數 變數名叫p1,說明這個p1變數 能存int型別變數的地址
4.不同型別的指標變數,儲存對應型別的變數的地址
* 指標變數的初始化
1.什麼叫指標變數
一個變數,用來儲存另外一個變數的地址
如果一個指標變數p 儲存了 另外一個變數num的地址
那麼我們稱 這個指標變數 指向了 num變數
儲存了誰的地址 就指向了誰
2.指標變數有啥用?
可以通過指標變數,間接 訪問/修改/獲取 它所指向的變數中資料
3.如何宣告一個指標變數?**
語法:資料型別 * 指標變數名
int * p1;定義了一個指標變數 變數名叫p1,說明這個p1變數 能存int型別變數的地址
4.不同型別的指標變數,儲存對應型別的變數的地址
* 指標變數的使用
1.如何 使用指標變數 操作它所指向的變數的資料
int num = 10;
int *p_num = #//這裡的*代表 p_num是一個指標變數
通過p_num指標間接操作指標指向的變數
*p_num; //這裡的*代表 解析地址 解析出來就是num變數
列印:printf("%d",*p_num);
賦值:*p_num = 200;
* 野指標
.什麼是野指標:
亂指的指標,指標變數中儲存的值 是一個垃圾值
int num;//垃圾值
int * p_num;//垃圾地址
這個指標就是野指標
定義一個指標 但是沒有給他賦初始值,那麼這個指標就是野指標
2.定義一個野指標
int *p_num;
*p_num = 50;//非法操作
野指標 如果隨便訪問 那麼會遇到 難以預料問題
“`
* NULL值
1.
int num = 0;//定義一個變數 如果不知道初始值,給他賦值一個0
int *p_num = NULL;//如果定義一個變數,不知道初始值是什麼,那麼我們會給他一個預設值 NULL
*p_num = 50;//會 100%報錯
2.如果1個指標變數的值是NULL值.這個時候通過指標變數去訪問指向的變數的時候 100%報錯.(沒有意義)
結論: 只要是申明瞭一個指標 不知道初始值
那麼 我們這麼幹 int *p_num = NULL;
```
* 多個指標指向同一個變數
int num = 10;
int* p1 = #
int* p2 = p1;p1和p2指標都指向了num變數.
2.練習:
int num1 = 10;//num1 的地址 0x1101
int num2 = 20;//num2 的地址 0x1102
int * p_num1 = &num1;// p_num1 裡面的值 0x1101
p_num1 = &num2;//p_num1 裡面的值 0x1102
*p_num1 = 30;//num2 = 30;
printf("num1 = %d,num2= %d\n",num1,num2);
* 指標作為函式的引數
**指標作為函式的引數是地址傳遞,在函式內部,如果改變了地址中變數的值,那麼呼叫者中的變數值也會一樣改變**
**一個函式具有多個返回值**
1.這個函式返回值有2個 但是一個函式只有一個返回值
2.就會想到指標,在主調函式中定義兩個變數
3.把這兩個變數的地址 作為引數傳遞給函式
4.在函式內部求出最大值最小值之後,將它們分別賦值給 這兩個地址解析後的變數裡
5.那麼函式呼叫完之後,主函式中的變數的值也會跟著改變
“`