# String 字串 ###### tags: `lion_1081` --- ## Introduce ---- ## Array 陣列 在 C 中,字串的本質是由字元所組成的array ---- ### 宣告 ```=c int a[4]; ``` 可以使用 a[0] a[1] a[2] a[3] 四個位置 ---- ### n-D array 以2-D為例 ```=c int b[2][2]; ``` 可使用的位置分別為 b[0][0] b[0][1] b[1][0] b[1][1] **注意 可使用的位置沒有b[2][2]** ---- ### array 在 memory 中的位置是連續的 ```c= #include<stdio.h> int a[5]; int main() { int i; for(i=0;i<5;i++) printf("a[%d]位置是:%p\n",i,&a[i]); } ``` ---- 結果如下 ``` a[0]位置是:0x5601c6977060 a[1]位置是:0x5601c6977064 a[2]位置是:0x5601c6977068 a[3]位置是:0x5601c697706c a[4]位置是:0x5601c6977070 ``` 使用環境 : 32位元 兩相鄰 address 之間都差了一個 int 的大小 ---- ### n-D array 的位置也是連續的 ```c= #include<stdio.h> int main() { int a[3][3]; int i,j; for(i=0;i<3;i++) { for(j=0;j<3;j++) printf("a[%d][%d]位置是:%p\n",i,j,&a[i][j]); } return 0; } ``` ---- ``` a[0][0]位置是:0x563d70029060 a[0][1]位置是:0x563d70029064 a[0][2]位置是:0x563d70029068 a[1][0]位置是:0x563d7002906c a[1][1]位置是:0x563d70029070 a[1][2]位置是:0x563d70029074 a[2][0]位置是:0x563d70029078 a[2][1]位置是:0x563d7002907c a[2][2]位置是:0x563d70029080 ``` 多維陣列的記憶體順序是由 a[0][0-2]、a[1][0-2]、a[2][0-2] --- ## String ---- C語言中並沒有替字串定義一個新的資料型別 字串是用字元陣列的形式來儲存 ---- ### 宣告 ```clike= // 字元 char a = 'H'; // 字串 (以'\0'表示結尾的字元陣列) char b[6] = {'H','e','l','l','o','\0'}; // 字串 (自動補上'\0') char c[6] = "Hello"; char d[] = "Hello"; ``` 字串大小不能超過宣告時的大小 ---- ### 跳脫字元 (escape) 如同字元,反斜線也能用來表示一些特定字元 ``` '\0' 空字元,用於字串的結束 '\n' New Line,換行符號 '\t' Tab,跳格 '\'' 單引號 '\"' 雙引號 ``` ---- 注意!! :::danger \0在記憶體中是佔1個char位置 ::: ```c= #include <stdio.h> int main(void) { char text[] = "hello"; int length = sizeof(text) / sizeof(char); printf("%d", length); return 0; } ``` print : 6 ---- ### 當讀到 `'\0'` 的時候 字串就結束了 ```clike= #include <stdio.h> int main() { char a[]="abcd\0"; char b[]="ab\0cd"; printf("%s\n",a); // output: abcd printf("%s\n",b); // output: ab return 0; } ``` ---- ### 練習 1 輸入學號,印出 my student id is <學號> ---- ### Ans ```clike= #include <stdio.h> int main() { char id[10]; char str[]="my student id is"; scanf("%s",id); printf("%s %s\n",str,id); } ``` --- ## Const 用法 ---- ### const 可以用來修飾普通變數及指標 const的變數一旦初始化後就不能做更動 且一定要做初始化 ---- ### 修飾普通變數 有兩種寫法,但本質上是一樣的 const 修飾的型別為 TYPE 的變數 value 是不可變的 ```c= const TYPE value; TYPE const value; ``` ```c= const int a; // a 是 const int const a; // a 是 const ``` ---- ### 修飾指標 有以下五種寫法 一般我們主要使用p1 ```c= char a = 'a'; const char b = 'b'; const char *p1 = &b; // pointer to const char char const *p2 = &b; // pointer to const char char* const p3 = &a; // const pointer to char const char* p4 = &b; // pointer to const char const char* const p5 = &b; // const pointer to const char ``` p1,p2,p4 可以改,\*p1,\*p2,\*p4 不能被修改 p3,p5 必須初始化且不能被修改 \*p3 可以改 \*p5 不能改 ---- ### 注意型別 const char 的指標 可以指向一般的char 一般的char 的指標 不能指向 const char --- ## 字串處理 ---- ### 結構字串化 `sprintf()` int sprintf(char *str, const char *format, ...) str: 格式化後的輸出字串 format:格式化的規格字串 使用 sprintf 產生 today is 2019/11/19 的字串 ```c= #include <stdio.h> int main() { char str[30]; int year=2019, month=11, day=19; sprintf(str,"today is %d/%d/%d",year,month,day); printf("%s\n",str); // today is 2019/11/19 return 0; } ``` ---- ### 剖析字串 `sscanf()` int sscanf ( const char * str, const char * format, ...); str : 被剖析的字串 , format: 剖析格式 如何將 hello 2019 拆解成一個字串跟一個整數? ```c= #include <stdio.h> int main() { char str[] ="hello 2019"; char buf[10]; int n; sscanf(str,"%s %d",buf,&n); printf("buf= %s\n",buf); // hello printf("n= %d\n",n); // 2019 return 0; } ``` ---- ### 能不能直接修改字串? ```c char a[]="abcd"; a="dcba"; // error char b[10]; b="HelloWorld"; // error ``` ---- #### 不行,你必須要一個一個字元的來修改 ```c a[0]='d'; a[1]='c'; a[2]='b'; a[3]='a'; ``` Q: 有沒有更好的方法呢 ? A: 有,C語言提供一個函式庫用來處理字串 <string.h> ---- ### 字串複製 `strcpy()` (<span style="color:red;">str</span>ing <span style="color:red;">c</span>o<span style="color:red;">py</span>) 將字串 s2 複製到 s1 char *strcpy(char *s1, const char *s2); ```c= #include <stdio.h> #include <string.h> int main() { char a[5] = "abcd"; char b[5] = "dcba"; printf("before: %s\n",a); // abcd strcpy(a,b); // 也可以寫成 // strcpy(a,"dcba"); printf("after : %s\n",a); // dcba return 0; } ``` ---- ### 字串複製 `strncpy()` 將字串 s2 最多 n 個字元複製到 s1 char *strncpy(char *s1, const char *s2, size_t n); ```c= #include <stdio.h> #include <string.h> int main() { char a[] = "hello world"; char b[] = "goodbye"; printf("before: %s\n",a); // hello world strncpy(a,b,5); printf("after : %s\n",a); // goodb world return 0; } ``` ---- ### 字串長度 `strlen()` (<span style="color:red;">str</span>ing <span style="color:red;">len</span>gth) size_t strlen(const char *s); ```c= #include <stdio.h> #include <string.h> int main() { char a[20]="wakenlion"; printf("%u\n",strlen(a)); // 9 char b[20]="waken\0lion"; printf("%u\n",strlen(b)); // 5 return 0; } ``` 注意: strlen並不會計算 '\0' ---- ### 練習 2 請寫一個程式,輸入一個英文名字 輸出 my name is xxx 並且 印出這個字串的長度 必須使用到 sprintf(), strlen() ---- ### Ans ```c= #include <stdio.h> #include <string.h> int main() { char str[100] ; char name[10]; scanf("%s",name); sprintf(str,"my name is %s",name); printf("%s\n",str); printf("%u\n",strlen(str)); return 0; } ``` ---- ### 連結字串 `strcat()` (<span style="color:red;">str</span>ing con<span style="color:red;">cat</span>enate) 將字串 s2 接到 s1 的尾端 char *strcat(char *s1, const char *s2); ```c= #include <stdio.h> #include <string.h> int main() { char s1[20]="hello "; char s2[20]="world"; strcat(s1,s2); printf("%s\n",s1); // hello world return 0; } ``` ---- ### 連結字串 `strncat()` 將字串 s2 最多 n 個字元接到 s1 的尾端 char *strncat(char *s1, const char *s2, size_t); ```c= #include <stdio.h> #include <string.h> int main() { char s1[20]="hello "; char s2[20]="world"; strncat(s1,s2,3); printf("%s\n",s1); // hello wor return 0; } ``` ---- ### 比較字串 `strcmp()` (<span style="color:red;">str</span>ing <span style="color:red;">c</span>o<span style="color:red;">mp</span>are) 比較 s1 與 s2 兩個字串是否相等(根據ASCII) int strcmp(const char * s1, const char * s2); [reference](https://overiq.com/c-programming-101/the-strcmp-function-in-c/) ```c= #include <stdio.h> #include <string.h> int main() { int result; result = strcmp("ncku","ncku"); printf("%d",result); // 0 return 0; } ``` ---- ### 比較字串 `strncmp()` 比較 s1 與 s2 兩個字串前 n 個字元是否相等 int strncmp(const char * s1, const char * s2, size_t n); ```c= #include <stdio.h> #include <string.h> int main() { char a[] = "hello"; char b[] = "helloworld"; if(strncmp(a,b,5)==0) { printf("correct\n"); } else { printf("incorrect\n"); } return 0; } ``` ---- ### 練習 3 寫一個密碼確認的程式 自己先在程式內設定一個密碼 然後輸入兩個字串 input1, input2 之後將 input2 連接在 input1後面 如果連接後的 input1 和密碼相等,印出"correct" 反之,印出"error" hint: strcmp , strcat ---- ### Ans ```c= #include <stdio.h> #include <string.h> int main(void) { char pwd[] = "123456"; char input1[10],input2[10]; scanf("%s %s", input1,input2); strcat(input1,input2); if(strcmp(pwd, input1) == 0){ printf("correct"); } else{ printf("error"); } return 0; } ```
{"metaMigratedAt":"2023-06-15T00:54:34.110Z","metaMigratedFrom":"Content","title":"String 字串","breaks":true,"contributors":"[{\"id\":\"8329238d-0a43-44c6-9d21-cb0bdf1001b8\",\"add\":14897,\"del\":7539}]"}
    1253 views