YUAN-HAN LEE
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    ###### tags: `Coding` # C / C++ 學習筆記(partII) ## 編寫規則(指標之前) --- ### 陣列 #### 定義 * 一群具有相同資料型態元素集合而成 * 於記憶體中會使用一段"連續"的記憶體空間存放 => 同等於array * 陣列的變數定義: * "元素" 資料型態 陣列名稱[元素個數]; 範例: int arr[3]; * 陣列index從0開始 * 陣列元素的存取: * 陣列變數名稱[索引編號] #### 陣列初始化寫法 ``` int counter[6] = {0,0,0,0,0,0}; //初始化六個位置皆為零 int counter2[6] = {0};//初始化時,最少需要指定一個值,沒有被指定到的位置會被自動指定為0(此case 指定到第一個位置) int counter3[] ={0,0,0,0,0,0} //直接以初始化的值設定矩陣大小 ``` #### 輸入0~99數(數個),並以10為單位,繪製bar chart ``` #include <stdio.h> #include <math.h> void bar(int []); int main(){ char check; int array_size,input_number; printf("This programe is used for value 0~99\nplease input your size of input array:"); scanf("%d",&array_size); int count[10] ={0}; for (int i=0;i<array_size;i++){ printf("your %d number:",i+1); scanf("%d",&input_number); count[input_number/10] += 1; input_number = 0; } bar(count); return 0; } void bar(int count[]){ for(int i=0;i<10;i++){ int CountDown = 0; if (i ==0){ printf("The amount of 00~09:"); } else{ printf("The amount of %d~%d:",i*10,(i+1)*10-1); } while (CountDown <count[i]){ printf("*"); CountDown++; } printf("\n"); } } ``` #### 陣列排序 => 演算法 **註解:此章節先跳過,等之後實作演算法時補充** #### 陣列的記憶體配置 &emsp;通常在宣告定義變數時(例如int)時,會藉由宣告的變數型態安排相對應的記憶體空間給該變數,當在宣告陣列時,會依照指定的元素型態,分派相對應大小的記憶體空間。 #### 陣列中的陣列(矩陣) ``` int v[x][y] =>可看成v[0]存有[y]個element... ``` &emsp;在陣列中的陣列(矩陣)當中,記憶體的儲存方式為藉由row儲存,也就是若今天有矩陣為:<br> > v[2][3]<br> 則其在記憶體內的儲存方式為如下:<br> ``` v[0][0] -> v[0][1] -> v[0][2] -> v[1][0] -> v[1][1] -> v[1][2] ``` #### 以二維陣列實踐隨機九宮格 ``` #include <stdio.h> #include <time.h> #include <stdlib.h> int main(){ srand(time(NULL)); int matrix[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; int count,random,row,col,t; for (int i=0;i<3;i++){ for (int j=0;j<3;j++){ random = rand() % 9; row = random / 3; col = random % 3; t = matrix[i][j]; matrix[i][j] = matrix[row][col]; matrix[row][col] = t; } } for (int i=0;i<3;i++){ for (int j=0;j<3;j++){ printf("%d ",matrix[i][j]); } printf("\n"); } return 0; } ``` #### 陣列的複製 * 陣列無法直接用另一個陣列初始化 ex:<br> v[10]=n (x) ##### 使用迴圈複製陣列 ``` #include <stdio.h> #include <stdlib.h> #include <time.h> int main(){ srand(time(0)); int i,n[10],v[10]; for (i = 0;i < 10;i++){ n[i] = rand() % 100; } for (i = 0;i < 10; i++){ v[i] = n[i]; } for (i = 0;i < 10;i++){ printf("n[%d]:%d\n",i,n[i]); print("v[%d]:%d\n",i,v[i]); } return 0; } ``` #### 函式間傳遞陣列 * 在陣列傳遞間,傳送到函式的陣列並不會為複製者,而是使用原本陣列(若是整數或是浮點數則是複製一份於新的函式使用。) * 函式的回傳值不可為陣列,取代而知當陣列作為引數傳入,即可直接改變陣列(需要注意此點)。 * C語言導入指標運算來做陣列的處理。 * 作為引入時,可以不給予大小(在作為傳入的時候是否有寫陣列大小無差異)。 ##### 原理 &emsp;於函式間傳遞陣列時,複製的不是陣列的全部資訊,而是複製陣列的起始位置,也就是傳入起始的(address),之後藉由搭配每個資料型態的大小,去計算每個元素的起始位置,得到該位置的元素,因此於宣告時,不管函式宣告的陣列大小為何都不影響,因為單純傳入的是起始位置,其餘都是藉由計算得到,同時於函數中更改陣列,會更改到原陣列原因也是於此,改變這個動作是直接操作address,而非複製值。 #### sizeof * 資料型別占用記憶體的大小為「實作定義」,隨編譯器與設定上不同而有所差異。 * 使用sizeof運算子可以求出某個值或型別所占用的記憶體大小空間(於printf內使用%zu呈現結果) ##### 使用sizeof求陣列長度 **註解:此用法只能在沒有經過函式傳遞的情況下,在計算矩陣的位元數時,可能不如想像** ``` int main(){ int v[3] = {1,2,3}; printf("Size of int: %zu\n",sizeof(int)); printf("Size of v[0]: %zu\n",sizeof(v[0])); printf("Size of v: %zu\n",sizeof(v)); printf("Length of v: %zu\n",sizeof(v)/sizeof(v[0])); // 用總共大小除以單個,可以得知陣列長度 return 0; } ``` #### 存取陣列元素的原理 &emsp;每次執行時,陣列的開始記憶體位置會不同,但單次執行到刪去陣列前,陣列的起始記憶體位置會相同,且由於陣列的連續性,可以用開始位置搭配sizeof()計算每個陣列元素的記憶體位置。 ``` v[i]的記憶體起始位置(address) = 第一個元素的起始位置(address of first element)+i * sizeof(元素型態) ``` --- ### 全域變數 #### 特性 1. 在沒有給定初始值的時候,初始值為0。 2. 流程:初始化全域變數 -> 呼叫main() (在呼叫main前,變會初始化全域變數) #### 缺點 &emsp;全域變數的使用會使得函數間的關係不明確(因為沒有特定給哪個變數使用)。 #### 與靜態區域變數差異 * 靜態的區域變數只會有一份,且只會初始化一次,寫法如下: ``` #include <stdio.h> int count(void){ static int k = 0; //使用static指定變數為靜態變數 k++; return k; } int main(){ for (int i = 1; i <= 5; i++){ printf(" %d\n",count()); } return 0; } ``` #### 靜態全域變數 ``` static unsigned int x = 1; //此為靜態全域變數,只有在此檔案內才可使用 int main(){ return 0; } ``` ----- ### 整數溢位 #### limits.h ``` #include <stdio.h> #include <limits.h> int main(){ printf("%d\n", INT_MAX); printf("%d\n", INT_MIN); return 0; } ``` **使用INT_MAX & INT_MIN 查看範圍內的最大與最小值(for 整數)** **Unsigned 型態在溢位後會算輸入值對(UINT_MAX +1 )取餘數** --- ### 偽亂數生成 &emsp;使用線性同餘法(Linear congruential generator) * X~n+1~ = (X~n~xa+c) % m * 初始值X~0~則稱為亂數種 * 可以利用unsigned int 溢位時會求餘數的概念編寫 ``` #include <stdio.h> int main(){ unsigned int next = 1; for (int i =1;i<=5;i++){ next = next * 1103515245+12345; //此行為求餘數 int rand = (unsigned int)(next/65536) % 32768; //取兩次餘數(此方式只會取到高位,以使得隨機性更高) printf("%d\n",rand); } return 0; } ``` --- ### 字串簡介 #### 字串是字元的序列 * 字元型別(char)可儲存「一個」字元,而通常需要處理的文字是「一串」字元。 * 字串沒有特別的資料型別,(char [])。 * 透過<string.h>,提供字元陣列的函式實現對字串的操作。 * char str[] = {'H','e','l','l','o'}; * 字串是以'\0'表示結尾的字元陣列 * char str[] = {'H','e','l','l','o','\0'} * 在讀入字串前就要先決定好存放字串的緩衝大小(字元大小-1因為有\0) ### const修飾字 在const賦值之後,除了初始化的階段之外,其值無法再被賦予 * 於C語言內可看成唯讀(read-only)的屬性 --- ## 編寫規則(指標) ### 於無指標的情況下 * 在無指標的情況下,使用外部函式傳入變數時如下:<br> ``` void addone(int n){ n = n+1; } int main(){ int a = 3; addone(a);//計算方式為複製a的值進去addone,而非將a傳入,因此不會改變a的值 print("%d",a);//此時a會印出3 } ``` * 無法直接複製陣列(同理無法複製字串) * 無法動態變更陣列長度 ### 指標基本簡介 * 指標為一種**資料型別**用以儲存**記憶體位置** !!很重要是資料型別 * 可解決問題: * 呼叫函式時,直接更改引數值 * 複製陣列 * 複製字串 * 動態更改陣列長度 * 變數宣告語法: `資料型別 *變數名稱; //表示變數內儲存的是資料型別的「記憶體位置」` * 範例: ``` int count = 9; int *countAddr = &count; ``` * 以上述範例而言,可整理成下表: | 表示式 | 資料型別 | 值 | | ----- | ------ | -- | |count|int|9| |&count|`int*`|數字9之儲存位置(為int)| |countAddr|`int*`|數字9之儲存位置(為int)| * 注意,雖然指標變數儲存的是整數,但是當中儲存的資料型別與int不同,而指標變數間不能自由轉型(無隱性轉型),如下: ``` int count = 9; int a ; int *b; // type 1 compare a = count //(o) int == int b = count // (x) (int* ) != int // type 2 compare a = &count//(x) int != (int*) b = &count //(o) (int*) == (int*) ``` ### 指標的間接運算 #### 取址運算子 (`&`) 可使用取址運算子取得變數開頭的記憶體位置。 ``` int count = 9; int *countAddr = &count; ``` #### 間接運算子(`*`) 可使用間接運算子,取得開頭位於指定地址的變數 ``` int count = 9; int *countAddr = &count; result = *countAddr; ``` | 表示式 | 資料型別 | 值 | | ----- | ------ | -- | |count|int|9| |&count|`int*`|數字9之儲存位置(為int)| |countAddr|`int*`|數字9之儲存位置(為int)| |`*countAddr`|int|9| |result|int|9| #### 指標運算(基礎) ``` int count = 9; int *countAddr = &count; *countAddr = 10; => 等同於將count改為10 => 使用指標直接改變該address的位置 ``` #### 指標與函式呼叫 函式呼叫時,複製記憶體位置(同樣是複製,但是由值改為記憶體位置) ``` #include <stdio.h> void pass_pointer(int *n){//這邊的星號為告知資料型態 *n += 1; //這邊的星號為間接運算子 } int main(){ int a = 3; pass_pointer(&a);//函式所需要的變數為指標變數,因此傳入address printf("%d",a); return 0; } ``` &emsp;以上述的方式編寫函式時,由於傳入的值為指標變數(複製address),因此在函式內做變動時更改的是address內的值,由此可以直接變更到a,而不同於之前的方式,變更到的是複製的值。 ##### 簡易兩變數排序(由定義兩function,使用pointer) ``` #include <stdio.h> void swap(int *a,int *b), sort(int *a,int *b); int main(){ int a,b; printf("please input your first and second number:"); scanf(" %d%d",&a,&b); sort(&a,&b); printf("your smaller number is %d,the bigger number is %d",a,b); return 0; } void sort(int *a,int*b){ if (*a > *b){ swap(a,b);//注意這邊的傳入值,不能只傳入&a,&b,因為這兩個值存的是記憶體位置,因此需要先用間接運算子,touch到原本的值再傳送該值的記憶體(swap(&*a,&*b)),or 直接傳入a,b(因為已經是記憶體位置) }; } void swap(int *a,int *b){ int tmp = *a; *a = *b; *b = tmp; } ``` #### 何時該傳數值本身或是數值位置 * 基本原則: * 可以傳值就傳值 => 複製值比較安全,確保函式間乾淨,且用起來較方便 * 例外規則: * 作為引數的變數在呼叫函式時會變動 * 無法直接複製值(陣列、字串) * 複製成本過高(較複雜的結構) #### 指標對整數的加減運算 ``` int v[5]; // 可透過將陣列元素的位置加減一個整數,來求得其他元素的位置 &v[0] + 1 == &v[1];//從v[0]往前移動一個陣列元素後的位置(為C語言定義) &v[1] + 1 == &v[2];//從v[1]往前移動一個陣列元素後的位置 &v[2] - 1 == &v[1];//從v[2]回推移一個陣列元素後的位置 &v[0] + &v[1] // 編譯失敗(x) &v[2] - &v[1] == 1 // 從v[2] 位置到 v[1]位置距離1個元素 &v[3] - &v[0] == 3 // 從v[3] 位置到 v[0]位置距離1個元素 ``` #### 陣列與指標間的關係 !!非常特別 ``` int v[5]; //宣告一個有五個元素的陣列 int *n; //宣告定義一個int指標 n = &v[0]; // !!!陣列型別可以隱性轉型成該陣列第一個元素的記憶體位置(通常陣列無法直接複製) n = v // n = &v[0] ``` 透過指標運算存取陣列元素 ``` int v[5]; int *n = v; n == &v[0]; *n == v[0]; // *n = 0等價於v[0] = 0 n+1 == &v[1]; *(n+1) == v[1]; // *(n+1) == 0 等價於 v[1] = 0 n+2 == &v[2]; *(n+2) == v[2]; // *(n+2) == 0 等價於 V[2] = 0 ``` #### 循序存取陣列元素 ``` #include <stdio.h> int main(){ int v[5] = {1,2,3,4,5}; int *n = v; int i; for (i = 0;i<5;i++) { printf("%d\n",*(n+i)); } return 0; } ``` ``` #include <stdio.h> int main(){ int v[5] = {1,2,3,4,5}; int *n; for (n = v;n != &v[5],n++){ //在此有一個很特別的點,雖然v[5]不存在,但是當在C語言之中寫存在陣列的下一個不存在元素時,其地址會被寫於該陣列尾端+1(下一個陣列開始) printf("%d\n",*n); } return 0; } ``` #### 指標與下標運算子(`[]`) &emsp;在C語言之中,下標運算子具有下列特性: ``` v[0] = 0; // a[b] => *(a+b),v[0] => *(v+0),0[v] => *(0+v) ``` 由上述規律可得下列: ``` int v[5]; int *n = v; //這邊會記錄v[0]的記憶體位置 n[0] == *n; //n[0] => *(n+0) = > *(&v[0]+0) n[1] == *(n+1); //n[1] => *(n+1) = > *(&v[1]+0) ``` #### 使用指標在函式中傳遞陣列 ``` int maxv(int[]); int main(){ int a[3] = {3,9,7}; printf("Max: %d\n",maxv(&a[0])); return 0; } int maxv(int *v){ int max = *(v+0),i; for (i = 1;i<3;i++){ if (*(v+i) > max){ max = *(v+i); } } return max; } ``` #### 統整:指標與陣列關係 * 指標儲存某陣列元素位置時的特殊性 * 透過加減整數,可以算出陣列其他元素的記憶體位置 * 加N等於向後移動N個元素後的記憶體位置 * 減N等於向前(往回)移動N個元素後的記憶體位置 * `a[b]` 運算等同於`*(a+b)`,反之亦同 * 在陣列中從a開始往後移動b所在的陣列元素 * 當指標儲存某陣列的第一個元素記憶體後,使用起來與陣列幾乎相同 * 陣列可以隱性轉型成該陣列第一個元素的記憶體位置 #### 指標與遞增遞減運算子 ``` int main(){ int v[5]; int i; int *p ; for ( p = v; p != &v[5];i++){ *p = 0; } return 0; } ``` or 寫成: ``` int main(){ int v[5]; int *p = v; while (p!= V+5){ *p++=0; //*(p++) = 0 => ++放於後,會獲得++前的值 } return 0; } ``` #### 指標與字串 * 字串以雙引號包裝時,可直接隱性轉成指標(不須先轉乘陣列) * 複合字面常數 => 藉由強制轉型將變數轉型 printf((char[]){'t','e','s','t','\0'}); #### 字面常數特殊性 ``` char strA[] = "test"; // 會開設記憶體空間(五個)儲存現有字串 char *strB = "test"; // 字串字面常數可隱性轉型成字元指標,於此種宣告方式,strB會儲存記憶體位置,而字串會被儲存於唯讀記憶體空間 strA[0] = 'T' // (o) strB[0] = 'T' // (x) 未定義行為,因為儲存於唯讀空間 strA = "Test";//(x) 編譯失敗 strB = "Test"; // (o) ``` #### 字串字面常數與const char* 於使用字面常數儲存資料時,為了安全,會使用const字面常數儲存,在printf內傳遞資料時,傳遞的也是const資料,避免呼叫printf時產生未定義行為(害怕誤改內容),通常能放雙引號(字串字面)位置時,大多都會使用const char。 #### 指標與const Type`*`可以轉成const Type`*` ``` char strA[] = "test"; char *strB = "test"; const char *strC = "test"; strA[0] = 'T'; //(o) strB[0] = 'T'; //未定義行為 strC[0] = 'T'; //(x)編譯失敗 strA = strB; //(x) (char []) = (char * ) strA = strC; //(x) (char []) = (const char *) strB = strA; //(o) (char *) = (char []) strB = strC; //(x) (char * ) = (const char * ) strC = strA; //(o) (const char *) = (char []) strC = strB; //(o) (const char * ) = (char *) ``` #### 陣列的指標 ``` int (*q)[3] = &v; //q儲存具有三個整數的陣列v的位置 //存取 (*q)[2] =5 ``` 陣列傳遞差別 ``` void print_int(int *n){ int i; for (i=0; i<3; i++){ printf(" %d",n[i]); } printf("\n"); } void print_addres(int (*q)[3]){ int i; for (i=0;i<3,i++){ printf("%d",(*q)[i]); } printf("\n"); } int main(){ int v[3] = {1,2,3}; print_int(v); //此方式傳遞的是v陣列開頭第一個元素的位置 print_address(&v); // 此方式傳遞的是V陣列的位置 return 0; } ``` 使用sizeof的情況下,如果傳入的是陣列的指標,則可以得到陣列大小:<br> ``` void print(int (*p)[3]{ //(但此情況傳入的陣列大小其實是固定的,不能傳入變動值) int i; for (i = 0;i<sizeof(*q)/sizeof((*q)[0]); i++){ printf("%d",(*q)[i]) } printf("\n"); } ``` #### 指標間轉型的限制 &emsp;絕大部分的情況下,指向不同型別的指標間是不能隱性轉型的。 ##### 合法的隱性轉型 1. 同類型別內的互轉 1. float = double 2. int = char 2. 整數與浮點數間互轉 1. int = double (無條件捨去) 2. double = int 3. 陣列可以隱性轉型成指向第一個元素的指標 1. int * = int [3] 4. Type * 可以隱性轉型成 const Type * 1. const int * = int * 5. void * 與其他型別的指標"可能"可以互轉 ##### 指標與整數間的轉型 **電腦如何儲存指標?** * 指標是一個儲存記憶體位置的資料型別 * 電腦中記憶體位置想像成一段連續空間,以位元組為單位,替每個位元組給定特定編號或表示法(每個電腦的表示法並沒有規定要相同(C語言的case下)) &emsp;void 可視為一個泛用型的記憶體空間,因此可自由轉型,在指標與整數型別中,無法確定記憶體位置所需的位元數,因此可能會發生整數的資料型別位元組不夠的情況。而是否可直接將整數轉型為指標,則需要依照強制轉型的實作定義,未必可成功。<br> ##### 指標間的強制轉型 **記憶體對齊** &emsp;在記憶體的對齊上為實作定義,可能為對齊到偶數、或是以固定公差為對齊基準,可有效增加記憶體的讀取效率。以此類推,若是將char對齊為1、int對齊為4,則char的記憶體位置未必能儲存int,反之int的記憶體位置必定能儲存char,因此在轉型時,需要注意到對齊的大小,才能確保技藝體能互轉。 ##### 改變陣列大小 * 不可行 -> 無法以現有的記憶體空間做擴充(因為陣列需要連續擺放,擴充的記憶體位置可能已經有儲存資料) * 可行 -> 創造新陣列 ->使用指標實現 ##### 動態記憶體(包含在<stdlib.h>內) * 使用malloc函式動態配置記憶體 * void* malloc(size_t size); * size為非負整數型態(size_t),表示要配置的記憶體空間大小(可由sizeof算出) * 回傳值void* 表示可隱性轉型成其他資料型態的指標 * 範例: int* larger = malloc(sizeof(int) * (length+1));//創建一個大小為(length+1)個int大小的空間,larger指向的malloc空間不會被自動釋放 * 使用free函式釋放動態配置的記憶體 * void free(void* ptr); * 使用realloc函式複製記憶體內容 * void* realloc(void* ptr,size_t size); * ptr 是要重新配置的記憶體空間開頭位置 * size是重新配置後的記憶體空間大小 * 回傳值為重新配置後的記憶體空間開頭位置 * 在空間足夠的情況下,有可能使用擴充的方式執行,可能會較有效率。 ##### 在函式中傳遞二維陣列 &emsp;編寫邏輯:<br>使用p儲存A陣列的內部陣列開頭位置,並將此值傳入至新的函式中,以此傳入內部陣列的開頭位置,而後面呼叫回全時,則會先進入p,也就是A陣列的相對應元素開頭位置,以此讀取內部值。 ``` #include <stdio.h> #include <stdlib.h> int print_two_dimensional(int **p,int height,int wide){ for (int i = 0;i<height;i++){ for (int j = 0; j<wide;j++){ printf("%d",p[i][j]); } printf("\n"); } }; int main(){ int A[2][3] = {{1,2,3},{4,5,6}}; int *p[2] = {A[0],A[1]}; //printf("%d",*p[0]); print_two_dimensional(p,2,3); return 0; } ``` ###### 儲存多個字串 1. 使用二維陣列儲存多個字串 ``` char strA[3][4] = {"How","are","you"}; // 三個字卻使用四格空間,是因為字串結尾需要'\0'作為結束點。 ``` 2. 只用指標陣列儲存多個字串 ``` const char *strB[3] = {"How","are","you"};//strB會儲存的是後面三個字串的開頭位置,為不可變動 ``` 兩者差異:<br> ``` strA[2][0] = 'Y'; // (o) strB[2][0] = 'Y'; // (x) ->因為資料型態為const,為不可變動型態 strB[2] = 'What'; // (o) ->因為是更改整個陣列 strA[2] = 'What'; //(x) - >陣列不可直接被複製 ``` 3. 藉由儲存開始位置 ``` char *strC[3] = {strA[0],strA[1],strA[2]}; strC[2][0] = 'Y'; // (o)相等於修改strA char strD[5] = "What" // (o) ->讓字串由const char轉為char strB[0] = strC;//(o) strB[0][0] = 'w'; //(o) ``` ##### 輸入多個字串 **ver 1 ->在輸入大於等於三個字串時會出現亂碼(還沒找到原因)** ``` #include <stdio.h> #include <stdlib.h> #include <string.h> /* 讓使用者輸入多字串,印出使用者輸入的字串,當使用者輸入END表示結束。 */ int main(){ int size = 0; //紀錄共多少字元 char *save = NULL; //設定save用來儲存多個字串 (後續會用realloc使其變浮動) char input[50]; //設定input字串大小 char **str = NULL; //雙重指標,用來儲存每個字串開頭的位置(後續會用realloc使其變浮動) int len = 0; //紀錄總共儲存多少字串 while (1){ printf("please input your word:"); scanf("%s",input); if (strcmp(input,"end") == 0) break; int size_loop = size; size += strlen(input)+1; save = realloc(save,sizeof(char)*(size)); str = realloc(str,sizeof(char)*(len +1)); str[len] = &save[size_loop]; strcpy(str[len],input); len++; } printf("-------\n"); int i; for (i =0;i<len;i++){ printf("%s ",str[i]); } printf("\n(%d,%d)\n",len,size); return 0; } ``` **ver 2 可正常運作** ``` #include <stdio.h> #include <stdlib.h> #include <string.h> /* 讓使用者輸入多字串,印出使用者輸入的字串,當使用者輸入END表示結束。 */ int main(){ int size = 0; char *save = NULL; char input[50]; char **str = NULL; int len = 0; while (1){ printf("please input your word:"); scanf("%s",input); if (strcmp(input,"end") == 0) break; size += strlen(input) + 1; str = realloc(str,sizeof(char)*(len +1)); str[len] = calloc(strlen(input) + 1, sizeof(char)); strcpy(str[len],input); len++; } printf("-------\n"); int i; for (i =0;i<len;i++){ printf("%s ",str[i]); } printf("\n(%d,%d)\n",len,size); return 0; } ``` ---- <a href ="https://hackmd.io/61b3sW1zR2q-rJboeJr0OA?both">C/C++ 學習筆記(PartI)</a>

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully