字符串是以空字符\0結尾的char類型數組。
字符數組和字符串
1.字符數組 %c
聲明 char arr[5];? ?
初始化?char arr[]={'h','e','l','l','o'};? //字符數組來的初始化
字符數組用單引號,用%c來作為單個字符的占位符
賦值? 除了初始化不能直接賦值,只能遍歷和函數賦值
字符數組的一般語法和其他數組的操作是相同的
2.字符串? %s
字符串是以空字符(\0)結尾的char類型數組。
'h','e','l','l','o'? //字符
"hello\0"? ? ? ? //字符串
char arry[]='h','e','l','l','o','\0'};
區分字符數組和字符串的區別 /0,/0是字符串的結束標志,%s讀取字符串的時候在遇到/0的時候會自動結束。
字符串arry[10] ; //可以存放10個字符,只不過最后一個是'\0',所以只能存放我們需要的9個字符
處理單字符的兩種函數getchar()和putchar()
字符串的輸入函數
1.字符串的輸入-fgets()函數
fgets()函數一共有三個參數
第一個參數,讀入的字符串
第二個參數,讀入字符串的最大值
第三個參數,讀入字符串寫入的文件, 如果讀入從鍵盤輸入的數據,則以stdin(標準輸入)作為參數,該標識符定義在stdio.h中。
fgets()函數會將換行符也儲存進字符串中。
我們通過一系列的操作來查找字符串中的換行符并把它替換掉
空字符('0')和空指針(NULL)的區別
空字符('\0')是用于標記C語言字符串末尾的字符,對應編碼為0
空指針(NULL)有一個值,該值不會和任何數據的有效地址連接起來
空字符是整數類型,是一個字符,占1字節
空指針是指針類型,是一個地址,通常占4字節
字符串的輸出(-fgets函數的好兄弟)-fputs()函數
fputs()函數通常與fgets()函數配對使用
fputs()函數的第1個參數是它要輸出的字符串或字符串的地址,第2個參數指明它要寫入的文件。如果要顯示在計算機顯示器上,應使用stdout(標準輸出)作為該參數。
fputs函數的返回值返回指向char類型的指針。如果一切進行順利,該函數返回的地址與傳入的第 1 個參數相同。但是,如果函數讀到文件結尾,它將返回一個特殊的指針:空指針(null pointer)。
2.get_s函數
get_s()函數和fgets()函數相類似,用一個參數限制讀入的字符數。
get_s(word,longs)函數和fgets()函數的不同點
get_s()函數只從標準輸入中讀取數據,所以不需要第三個文件參數
如果get_s()讀到換行符,丟棄它而不是儲存它。
3.s_gets()函數
fputs()函數和puts()函數的不同點
puts()函數會給字符串添加換行符,當字符串遇到換行符時候,停止輸出。
puts()函數針對于屏幕,fputs()是puts()函數針對于文件訂制的版本。
gets()函數丟棄換行符
fgets()函數保留換行符
puts()函數添加換行符
fputs()函數不添加換行符
字符串的輸出-puts()函數
1.和printf( )函數相同,puts( )函數也屬于stdio.h系列的輸入輸出函數。
2.與printf( )函數不同的是,函數只顯示字符串,并且自動在顯示的字符串末尾加上換行符\n? 。
3.只需要把要輸出的字符串的地址作為參數傳遞給puts()函數即可。
4.puts()函數遇到空字符\n就停止輸出。
結果
字符串面量,字符串常量?
雙引號括起來的內容被稱為字符串面量,字符串面量和/0被存儲在內存中
char greeting[] = "Hello, and"" how are" " you"
char greeting[] = "Hello, and how are you today!";
兩個代碼等價,字符串之間用空白間隔,C視其為連接起來的字符串面量。
字符串常量屬于靜態存儲類別。函數中使用字符串常量,在函數中使用字符串面量,只會在內存中被存儲一次。函數被調用多次。用雙引號括起來的內容被視為指向該字符串存儲位置的指針。類似于數組名作為指向該數組位置的指針,但是字符串面量被清除。
3.初始化和賦值的區別
初始化: 在定義的時候進行賦值
賦值:必須用for循環或者函數進行拷貝
4.字符串的使用 arr指向字符串的第一個字符
int arr[10];? arr指向arr[1]
char arr[10];? arr指向字符串的第一個字符
字符串數組和指針
輸出結果
注意這段代碼有三種形式的字符串 MSG ar[ ]數組 和指針 p?
相同的字符串面量,但是數組的地址不同于其它兩種。`????
第一? p 和 MSG 的地址相同,而 ar 的地址不同。
第二 雖然字符串面量 "I love Huangyiding" 在兩個 printf( ) 函數中出現了兩次,但是編譯器可以多次使用相同字面量儲存在一處或者多處。
第三 靜態數據使用內存和 ar 使用的動態內存不一樣,不僅地址不同,特定編譯器甚至使用不同的位數表示兩種內存。
字符串數組和指針的區別
用數組存儲一個字符串
用指針指向一個字符串兩者有什么區別嗎
輸出結果
數組和指針的區別
雖然數組名是數組首元素的地址,
數組名是常量,右值。不能進行++運算
指針是變量,左值??梢赃M行++運算
附錄:如果打算修改字符串,就不要用指針指向字符串面量
字符串數組
我們用指針和數組形式 分別寫了兩個字符串數組
結果
從某些方面看,book和bank字符串數組相似
book [1][2]表示數組中第二2個指針單元所指向的字符串第三個字符
bank[1][2]表示的數組中第二個字符串的第三個字符
book數組是一個含有5個指針的數組 char*book[5],[ ]優先級高于*
占用20字節
bank是一個5個字符串數組的數組
占用200字節
book中的指針指向初始化字符串面量的位置,存在靜態內存
bank數組儲存字符串面量的副本,存在動態內存。分為指針地址和字符串地址
二者區別
一個是規則矩形,一個是不規則矩形
5.字符串的函數 C標準庫 <string.h>
5.1 strcpy函數:
我們把src所指向的字符串 拷貝 到dest中,str(string) cpy(copy)
char*strcpy(char *dest,const char*src)? ? ? ? ? ?//src 源
中文占用兩個字節
5.2 strncmp函數?
比較兩個字符串前n個字符,相同返回0,不同返回1
不同的情況下:比較e和h的ASCII值,e<h,返回-1,e>h,返回1。函數核心比較字符的ASCII值哪個比較大
接下來我們通過指針來自己寫一個函數strcpy
反思:
函數的參數和返回值為char類型指針型
在我們函數調用的時候傳遞的實參是字符型常量?
我們自己寫一個strncmp函數
結果
反思:
1.用for控制字符偏移,和字符自加
2.設置多個條件 if-esle if - else if ,注意區分函數塊
3.for循環外的return0 ,如果前面第一個條件成立,直接return 0;
4. 如果前面的任意一個條件成立,執行一個return 1 后return 0不執行。因為函數只能執行一個return
其他函數
頭文件<string.h>函數還定義了很短函數,在下面各個函數中 s和t為char*類型,c和n為int類型
strcat(char* s,char* t)?? ? ? ? ? ? ? ? 將?t?指向的字符串鏈接到?s?指向字符串的末尾
strncat(char* s,char* t,int n)? ? ? 將?t?指向的字符串的前?n?個字符鏈接到?s?指向的字符串的末尾
strcmp(char*? s ,char*? t )? ?? ? ? ? ?將?s?指向的字符串和?t?指向的字符串進行比較,并返回一個? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int值。
strncmp(char*? s ,char*? t )?? ? ? ? ? ? ? ?將 s 指向的字符串和t指向的字符串比較前 n 個字符,返? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?回 一 個int值? ? ?
strcpy(char* s,char* t)? ? ? ? ? ? ? ? ? ? ?將 t 指向的字符串拷貝到 s 位置上
strncpy(char* s,char* t,int n)? ? ? ?將 t 指向的字符串的前 n 個字符拷貝到 s 位置上
strlen(char* s)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?返回 s 指向的字符串的長度
strchr(char* s , int c )? ? ? ? ? ? ? ? ? ? ? s 指向的字符串中查找 c,若找到,則返回它指向第一次? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 出現位置的指針,否則返回 NULL
strrchar(char* s , int c)