---
# System prepended metadata

title: 教材準備

---

教材準備
===

字串
---

> C 其實沒有字串這個類別。

好，我們今天就上到這裡，下課。



<br><br><br><br><br><br><br><br><br><br>

C++和Python其實都有```string```這個類別，不過C沒有，我們用**字元的陣列**來代表字串。

### 基本用法

```clike
#include <stdio.h>

int main()    {
    char a[80];
    scanf("%s", a); // 讀到空格或換行就結束。
    printf("%s\n", a);
    char b[64] = "aloha", c[64] = "int main()\n{\n}\n"; 
    // 字串的初始化要用雙引號  " "
    printf("%s\n%s\n", b, c);
    return 0;
}
```

問題就來了。```b```的長度是64，aloha只有5個字，當你在```printf```的時候編譯器是怎麼知道你的字串已經結束？

還記得上次提到的ASCII表嗎?ASCII表的第一個字元 NULL就是 ```\0```，字串處理函式遇到```\0```就知道字串已經結束。

小練習：如果你要存一個最多100個字的字串，你的字元陣列最少要開多大？

* 注意： 字串的題目很多時候出bug都是因為最後的```\0```沒有處理好。

### 其他寫法

這些是課本有提到不過我個人覺得比較少用到的寫法
```clike
char a[] = "aloha" // 沒說長度，讓編譯器自己算。
char *b = "aloha" // 字元指標
```

### 常用函式

首先，你必須```#include <string.h>```。

1. strlen

給定一個字串，回傳字串的長度
```clike
#include <string.h>
#include <stdio.h>

int main()	{
    char a[80];
    scanf("%s", a);
    printf("%lu\n", strlen(a));
    return 0;
}
```

小練習：自己實作```strlen```函式。

2. strcpy, strncpy, strcat, strncat

```strcpy```會把source字串複製並**覆蓋**到destination。strncpy做的事情也一樣，只是你需要多給一個參數說你想複製多少個字元。
```clike
#include <string.h>
#include <stdio.h>

int main()	{
    char source[80] = "aloha", destination[80] = "hello";
    strcpy(destination, source);
    printf("%s\n", destination);
    return 0;
}
```

```strcat```會把source字串複製並**接到**destination。strncat做的事情也一樣，只是你需要多給一個參數說你想複製多少個字元。
```clike
#include <string.h>
#include <stdio.h>

int main()	{
    char source[80] = "aloha", destination[80] = "hello";
    strcat(destination, source);
    printf("%s\n", destination);
    return 0;
}
```
* 注意：編譯器不會幫你檢查複製/接上的結果會不會超過目標字元陣列的大小，超過的部分會被吃掉，這也就是所謂緩衝區覆蓋(buffer overrun)

3. strcmp, strncmp

比較兩個字串是否相同，相同的話回傳0，前者比後者“大”回傳正數，後者比回傳“大”回傳負數。
大小是用ASCII表作為標準。

strncmp做的事情也一樣，只是你需要多給一個參數說你想比對前幾個字元。

```clike
#include <string.h>
#include <stdio.h>

int main()	{
    printf("%d\n", strcmp("aloha", "hello"));
    printf("%d\n", strcmp("aloha", "aloha"));
    return 0;
}
```

小練習:讀入兩個字串，檢查這兩個字串是否相同，字串的長度 < 64。

4. strchr, strrchr, strstr

strchr在字串中搜尋一個字元c, 如果找的到就回傳第一個字元c的記憶體位置。
strrchr也是一樣，不過就是反著找。
strstr也是一樣，不過是在字串裡面找字串。

```clike
#include <string.h>
#include <stdio.h>

int main()	{
	char a[80] = "helloaloha";
	char *ptr = strchr(a, 'a');
	printf("%lu\n", ptr - a);
	return 0;
}
```

5. strtok

strtok會把字串切成一段一段的token。token就是字串被delimeters中的任何字元所隔開的部分。

strtok的用法很特別，分為3個步驟。

* 先呼叫strtok一次。```token = strtok(string, delimeters)``` 會把string切成很多個token並指定給定一個指標token。每個token都會在最後被塞入一個\0，可以用各種字串函式處理。
* 進入while迴圈檢查token是否為NULL，然後作處理。
* 呼叫多一次strtok ```strtok(NULL, delimeters)```跳到下一個token。

```clike
#include <string.h>
#include <stdio.h>

int main()	{
    char a[80] = "welcome,to,facebook.mark.zuckerberg";
    char *token;
    token = strtok(a, ",.");
    while (token != NULL)	{
        printf("%s\n", token);
        token = strtok(NULL, ",.");
    }
    return 0;
}
```

最後一份習題
---

寫一份能印出自己的Code。

[Quine](https://en.wikipedia.org/wiki/Quine_(computing))

例 :
```clike
#include <stdio.h>
int main() {
    char c;FILE *f;
    f=fopen(__FILE__,"r");
    while((c=fgetc(f))!=EOF)putchar(c);
}
```

這個計程不會考，不過我覺得還蠻有趣的 XD