280 likes | 482 Views
第 8 章 字符串. 字符串的基本概念 字符数组 字符串与指针 常用的字符串处理函数. 8.1 什么是字符串. 字符串是一系列字符的有序集合,具有整体特性。 C 语言没有专门提供字符串数据类型。 C 语言中的字符串通过一个以空字符‘ ’ 作为结束符的一维字符数组来表示。 '' 的作用是标志字符串结束,其 ASCII 码值为 0 。 ' ' 作为标志占用存储空间,但不计入字符串的实际长度。. 8.2 字符数组. 字符数组是用来存放字符型数据的数组。其定义和引用方式与一维数组相同。在字符数组中,每一个数组元素只能存放一个字符。
E N D
第8章 字符串 • 字符串的基本概念 • 字符数组 • 字符串与指针 • 常用的字符串处理函数
8.1什么是字符串 • 字符串是一系列字符的有序集合,具有整体特性。 • C语言没有专门提供字符串数据类型。C语言中的字符串通过一个以空字符‘\0’作为结束符的一维字符数组来表示。 • '\0'的作用是标志字符串结束,其ASCII码值为0。'\0 '作为标志占用存储空间,但不计入字符串的实际长度。
8.2 字符数组 • 字符数组是用来存放字符型数据的数组。其定义和引用方式与一维数组相同。在字符数组中,每一个数组元素只能存放一个字符。 • 字符数组有两种用法:一是当作字符的数组来使用,对字符数组的输入、输出、赋值、引用等都是针对单个元素进行的;二是用于存储和处理字符串,将字符串作为一个整体进行操作。但字符数组不等同于字符串变量。 8.2.1 字符数组的定义 1.字符数组的定义 char字符数组名[常量表达式]; char str[80]; • 一个一维字符数组可以用来存放一个字符串。
8.2.1 字符数组的定义 2.字符数组的初始化 char 字符数组名[常量表达式]={初值表}; (1)用字符常量对字符数组初始化 char str1[10]={ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; char str2[10]={ 'a', 'b ', 'c', 'd', 'e'}; (2)用字符串常量对字符数组初始化 char str4[9]={"computer"}; char str4[9]="computer"; char str4[]="computer"; • str4的长度为“实际串长+1”
8.2.1 字符数组的定义 3.字符数组的引用 char i, stra[26],c[4]; c[0]='A' ; c[1]=66; c[2]= c[0]+1; /* 等价于赋值字母B */ c[3]= c[1]-1; /* 等价于赋值字母A */ stra[0]='A'; for (i=1;i<=25;i++) /*将字母A到Z共26个字符存放至数组stra中*/ stra[i]= stra[i-1]+1 ; • 不可以为字符数组整体赋值。 char str[10]; str="computer"; × char str1[10]="computer",str2[10]; str2=str1; ×
8.2.1 字符数组的定义 4.字符数组和字符串的区别 • 字符串的最后一个字符是字符串结束标志‘\0’,而字符数组的最后一个字符不限定必须是‘\0’。 • 可以用字符数组来存放字符串,但不能通过赋值语句将字符串常量等直接赋给字符数组。字符串是字符数组的一种具体应用。
8.2 字符数组 8.2.2 字符数组的输入输出 1.单个字符输入输出 • 利用格式符%c,调用scanf()或printf()函数对字符数组中的数组元素逐个字符地输入或输出。 char s[11]; int i; printf("请输入10个字符: \n"); for (i=0;i< 10;i++) /* 向字符数组s中逐个输入字符 */ scanf("%c",&s[i]); s[i]='\0'; /*最后人为加上字符串结束标志*/ printf("\n 输入的字符序列为:\n"); for (i=0;i< 10;i++) /* 通过循环输出每一个字符 */ printf("%c",s[i]);
8.2.2 字符数组的输入输出 2.字符串整体输入输出 • 利用格式符%s,调用scanf()或printf()函数实现字符串整体的输入或输出。 char s[11]; printf("请输入10个字符: \n"); scanf("%s",s); /* 向字符数组中输入字符串 */ printf("输入的字符序列为:\n"); printf("%s",s); /* 输出字符数组中的字符串 */ scanf("%s", &s[0]); scanf("%s", &s); printf("%s\n", s[0]); × • scanf()函数读入的字符串开始于第一个非空白符,包括下一个空白符之前的所有字符,最后自动加上字符串结束标志‘\0’。 • printf()函数在输出字符串时,一旦遇到'\0',就停止输出,输出字符中不包含'\0'。
8.2.2 字符数组的输入输出 3.gets()字符串输入函数 gets(str) str可以是字符数组名或字符串指针变量名 • gets()函数的作用是从终端键盘读入字符串(包括空格符),当遇到第一个回车符时结束输入。在读入一个字符串后,系统会自动在字符串后加上字符串结束标志‘\0’。函数调用的返回值为字符数组的首地址。 • gets()函数读入字符串时是以回车符结束输入,因此可以读入含空格、制表符的字符串。 输入: program C↙ program C↙ 输出为: str1: program C str2: program char str1[20],str2[20]; gets(str1); scanf("%s",str2); printf("str1: %s\n",str1); printf("str2: %s\n",str2);
8.2.2 字符数组的输入输出 4.puts()字符串输出函数 puts(str) str可以是字符数组名或字符串指针变量名 • puts()函数的作用是将字符串输出,当遇到字符串结束标志'\0'时结束。同时将'\0'转换为回车符,即输出后自动换行。 char str1[20]= "Great Wall",str2[20] ="Guiyuan Trmple",str3[20] ="Yellow Crane Tower"; puts(str1); printf("%s\n%s\n",str2,str3); 输出为: Great Wall Guiyuan Trmple Yellow Crane Tower
8.3字符串与指针 • 可用一个指针指向一个字符串,这个指针中存放的是字符串的首字符地址 。 • 字符串指针变量是C语言中表示字符串的第二种方法。指向字符串的指针变量等同于指向字符型数组元素的指针变量,可以指向字符串中的任意一个字符。通常将指向字符串的指针变量称为字符指针。 8.3.1 字符指针的定义 1.字符指针的定义和初始化 char *字符指针变量名; char *字符指针变量名=初始地址值; char *ptr="Welcome to study C program language! "; /*定义字符指针变量ptr,并进行初始化*/ printf("%s\n", ptr); /*输出ptr指针变量所指向的字符串*/ char str[]=“Welcome to study C program language! ”, *ptr=str;/*指针变量指向一个已定义的数组 */
8.3.1字符指针的定义 2.通过赋值运算使字符指针指向一个字符串 char *ptr; ptr="Welcome to study C program language!"; • 对于已定义的字符指针,可以通过赋值运算将某个字符串的首地址赋给该字符指针,使它指向一个具体的字符串。 【例8-3】 字符指针应用例子:编程实现将字符串str1复制到字符串str2(不使用strcpy()函数)。 char str1[]="Copy string", str2[30]; char *ptr1, *ptr2; ptr1=str1; /*通过赋值语句使ptr1指向了存放字符串的数组str1的首地址*/ ptr2=str2; /*指针ptr2指向了存放字符串的字符数组str2的首地址*/ for (;*ptr1!='\0';ptr1++,ptr2++) *ptr2=*ptr1; *ptr2='\0';
8.3字符串与指针 8.3.2 字符数组与字符指针的比较 • 字符数组是由若干个元素组成,每个元素存放一个字符,字符数组占有连续的内存空间。而字符指针是一个指针变量,只存放了字符串的首地址,而不是整个字符串。 char str[]="Computer"; char *ptr=" Computer"; • 赋值方式不同。对字符数组的赋值只能是对各个元素分别赋值,而对字符指针赋予的是字符串的首地址。 • 对于字符数组,读入一个字符串时可以采用下面的方法: • char str[80]; scanf("%s",str); • 但对于字符指针,如下的方法是错误的: • char *ptr; scanf("%s",ptr);
8.3.2 字符数组与字符指针的比较 • 字符指针的值在程序运行过程中可以被改变,但字符数组的地址是不能被改变的。指针变量中所存放的地址在程序中可以根据需要灵活地变化,而数组名代表的是该数组的首地址,而且是在程序一开始运行就被分配好的,在程序运行过程中不会变化。 char *ptr="Welcome to study C program language!"; printf("%s\n",ptr); /*输出Welcome to study C program language!*/ ptr+=11; /* 改变了指针变量的值 */ printf("%s\n",ptr); /*输出study C program language!*/ 【例8-4】 判断字符串是否回文,所谓回文是指字符串正读和倒读相同。如字符串"abcdcba"是回文。
8.3.2 字符数组与字符指针的比较 #include <stdio.h> #include <string.h> int main(void) { char str[80],*ptr1,*ptr2; int flag=1; printf("\n请输入字符串: "); gets(str); ptr1=str; /*ptr1指向数组str的开始*/ ptr2=str; while((*ptr2)!= '\0') ptr2++; ptr2--; /*ptr2指向str的最后一个字符*/ while((ptr1<ptr2)&&flag) { if (*ptr1!=*ptr2) flag=0; else { ptr1++; ptr2--; } } /*判断是否回文*/ if (flag) printf("\n字符串%s是回文\n",str); else printf("\n字符串%s不是回文\n",str); return 0;}
8.3字符串与指针 8.3.3 字符指针作为函数参数 • 将一个字符串从主调函数传递到被调用函数,可以使用地址传递的方法,即用字符数组名或字符指针变量作为参数。在被调用函数中可以改变字符串的内容,在主调函数中可以得到被改变了的字符串。 【例8-5】 编写函数strcat(),连接给定的两个字符串str1和str2,连接后的结果放在str1中。 • 算法分析:设str1和str2分别指向“Hello ”和“World! ”两个字符串。连接两个字符串就是将str2中所有字符接到str1的后面。str1所占存储单元应大于等于连接前其中的字符串长度加str2的长度再加1。因为主调函数与被调用函数都要对str1和str2进行操作,而且要在被调用函数中修改主调函数中str1的值,因此函数调用时用指针作为参数来传值。
8.3.3 字符指针作为函数参数 #include <stdio.h> void strcat(char *,char *); int main(void) { char str1[15]="Hello ", str2[ ]="World!"; strcat(str1,str2); printf("String str1=%s\n",str1); return 0;} void strcat(char *s, char *t) { while(*s!='\0') s++; /* 使s指向字符串str1的结尾 */ while(*t!='\0') { *s=*t; s++; t++; } *s='\0'; /* 在s后加上字符串结束标志 */ }
8.4字符串处理函数 • 在C语言的标准函数库中,专门提供了一些处理字符串的函数.。 • 命令行指定包含标准头文件 #include <string.h>。 8.4.1 字符串长度函数strlen() strlen (str) • strlen()函数的作用是计算并返回字符串str的有效长度(不包含字符'\0')。 8.4.2 字符串连接函数strcat() strcat(str1, str2 ) • strcat()函数的作用是将字符串str2连接在字符串str1后面,原str1结尾的'\0'被自动覆盖,连接后的新字符串的结尾自动加上'\0',生成的连接串存放在str1中。函数返回值为字符串str1的首地址。
8.4字符串处理函数 8.4.3 字符串复制函数strcpy() strcpy(str1, str2) • strcpy()函数的作用是将字符串str2的内容连同'\0'一起复制到str1中。函数返回值为字符串str1的首地址。 8.4.4 字符串比较函数strcmp() strcmp(str1, str2) • strcmp()函数的作用是比较str1和str2两个字符串的大小。字符串比较的规则是:对两个字符串逐个字符比较ASCII码值的大小,直至遇到不同的字符或者遇到结束符'\0'为止。 • 两个字符串相等,函数返回值为0。 • 字符串1大于字符串2,函数返回值为正整数。 • 字符串1小于字符串2,函数返回值为负整数。
8.4.4 字符串比较函数strcmp() #include <stdio.h> #include <string.h> int main(void) { char str1[20]="China", str2[20]="China",str3[20]= "Chinese"; printf("strcmp(str1,str2)=%d\n", strcmp(str1,str2)); printf("strcmp(str1,str3)=%d\n", strcmp(str1,str3)); printf("strcmp(str3,str1)=%d\n", strcmp(str3,str1)); return 0; }
8.5字符串数组 • 所谓字符串数组就是这个数组中的每个元素又都是一个存放字符串的一维数组。 • 二维字符数组可以看成是一维的字符串数组。 8.5.1 字符串数组的定义 1.字符串数组的定义 char字符数组名[常量表达式1] [常量表达式2]; • 常量表达式1决定了字符串的个数,常量表达式2决定了字符串的最大长度 。 • char str[5][10]; • str是一个具有5个字符串元素的一维字符串数组,每个字符串元素的最大长度为10个字符。
8.5.1 字符串数组的定义 2.字符串数组的初始化 • 对于二维字符数组进行初始化,可以用字符常量和字符串赋初值两种方法。 char stra1[2][3]={ {'0', '1', '2'},{'3', '4', '5'}}; /*给全部数组元素赋初值*/ char stra2[2][3]={'0', '1', '2', '3'}; /*给部分字符数组元素赋初值*/ char stra3[][3]={ {'0', '1', '2'},{'3', '4', '5'}}; /*给全部数组元素赋初值省略指定第一维的长度*/ char strb[4][8] ={"ZHANG", "ZHOU", "HUANG", "LI"};
8.5字符串数组 8.5.2 字符串数组的引用和输入/输出 • 二维字符数组可当作一维字符串数组来使用,这个一维字符串数组中的每个数组元素是一个一维数组。对于一个m*n的二维字符数组,可看作m个一维字符数组来引用和输入/输出。也就是说,可以采用二维字符数组名加第一维下标作为一个一维字符数组名来使用。 • char strc[5][10] ={"China", "Korea", "USA", "India", "Russia"}; • 则strc[i]表示引用第i行的字符串,strc[i][j]表示引用第i行j列的字符。 1.字符串数组的赋值 • 除了对字符串数组赋初值外,还可以采用赋值运算符和字符串处理函数对字符串数组进行赋值操作。
8.5.2字符串数组的引用和输入/输出 • (1)使用C标准库函数中的字符串函数 • 可以使用字符串复制函数strcpy()进行字符串的赋值。 char strname[3][8] ={"WANG", "ZHOU", "LI"}; strcpy(strname[0],"ZHANG"); (2)使用赋值语句 2.字符串数组的输入 • 使用scanf()函数和gets()函数输入字符串到二维字符数组中。 scanf("%s", strname[0]); 3.字符串数组的输出 • 使用printf()函数输出二维字符数组中存储的字符串。 int i; char strname[3][8] ={"ZHANG", "ZHOU", "LI"}; for (i=0;i<3;i++) printf("%s\n", strname[i]); /* 输出第i行字符串 */
8.5.2字符串数组的引用和输入/输出 【例8-8】 编写一个程序,输入若干个姓氏的全拼(假设其中不含空格),然后在其中查找指定的姓氏。 #include <stdio.h> #include <string.h> #define N 5 int main(void) { int i; char str[N],strname[N][10]; for (i=0;i<N;i++) /*用字符串数组strname存储输入的姓氏全拼*/ scanf("%s",strname[i]); scanf(“%s”,str); /*输入查找的姓氏*/ for (i=0;i<N;i++) if (strcmp(strname[i],str)==0) /*使用strcmp()函数进行查找匹配*/ break; if (i<N) printf("找到!\n"); else printf("没有找到!\n"); return 0;}
8.5.3 字符型指针数组 • 由于指针数组的每个数组元素已指向确定的存储单元,因此,也可以用输入函数给这些字符串重新赋值。 有如下的语句:gets(ptra[1]); • 表示把从键盘上读入的字符串输入到ptra[1]所指向的字符串中。 【例8-9】 输入—个从星期日到星期六中一天的英文字符串,判断它是一个星期的第几天,如果该字符串不存在,则输出-1。 算法分析:用一个字符型指针数组week存储星期表,每行存一个字符串。编写查找函数find(),在星期表中查找输入的字符串str是否存在,如果找到,则输出是第几天,否则输出-1表示没有找到。
8.5.3 字符型指针数组 #include <stdio.h> #include <string.h> char *week[8]={ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL }; int find(char[ ]); int main(void) { int a;char str[20]; printf("Please input the weekday:\n"); scanf("%s", str); a=find(str); printf("It is %d\n",A); scanf("%s",str); return 0;} int find(char ch[ ]) { int i,j; char *p; for(i=0;week[i]!=NULL;i++) { for(j=0,p=week[i];*p==ch[j]&&*p!='\0';p++,j++); if(*p==ch[j]&&*p=='\0') return(i); } return(-1); }
8.6 应用举例 【例8-10】 输入一行字符,统计其中有多少个单词,单词之间用空格分隔。 算法分析:单词的数目可通过空格出现的次数确定,连续空格按一个处理,一行开头的空格不统计。程序中用num统计单词的个数,用word作为判断是否单词的标志,word=0表示未出现单词,word=1表示出现单词。 #include <stdio.h> int main(void) { char str[100], c; int i, num, word; num = word = 0; gets(str); for ( i = 0; ( c=str[i])!= '\0'; i++ ) if ( c == ' ') word = 0 ; else if ( word == 0) { word = 1 ; num ++; } printf("共有单词 :%d。\n ", num); return(0);}