本文目錄
- [一、字符串簡介](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#label0)
- [二、字符串的初始化](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#label1)
- [三、字符串的輸出](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#label2)
- [?四、字符串的輸入](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#label3)
- [五、字符串數組](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#label4)
說明:這個C語言專題,是學習iOS開發的前奏。也為了讓有面向對象語言開發經驗的程序員,能夠快速上手C語言。如果你還沒有編程經驗,或者對C語言、iOS開發不感興趣,請忽略
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#labelTop)
### 一、字符串簡介
* 在Java中,一個字符串可以用String類型來存儲
~~~
String s = "MJ";
~~~
C語言中沒有String這種類型。其實字符串就是字符序列,由多個字符組成,所以在C語言中,我們可以用字符數組來存儲字符串。
* 字符串可以看做是一個特殊的字符數組,為了跟普通的字符數組區分開來,應該在字符串的尾部添加了一個結束標志'\0'。'\0'是一個ASCII碼值為0的字符,是一個空操作符,表示什么也不干。所以采用字符數組存放字符串,賦值時應包含結束標志'\0'。
* 字符串"mj"的存儲情況如下(假設用字符數組char a[]來存儲):

注意了,尾部有個'\0',如果沒有這個結束標記,說明這個字符數組存儲的并不是字符串
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#labelTop)
### 二、字符串的初始化
~~~
1 char a[3] = {'m', 'j', '\0'};
2
3 char b[3];
4 b[0] = 'm';
5 b[1] = 'j';
6 b[2] = '\0';
7
8 char c[3] = "mj";
9
10 char d[] = "mj";
11
12 char e[20] = "mj";
~~~
當我們使用類似第8行的初始化方式時,系統會自動在字符串尾部加上一個\0結束符
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#labelTop)
### 三、字符串的輸出
我們可以使用stdio.h中兩個函數來輸出字符串,分別是printf和puts函數
### 1.printf函數
* 這個函數我們已經用過很多遍了,用格式符%s表示需要輸出一個字符串
~~~
char a[3] = {'m', 'j', '\0'};
printf("%s", a);
~~~
輸出結果:
,最后面那個\0是不可能輸出的,它只是個空字符,只是字符串結束的標記。
* 說到這里,有人可能會想:這樣看來,似乎把最后的\0去掉也沒什么影響吧,輸出結果應該還是一樣的啊,都是"mj"。
我們可以試一下,把最后面的\0去掉,再進行輸出:
~~~
char a[3] = {'m', 'j'};
printf("%s", a);
~~~
輸出結果:
,跟上面添加了\0的輸出結果是一樣的。
別高興地太早了,我只能說你這是僥幸一樣的,運氣好了一點。
* 我們再來看一個例子
~~~
1 char a[3] = {'m', 'j', '\0'}; // 添加了結束符\0
2
3 char b[] = {'i', 's'}; // 假設忘記添加結束符\0
4
5 printf("字符串a:%s", a); // 輸出字符串a
6
7 printf("\n"); // 換行
8
9 printf("字符串b:%s", b); // 輸出字符串b
~~~
看清楚了,第3行的字符數組b后面沒有添加結束符\0,因此b不算是個正宗的字符串。
按照你的猜想,字符串b的輸出應該就是"is",但是輸出結果為:
,可以看出,當我們嘗試輸出b的時候,把a也輸出了。
要搞清楚為什么,首先要看看a和b的內存地址:
~~~
printf("a的地址:%x", a);
printf("\n");
printf("b的地址:%x", b);
~~~
輸出結果:
,由這個數據我們可以分析出a和b的內存存儲情況如下:

可以看出來,數組b和a的內存地址是連續的。我們再回到輸出b的代碼:
~~~
printf("字符串b:%s", b); // 輸出字符串b
~~~
%s表示期望輸出一個字符串,因此printf函數會從b的首地址開始按順序輸出字符,一直到\0字符為止,因為\0是字符串的結束標記。
所以,如果想要創建一個字符串,記得加上結束符\0,不然后果很嚴重,會訪問到一些垃圾數據。
### 2.puts函數
~~~
1 char a[] = "mj";
2 puts(a);
3
4 puts("lmj");
~~~
看第2行代碼,puts函數會從a的首地址開始輸出字符,一直到\0字符為止。
輸出結果:
,可以看出puts函數輸出一個字符串后會自動換行。
* puts函數一次只能輸出一個字符串,printf函數則可以同時輸出多個字符串
~~~
printf("%s - %s", "mj", "lmj");
~~~
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#labelTop)
### ?四、字符串的輸入
stdio.h中有2個函數可以用來接收用戶輸入的字符串,分別是scanf和gets
### 1.scanf函數
~~~
char a[10];
scanf("%s", a);
~~~
scanf函數會從a的首地址開始存放用戶輸入的字符,存放完畢后,系統會自動在尾部加上一個結束標記\0
注意,不要寫成scanf("%s", &a),因為a已經代表了數組的地址,沒必要再加上&這個地址運算符。
### 2.gets函數
~~~
char a[10];
gets(a);
~~~
gets跟scanf一樣,會從a的首地址開始存放用戶輸入的字符,存放完畢后,系統會自動在尾部加上一個結束標記\0。
* gets一次只能讀取一個字符串,scanf則可以同時讀取多個字符串
* gets可以讀入包含空格、tab的字符串,直到遇到回車為止;scanf不能用來讀取空格、tab
[回到頂部](http://www.cnblogs.com/mjios/archive/2013/03/15/2961273.html#labelTop)
### 五、字符串數組
### 1.字符串數組簡介
* 一維字符數組中存放一個字符串,比如一個名字char name[20] = "mj"
* 如果要存儲多個字符串,比如一個班所有學生的名字,則需要二維字符數組,char names[15][20]可以存放15個學生的姓名(假設姓名不超過20字符)
* 如果要存儲兩個班的學生姓名,那么可以用三維字符數組char names[2][15][20]
### 2.字符串數組的初始化
~~~
char names[2][10] = { {'J','a','y','\0'}, {'J','i','m','\0'} };
char names2[2][10] = { {"Jay"}, {"Jim"} };
char names3[2][10] = { "Jay", "Jim" };
~~~
可以把字符串數組看作是一維數組,它的元素是字符串。字符串數組names由字符串"Jay"和字符串"Jim"構成。
- 前言
- C語言入門教程1-概述
- C語言入門教程2-第一個C程序
- C語言入門教程3-關鍵字、標識符、注釋
- C語言入門教程4-變量與常量
- C語言入門教程5-進制
- C語言入門教程6-變量與內存
- C語言入門教程7-基本數據類型
- C語言入門教程8-運算符
- C語言入門教程9-流程控制
- C語言入門教程10-函數
- C語言入門教程11-函數的聲明定義
- C語言入門教程12-scanf與printf輸入輸出函數
- C語言入門教程13-數組-批量數據存儲
- C語言入門教程14-字符串
- C語言入門教程15-字符與字符串常用處理函數
- C語言入門教程16-指針
- C語言入門教程17-指向一維數組元素的指針
- C語言入門教程18-指針與字符串
- C語言入門教程19-預處理指令1-宏定義
- C語言入門教程20-預處理指令2-條件編譯
- C語言入門教程21-預處理指令3-文件包含
- C語言入門教程22-變量類型與作用域
- C語言入門教程23-枚舉
- C語言入門教程24-結構體
- C語言入門教程25-typedef類型別名