2019-04-01 C初階3:字符串

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)生新的字符串,只是st指向相同的字符串。下面是查看兩個(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í)

  1. 交換
    實(shí)現(xiàn)字符串交換函數(shù)void swap(char* s1,char* s2)
  2. 拼接
    實(shí)現(xiàn)字符串拼接函數(shù)char* strcat(char* s1,char* s2)
  3. 拷貝
    實(shí)現(xiàn)字符串拷貝函數(shù)char* strcpy(char* s1,char* s2)
  4. 比較
    實(shí)現(xiàn)字符串相等判斷函數(shù)bool strcmp(char* s1,char* s2)

4. 字符串指針與字符數(shù)組的區(qū)別

4.1 sizeofstrlen()

#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è)例子

  1. 修改字符數(shù)組
#include <stdio.h>
#include <string.h>

int main(){
    char arr[] = "Hello World";
    arr[0] = `h`;
    arr[6] = `w`;
    printf("%s\n",arr);    
}

  1. 字符串指針
#include <stdio.h>
#include <string.h>

int main(){
    char* ptr = "Hello World";;
    *ptr = `h`;
    *(ptr+6) = `w`;
    printf("%s\n",ptr);    
}

  1. 指向字符數(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);    
}

  1. 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);    
}

  1. 指向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ù)組中。

如何選擇?

  1. 如果需要構(gòu)造字符串使用數(shù)組;如果需要處理字符串使用指針。
  2. 字符串不需要修改使用字符串字面量初始化字符串指針。
  3. 字符串需要修改使用字符串字面量初始化字符數(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

  • sprintf:數(shù)據(jù)按格式寫(xiě)入字符串
  • sscanf:按格式從字符串讀出數(shù)據(jù)

stdlib.h

  • atof:字符串轉(zhuǎn)浮點(diǎn)數(shù)
  • atoi:字符串轉(zhuǎn)整數(shù)
  • atol:字符串轉(zhuǎn)長(zhǎng)整數(shù)

string.h

復(fù)制

  • strcpy:字符串拷貝
  • strncpy:指定個(gè)數(shù)字符串拷貝

連接

  • strcat:字符串連接
  • strncat:指定個(gè)數(shù)字符串連接

比較

  • strcmp:字符串比較
  • strncmp:指定個(gè)數(shù)字符串比較

查找

  • strchr:查找字符串中第一個(gè)出現(xiàn)指定字符的位置
  • strrchr:查找字符串中最后一個(gè)出現(xiàn)指定字符的位置
  • strstr:查找字符串中第一個(gè)出現(xiàn)指定子串的位置
  • strtok:切分字符串

其他

  • strerror:獲取出錯(cuò)信息
  • strlen:獲取字符串長(zhǎng)度

練習(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ū)別

  1. 大小的區(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));

  1. 二維指針的區(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í)踐

  1. 已知十天干和十二地支
    天干:甲、乙、丙、丁、戊、己、庚、辛、壬、癸
    地支:子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥
    按順序打印出六十甲子
    甲子、乙丑、丙寅、丁卯、戊辰、己巳、庚午、辛未、壬申、癸酉、
    甲戌、乙亥、丙子、丁丑、戊寅、己卯、庚辰、辛巳、壬午、癸未、
    甲申、乙酉、丙戌、丁亥、戊子、己丑、庚寅、辛卯、壬辰、癸巳、
    甲午、乙未、丙申、丁酉、戊戌、己亥、庚子、辛丑、壬寅、癸卯、
    甲辰、乙巳、丙午、丁未、戊申、己酉、庚戌、辛亥、壬子、癸丑、
    甲寅、乙卯、丙辰、丁巳、戊午、己未、庚申、辛酉、壬戌、癸亥

  2. 已知今年的紀(jì)年,輸入21世紀(jì)任意年份,打印出對(duì)應(yīng)的甲子。

  3. 已知今年的紀(jì)年,打印出21世紀(jì)所有年份的甲子。

  4. 已知小明同學(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
侵刪。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容