### 字符串
C語言里規定文字信息必須記錄在一組連續的字符存儲區里。
所有文字信息必須以'\0'字符做結尾,這個字符就是ASCII碼的0。
符合以上兩種特征的內容叫字符串,C語言里用字符串記錄文字信息。
字符串里'\0'字符前面的字符叫有效字符。
所有的字符串都可以采用一個字符指針來表示。
字符串字面值是一種字符串,用兩個雙信號中間的一組字符表示,例如: "dsg", "!@%Q#"等。
編譯器在編譯的時候會自動在字符串字面值的末尾增加一個'\0'字符。
/*
字符串演示
*/
#include <stdio.h>
int main(){
printf("%p\n", "abc");
printf("%c\n", *"abc");
printf("%c\n", *("abc" + 3));
return 0;
}
字符串字面值的內容,在程序執行過程中是不可改變的。
程序里內容一樣的字符串字面值其實是同一個。
/*
字符串演示
*/
#include <stdio.h>
int main(){
printf("%p\n", "abc");
printf("%p\n", "abc");
return 0;
}
多個并列的字符串字面值會被合并成一個。
/*
字符串演示
*/
#include <stdio.h>
int main(){
printf("%p\n", "abc");
printf("%p\n", "ab""c");
return 0;
}
### 字符數組
字符數組也可以用來記錄字符串。
并不是所有的字符數組都可以當字符串使用,只有包含'\0'字符的字符數組才可以當字符串使用。
可以使用字符串字面值對字符數組進行初始化,這個時候編譯器會吧字符串字面值里的'\0'字符初始化到字符數組里。
#include <stdio.h>
int main(){
char str[] = "abcxyz";
printf("sizeof = %ld\n", sizeof(str));
return 0;
}
字符數組里的字符串內容可以修改。
可以在printf函數調用語句里使用%s作為占位符把字符串里的有效字符顯示出來。
#include <stdio.h>
int main(){
char str[] = "abcxyz";
printf("%s\n", str);
return 0;
}
### 字符串的標準函數
不可以在程序里使用操作符來操作字符串,而應該使用一組標準函數。
為了使用這些標準函數,需要包含string.h頭文件。
**strlen**
這個函數用來統計字符串里有效字符個數。
#include <stdio.h>
#include <string.h>
int main(){
char str[10] = "abcdef";
printf("%ld\n", strlen(str));
return 0;
}
這個函數和sizeof完全沒有關系。
**strcat**
用來合并兩個字符串的,但是這種方式不可控,有可能會修改不屬于數組的存儲區,造成嚴重的后果
實例:
/*
strcat 演示
*/
#include <stdio.h>
#include <string.h>
int main(){
char str[10] = "abc";
strcat(str, "xyz"); // 將第二個參數合并到第一個參數
printf("str = %s\n", str);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
str = abcxyz
**strncat**
這個函數和strcat類似,但是它是可以修改不屬于數組的存儲區
實例:
/*
strncat 演示
*/
#include <stdio.h>
#include <string.h>
int main(){
char str[10] = "abc";
strncat(str, "asdfrgasfg", 3); // 將第二個參數的前三位合并到一個參數的字符數組中
printf("str = %s\n", str);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
str = abcxyz
**strcmp**
用來比較兩個字符串的大小,返回值是1表示前一個字符串大,返回值是-1表示后一個字符串大,返回值是0表示一樣大,這個函數的比較是字符串穿從左到右每個字符在ASCII中代表的數字的大小
實例:
/*
strcmp 演示
*/
#include <stdio.h>
#include <string.h>
int main(){
printf("比較的結果是:%d\n", strcmp("aqwe", "arwe"));
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
比較的結果是:-1
**strncmp**
和strncmp類似,但是這個函數只比較兩個字符串的前n個字符
實例:
/*
strcmp 演示
*/
#include <stdio.h>
#include <string.h>
int main(){
printf("比較的結果是:%d\n", strcmp("aqwe", "arwe", 2));
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
比較的結果是:-1
**strcpy**
用來把一個字符串復制到一個字符串數組里,這個函數有可能修改不屬于數組的存儲區,造成嚴重的錯誤
實例:
/*
strcpy 演示
*/
#include <stdio.h>
#include <string.h>
int main(){
char str[10] = "abcdef";
strcpy(str, "xyz");
printf("str = %s\n", str);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
str = xyz
**strncpy**
功能和strcpy類似,但是可以限制復制的字符的個數,可以保證不會修改不屬于數組的存儲區
實例:
/*
strcpy 演示
*/
#include <stdio.h>
#include <string.h>
int main(){
char str[10] = "abcdef";
strcpy(str, "xyz", 2);
printf("str = %s\n", str);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
str = xycdef
**memset**
可以把字符數組里多個存儲區的內容設置成同一字符
實例:
/*
memset 演示
*/
#include <stdio.h>
#include <string.h>
int main(){
char str[10] = "abc";
memset(str, 'z', 5); // str字符數組中的前五個字符全部設置成z
printf("str = %s\n", str);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
str = zzzzz
**strstr**
用來在一個大字符串里查找小字符串的位置,如果找不到返回值是NULL
實例:
/*
strstr 演示
*/
#include <stdio.h>
#include <string.h>
int main(){
printf("找到的字符為:%s\n", strstr("asdfdfg", "dfg"));
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
找到的字符為:dfg
**sprintf**
按照格式把多個數字轉成一組字符并記錄到字符數組里形成字符串
實例:
/*
sprintf 演示
*/
#include <stdio.h>
int main(){
char str[20] = {0};
sprintf(str, "%c %d %g", 'a', 5, 2.1f);
printf("str = %s\n", str);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
str = a 5 2.1
**sscanf**
按照格式從字符串里獲得數字并記錄到存儲區里
實例:
/*
sscanf 練習
*/
#include <stdio.h>
int main(){
char ch = 0;
int num = 0;
float fnum = 0.0f;
sscanf("p 18 165.5", "%c%d%g", &ch, &num, &fnum);
printf("%c %d %g\n", ch, num, fnum);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
p 18 165.5
**atoi**
可以把字符串中整數轉成整數類型,僅能或轉換字符串前面連貫的數字
實例:
/*
字符串演示
*/
#include <stdio.h>
#include <stdlib.h>
int main(){
int num = atoi("34asdfasd3");
printf("num = %d\n", num);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
num = 34
**atof**
可以字符串里的浮點數轉換成雙精度浮點類型
實例:
/*
atof演示
*/
#include <stdio.h>
#include <stdlib.h>
int main(){
double dnum = 0.0;
dnum = atof("23.867asderg");
printf("dnum = %lg\n", dnum);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
dnum = 23.867
**fgets**
在scanf函數調用語句里使用%s作為占位符可以把用戶在鍵盤輸入的字符串記錄到鍵盤里,使用這種辦法會產生嚴重錯誤,修改不屬于字符數組的存儲區
fgets函數也可以從鍵盤得到一個字符串并記錄到字符數組中,這個函數可以避免scanf函數的問題
函數參數:
1. 數組名稱
2. 數組里的存儲區
3. 用stdin表示鍵盤
如果輸入的內容不能充滿數組,就會把用戶最后輸入的換行字符也讀入到數組里
若果輸入的內容超過數組能容納的范圍就把多余的部分留給下次讀,也就是階段
實例:
#include <stdio.h>
#include <string.h>
int main(){
char str[10] = {0};
printf("請輸入一個字符串:");
fgets(str, 10, stdin);
// 清理緩沖區里的數據
if (strlen(str) == 9 && str[8] != '\n'){
scanf("%*[^\n]");
scanf("%*c");
}
printf("%s\n", str);
return 0;
}
結果:
lanyulei@lanyulei-c:$ ./a.out
請輸入一個字符串:asdfasgasgrawsrgasdf
asdfasgas
在使用fgets函數從鍵盤得到字符串以后必須清理輸入緩沖區里可能存在的多余數據。
清理語句應該放在分支里,分支需要保證輸入緩沖區里存在多余數據。
if (strlen(str) == 9 && str[8] != '\n'){
scanf("%*[^\n]");
scanf("%*c");
}