# 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}]"}