1. 字符串操作
1.1 字符串遍歷
可以通過(guò)數(shù)組方式遍歷字符串。
char* str="Hello World";
for(int i = 0;'\0' != str[i];++i){
printf("%c\n",str[i]);
}
也可以使用指針?lè)绞?/p>
char* str="Hello World";
for(int i = 0;'\0' != *str;++i){
printf("%c\n",*(str+i));
}
指針?lè)绞娇梢院?jiǎn)化成
char* str="Hello World";
for(;'\0' != *str;++str){
printf("%c\n",*str);
}
甚至是
while('\0' != *str){
printf("%c\n",*str++);
}
1.2 字符串賦值
char* s = "Hello World";
char* t;
t = s;
printf("%s\n",t);
沒(méi)有產(chǎn)生新的字符串,只是s和t指向相同的字符串。下面是查看兩個(gè)字符串的地址。
printf("%p\n",s);
printf("%p\n",t);
1.3 字符串輸入輸出
char str[8];
scanf("%s",str);
printf("%s\n",str);
scanf()讀入一個(gè)單詞直到空白符(空格、回車(chē)、Tab)
scanf()不安全,因?yàn)椴恢酪x入的內(nèi)容長(zhǎng)度,容易溢出。
例如:輸入123456789
解決方式:指定讀取的長(zhǎng)度。
char str[8];
scanf("%7s",str);
printf("%s\n",str);
%與s之間的數(shù)字表示最多允許輸入的字符數(shù),這個(gè)數(shù)字要比數(shù)組長(zhǎng)度少1。
2. 字符串與函數(shù)
2.1 字符串傳參
字符串傳參方式與數(shù)組傳參方式一樣,只不過(guò)很多時(shí)候不需要傳遞字符串的長(zhǎng)度(為什么?)。
void print_string(char str[]){
printf(str);
}
或者
void print_string(char* str){
printf(str);
}
2.2 字符串返回
字符串返回只能使用指針char*
3. 練習(xí)
- 交換
實(shí)現(xiàn)字符串交換函數(shù)void swap(char* s1,char* s2) - 拼接
實(shí)現(xiàn)字符串拼接函數(shù)char* strcat(char* s1,char* s2) - 拷貝
實(shí)現(xiàn)字符串拷貝函數(shù)char* strcpy(char* s1,char* s2) - 比較
實(shí)現(xiàn)字符串相等判斷函數(shù)bool strcmp(char* s1,char* s2)
4. 字符串指針與字符數(shù)組的區(qū)別
4.1 sizeof與strlen()
#include <stdio.h>
#include <string.h>
int main(){
char arr[] = "Hello World";
char* ptr = "Hello World";
printf("sizeof(arr) = %ld\n",sizeof(arr));
printf("strlen(arr) = %ld\n",strlen(arr));
printf("sizeof(ptr) = %ld\n",sizeof(ptr));
printf("strlen(ptr) = %ld\n",strlen(ptr));
}
4.2 替換字符
試一下下面三個(gè)例子
- 修改字符數(shù)組
#include <stdio.h>
#include <string.h>
int main(){
char arr[] = "Hello World";
arr[0] = `h`;
arr[6] = `w`;
printf("%s\n",arr);
}
- 字符串指針
#include <stdio.h>
#include <string.h>
int main(){
char* ptr = "Hello World";;
*ptr = `h`;
*(ptr+6) = `w`;
printf("%s\n",ptr);
}
- 指向字符數(shù)組的字符串指針
#include <stdio.h>
#include <string.h>
int main(){
char arr[] = "Hello World";
char* ptr = arr;
*ptr = `h`;
*(ptr+6) = `w`;
printf("%s\n",ptr);
}
-
const字符數(shù)組
#include <stdio.h>
#include <string.h>
int main(){
const char arr[] = "Hello World";
arr[0] = 'h';
arr[6] = 'w';
printf("%s\n",arr);
}
- 指向
const字符數(shù)組的字符串指針
#include <stdio.h>
#include <string.h>
int main(){
const char arr[] = "Hello World";
char* ptr = arr;
*ptr = 'h';
*(ptr+6) = 'w';
printf("%s\n",ptr);
}
決定能否修改的是指針指向的值能否修改。
const的限制只針對(duì)定義為const的變量。
4.3 字符串字面量初始化
字符串字面量初始化字符數(shù)組
字符串字面量初始化字符串指針
char* str1 = "Hello World";
char str2[] = "Hello World";
str1[5] = '\0'; // Error
str2[5] = '\0'; // OK
printf("str1=%s\n",str1);
printf("str2=%s\n",str2);
str1是一個(gè)指針,初始化指向一個(gè)字符串常量。(在C99標(biāo)準(zhǔn)中,str1報(bào)警告,提示應(yīng)該使用const char*)
修改字符串常量可能會(huì)導(dǎo)致嚴(yán)重后果。
str2是一個(gè)字符數(shù)組,初始化把字符串字面量自動(dòng)復(fù)制到數(shù)組中。
如何選擇?
- 如果需要構(gòu)造字符串使用數(shù)組;如果需要處理字符串使用指針。
- 字符串不需要修改使用字符串字面量初始化字符串指針。
- 字符串需要修改使用字符串字面量初始化字符數(shù)組。
5. 字符串函數(shù)
5.1 字符串長(zhǎng)度
size_t strlen(const char *s);
返回字符串長(zhǎng)度不包含\0。
5.2 字符串比較
int strcmp(const char *s1,const char *s2);
比較兩個(gè)字符串
返回0,表示s1 == s2
返回>0,表示s1 > s2
返回<0,表示s1 < s2
為什么字符串不能直接比較?
為什么字符串比較會(huì)有大?。?/p>
5.3 字符串拷貝
char* strcpy(char* restrict dst,const char* restrict src);
把字符換src拷貝到dst。
restrict是C99關(guān)鍵字,表示src和dst不能重疊,便于并行處理。
返回值為dst,便于連接。
連續(xù)賦值。
復(fù)制一個(gè)字符串
// char* dst = (char*)malloc(strlen(src)+1);
char dst[strlen(src)+1];
strcpy(dst,src);
5.4 字符串連接
char* strcat(char* restrict s1,const char*restrict s2);
把s2拷貝到s1的后面,拼接成一個(gè)長(zhǎng)的字符串。
返回s1,注意:s1必須有足夠的空間。
char* a="Hello";
char* b="World";
char res[strlen(a)+strlen(b)+1] = {0};
strcat(strcat(res,a),b);
strcpy和strcat都會(huì)有安全問(wèn)題:dst空間不足,出現(xiàn)越界。
5.5 字符查找
char* strchr(const char*s,int c);
char* strrchr(const char*s,int c);
返回找到字符的指針,沒(méi)找到返回NULL
如何查找第二個(gè)?
5.6 子串查找
char* strstr(const char*s1,const char*s2);
char* strcasestr(const char*s1,const char*s2);
6. 文檔
學(xué)會(huì)通過(guò)例子,學(xué)會(huì)函數(shù)的使用。
stdio.h
stdlib.h
string.h
復(fù)制
連接
比較
查找
- strchr:查找字符串中第一個(gè)出現(xiàn)指定字符的位置
- strrchr:查找字符串中最后一個(gè)出現(xiàn)指定字符的位置
- strstr:查找字符串中第一個(gè)出現(xiàn)指定子串的位置
- strtok:切分字符串
其他
練習(xí)
實(shí)現(xiàn)函數(shù)times(char* dst,int n,char* src)
7. 字符串?dāng)?shù)組與字符串指針數(shù)組
7.1 字符串?dāng)?shù)組
字符串?dāng)?shù)組,可以看成二維字符數(shù)組,只是初始化可以使用字符串方式。
char arr[12][10] = {"January","February","March","April",
"May","June","July","August",
"September","October","November","December"};
簡(jiǎn)化
char arr[][10] = {"January","February","March","April",
"May","June","July","August",
"September","October","November","December"};
7.2 字符串指針數(shù)組
char* arr[12] = {"January","February","March","April",
"May","June","July","August",
"September","October","November","December"};
簡(jiǎn)化
char* arr[] = {"January","February","March","April",
"May","June","July","August",
"September","October","November","December"};
7.3 字符串?dāng)?shù)組與字符串指針數(shù)組的區(qū)別
- 大小的區(qū)別
char arr1[][10] = {"January","February","March","April",
"May","June","July","August",
"September","October","November","December"};
char* arr2[] = {"January","February","March","April",
"May","June","July","August",
"September","October","November","December"};
printf("sizeof(arr1)=%d\n",sizeof(arr1));
printf("sizeof(arr2)=%d\n",sizeof(arr2));
- 二維指針的區(qū)別
#include <stdio.h>
int main () {
char arr1[][10] = {"January","February","March","April",
"May","June","July","August",
"September","October","November","December"};
char* arr2[] = {"January","February","March","April",
"May","June","July","August",
"September","October","November","December"};
char** p1 = arr1;
for(int i=0;i<12;++i){
printf("%s\n",p1[i]);
}
char** p2 = arr2;
for(int i=0;i<12;++i){
printf("%s\n",p2[i]);
}
return 0;
}
8. 實(shí)踐
已知十天干和十二地支
天干:甲、乙、丙、丁、戊、己、庚、辛、壬、癸
地支:子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥
按順序打印出六十甲子
甲子、乙丑、丙寅、丁卯、戊辰、己巳、庚午、辛未、壬申、癸酉、
甲戌、乙亥、丙子、丁丑、戊寅、己卯、庚辰、辛巳、壬午、癸未、
甲申、乙酉、丙戌、丁亥、戊子、己丑、庚寅、辛卯、壬辰、癸巳、
甲午、乙未、丙申、丁酉、戊戌、己亥、庚子、辛丑、壬寅、癸卯、
甲辰、乙巳、丙午、丁未、戊申、己酉、庚戌、辛亥、壬子、癸丑、
甲寅、乙卯、丙辰、丁巳、戊午、己未、庚申、辛酉、壬戌、癸亥已知今年的紀(jì)年,輸入21世紀(jì)任意年份,打印出對(duì)應(yīng)的甲子。
已知今年的紀(jì)年,打印出21世紀(jì)所有年份的甲子。
已知小明同學(xué)的屬相,推斷出可能的年齡。
9. main()參數(shù)與返回值
9.1 main()參數(shù)
main()的完全形式是這樣的。
int main(int argc,char* argv[])
或者
int main(int argc,char** argv)
其中,argc是命令與參數(shù)數(shù)量。argv是命令和參數(shù)組成的字符串?dāng)?shù)組。argv[0]是命令本身。其余是參數(shù)。
int main(int argc,char* argv[]){
for(int i=0;i<argc;++i){
printf("%d:%s",i,argv[i]);
}
return 0;
}
9.2 main()返回值
main()返回值是與調(diào)用程序交互的,返回程序執(zhí)行狀態(tài)。通常0表示執(zhí)行成功,非零表示執(zhí)行失敗。
int main(){
int n;
printf("請(qǐng)輸入一個(gè)整數(shù):");
scanf("%d",&n);
return n;
}
在終端執(zhí)行程序后,接著執(zhí)行echo $?可以看到返回值。
10. 擴(kuò)展
char*一定是字符串嗎?
char*不一定是字符串,只有以0結(jié)尾的字符數(shù)組才是字符串。
10.1 0、'\0'與'0'
0與'\0'
'\0'表示字符串的結(jié)束,但不是字符串的一部分。計(jì)算字符串長(zhǎng)度時(shí)不包含'\0'。
字符串以數(shù)組方式存儲(chǔ),可以用數(shù)組或者指針形式訪問(wèn)。
10.2 空字符串
char str[10]="";
這是一個(gè)空字符串,str[0]為\0。
char str[]="";
這是也是一個(gè)空字符串,str數(shù)組長(zhǎng)度為1。
常見(jiàn)錯(cuò)誤:使用未初始化的char*
char* str;
printf("%s\n",str);
同常如果指針定義時(shí)無(wú)法確定初始值時(shí),使用NULL初始化指針。
10.3 字符串常量連接
兩個(gè)相鄰字符串常量會(huì)自動(dòng)連接。
char greeting = "Hello" "World";
小禮
作者:jdzhangxin
鏈接:http://www.itdecent.cn/p/0eb5ad941416
侵刪。