1、1第十章字符串l知识点1:字符串l1.字符串常量l(1)C语言中字符串常量的形式,用一对双引号将一串字符括起来称为字符串常量。l例如:“abcd”.l(2)字符串的长度。一对双引号中字符的个数就是字符串的长度。可调用strlen函数求字符串长度,例如,strlen(“abcd”),字符串的长度为4.l(3)字符串的结束标志。在字符串最后一个字符的后面,系统自动添加一个转义字符0作为字符串的结束标志。当人为地在字符串中间插入转义字符0时,例:“a0bcd”,系统就认为字符串到a为止,长度为1,不再顾及0后的字符。2l(4)字符串常量的存储结构。1个字符串所占字节数为:字符串长度+1.例如字符串“
2、abcd”,在内存上5个字节,其字符占4个字节,字符串结束标志0占一个字节。可调用sizeof函数求字符串所占字节数,如:sizeof(“abcd”).l(5)字符串常量的面值和地址值。“abcd”是字符串的面值,而当把它赋给某个变量时,给出的是此字符串在内存所占连续存储区的首地址。3l2.一维字符数组和字符串变量l(1)一维字符数组的每个元素可以存放一个字符。l(2)当一维字符数组中存放最后一个字符是0时,可称此一维字符数组内存放了一个字符串,同时可称此一维数组为字符串变量。l3.通过赋初值给一维字符数组赋字符串l赋字符串初值形式:l(1)char s5=a,b,c,d,0;显示赋字符串结束
3、标志。l(2)char s5=a,b,c,d;系统会自动赋字符串结束标志。4l(3)char s5=“abcd”;直接赋字符串常量。l(4)char s5=“abcd”;把字符串常量放在一对花括号中。l(5)char s=“abcd”;根据所赋字符串初值来确定数组长度。l注意,若有定义:char s5=“aa”;,sizeof(s)的值为5,strlen(s)的值为2.前者是s在内存中所中字节数,后者是s中的字符个数。5l10-1有以下程序l main()l char a=a,b,c,d,e,f,g,h,0;l int i,j;l i=sizeof(a);l j=strlen(a);l pri
4、ntf(“%d,%dn”,i,j);l l程序运行后结果是lA.9,9 B.8,9 C.8,8 D.9,86l10-2有以下程序l#include l main()l char*p=“abcde0fghjik0”;l printf(“%dn”,strlen(p);l l程序运行后结果是lA.12B.15C.6D.57l10-3以下不能正确进行字符串赋初值的语句是lA.char str5=“good!”;lB.char str=“good!”;lC.char*str=“good!”;lD.char str5=g,o,o,d;8l10-4有以下程序l main()l char p20,*q=p;l
5、scanf(“%s%s”,p,q);printf(“%s%sn”,p,q);ll若从键盘输入:abc def,则输出结果是lA.def deflB.abc deflC.abc dlD.d d9l10-5有以下程序l main()l char s=“ABCD”,*p;l for(p=s+1;ps+4;p+)l printf(“%sn”,p);l l程序运行结果是lA.ABCD B.A C.B D.BCDl BCD B C CDl CD C D Dl D D 10l4.程序中给一维字符数组赋字符串l有定义char s5;l(1)不可以用赋值语句给s数组赋字符串。例如,s=“abcd”;是错误的,数
6、组名s是一个常量,不可重新赋值。l(2)可给数组元素一个一个赋字符:ls0=a;s1=b;。l(3)可调用strcpy函数把字符串复制到数组中。例如,strcpy(s,“abcd”).l(4)若有定义:char s110,s220;,可用%s格式,调用scanf函数给字符数组输入字符串。例如,scanf(“%s%s”,s1,s2);.l(5)用gets函数给字符数组输入一行字符串。例如,gets(s1);gets(s2);.输入的一串字符用回车结束。11l5.使指针指向字符串l(1)给基类型为char的指针赋字符串的地址,可通过以下赋初值方式使指针指向字符串常量。l char*sp=“abcd
7、”;把字符串“abcd”的首地址赋给基类型为char的指针变量。指针sp指向一个具有5个字节的连续存储区的开头,即指向字符a所在存储单元。l char*sp=“abcd”;同上12l(2)通过赋值语句给基类型为char的指针赋字符串。若有定义语句:char *sp;,则可通过赋值语句:sp=“abcd”;,把字符串“abcd”的首地址赋给指针变量sp。l(3)若有以上定义和赋值语句,sp+;将移动指针sp,使其指向字符串中的字符b,这时sp指向字符串“bcd”.13l10-6下列选项中正确的语句组是lA.char s8;s=“Beijing”;lB.char s8;s=“Beijing”;lC
8、.char *s;s=“Beijing”;lD.char *s;s=“Beijing”;14l6.通过指针引用字符串中的字符l(1)若有定义:char *sp=“abcd”;,*sp代表字母a,*(sp+1)代表字母b,。l(2)若有以上定义,sp0代表字母a,sp1代表字母b,。l7.字符串的输出l(1)可以调用printf函数,用%s格式输出字符数组中的字符串和字符指针所指的字符串。l(2)可以调用puts函数,输出字符数组中的字符串和字符指针所指的字符串。15l知识点2:字符串数组l1.字符串数组赋值l在二维字符数组的每一行存放一个字符串,此二维数组构成字符串数组。l(1)例如,以下定义
9、语句通过赋初值给每行赋字符串l char s1380=“aa”,”bbbb”,”543211”,s2380;l(2)可调用strcpy函数给每行赋字符串。l for(i=0;i3;i+)strcpy(s2i,s1i);16l(3)可通过输入语句给每行赋字符串。l for(i=0;i3;i+)scanf(“%s”,s2i);l(4)不可用赋值语句给每行赋字符串。l for(i=0;i3;i+)s2i=s1i;是错误的。注意,s2i是地址常量,不能赋值。17l2.通过一个一维指针数组构成一个字符串数组l(1)例如,以下定义语句通过赋初值建立一个字符串数组l char*sp3=“aa”,”bbbb”
10、,”543211”;l以上定义在内存构成如图所示的存储结构18l(2)特点l由此方式构成的存储结构每行的长度可以不一;l可以给spi重新赋值,指针数组中每个元素的地址值可以改变,因为spi是变量。l当spi没有指向确定的存储空间时,不可以通过scanf函数或gets函数给它赋字符串。l(3)引用每个字符元素。l按以上定义,若i和j有正确定义和赋值,可通过*(spi+j)或spij的形式引用每个字符。19l10-7以下程序的输出结果是l#include l#include l main()l char b18=abcdefg,b28,*pb=b1+3;l while(-pb=b1)strcpy(
11、b2,pb);l printf(“%dn”,strlen(b2);l A.8B.3C.1D.720l10-8有以下程序l char cchar(char ch)l if(ch=A&ch=Z)ch=ch-A+a;l return ch;ll main()l char s=“ABC+abc=defDEF”,*p=s;l while(*p)l *p=cchar(*p);l p+;l printf(“%sn”,s);l lA.abc+ABC=DEFdefB.abc+abc=defdeflC.abcABCDEFdefD.abcabcdefdef21l10-9有以下程序l void ss(char*s,c
12、har t)l while(*s)l if(*s=t)*s=t-a+A;l s+;l ll main()l char str1100=“abcddfefdbd”,c=d;l ss(str1,c);printf(“%sn”,str1);llA.ABCDDEFEDBDB.abcDDfefDbDlC.abcAAfefAbAD.Abcddfefdbd22l10-10以下程序的输出结果是l main()l char s=“abcdef”;l s3=0;l printf(“%sn”,s);l 23l10-11以下程序运行后的输出结果是l main()l char a=“Language”,b=“Progr
13、ame”;l char *p1,*p2;int k;l p1=a;p2=b;l for(k=0;k=7;k+)l if(*(p1+k)=*(p2+k)printf(“%c”,*(p1+k);l 24第十一章对函数的进一步讨论l知识点1:main函数的参数l1.执行程序时的命令行l(1)C程序经过编译连接之后,将自动生成后缀为.exe的可执行文件。例如名为myp.c的C源程序,生成的可执行文件名为myp.exe。l(2)在操作系统的提示符下,打入myp,就可执行myp程序,myp就被称为执行命令。所在行称为命令行。l(3)在命令行中不仅有命令,其后还可跟随若干参数,通常各参数由空格隔开。每个参数
14、由一串字符组成。例如:myp hello worldl其中hello和world就是参数。25l(4)系统将自动开辟存储区存放这些字符串,并如图所示通过无名指针数组指向字符串。26l2.main函数后一对括号中的形参l(1)在运行C程序时,可以通过命令行把参数传给main函数的形参,从而把命令行中的参数传给main函数。l(2)main函数通常可用两个参数。例如:l main(int arge,char*argv)或l main(int arge,char*argv)l其中arge和argv是用户标识符,用作形参,可取任何合法的名字。l(3)arge中将存放命令行中字符串的个数。l(4)形参a
15、rgv被定义为指向指针的指针,它指向指针数组始元素。因此,通过argv可以引用命令行中的任一字符串,例如,对于上面的命令行,argv0指向字符串myp,argv1指向字符串hello,argv2指向字符串world。27l例:若以下程序放在myp.c文件中,在编译连接后,已生成一个myc.exe文件,输出argc和argv中的数据l main(int argc,char*argv)l int i;l printf(“argc=%dn”,argc);l for(i=1;iargc;i+)l printf(“%s “,argvi);l printf(“n”);l若在命令行中打入:l myc A C
16、OMMAND LINEl程序将输出:l argc=4l A COMMAND LINE28l11-1不合法的main函数命令行参数表示形式是lA.main(int a,char *c)lB.main(int arc,char *arv)lC.main(int argc,char *argv)lD.main(int argv,char *argc)29l11-2有以下程序l#include l main(int argc,char*argv)l int i,len=0;l for(i=1;iargc;i+)l len+=strlen(argvi);l printf(“%dn”,len);l程序编译
17、连接后生成的可执行文件是ex1.exe,若运行输入的带参数的命令行是:lex1abcdefg10lA.22B.17C.12D.9 30l知识点2:函数的递归调用l(1)C语言中函数可以递归调用,即可以自己调用自己,也可以间接地调用自己。l(2)分析递归调用的程序时需要建立以下概念。l每一层调用时,系统将为本次调用所用到的形参和函数中定义的变量开辟独立的存储单元。所以分析时必需清楚是在哪一层调用,以及该层中各变量的值。l递归算法必定有结束递归的条件,不可能无限递归下去,因此注意递归结束条件,然后有序地一层一层返回,有函数值的,同时返回函数值。元函数值的一定要注意本层中各变量的值。31l11-3在
18、函数调用过程中,如果函数funA调用了函数funB,函数funB又调用了函数funA,是lA.称为函数的直接递归调用lB.称为函数的间接递归调用lC.称为函数的循环调用lD.C语言中不允许这样的递归调用32l11-4有以下程序l void fun(int*a,int i,int j)l int t;l if(ij)l t=ai;ai=aj;aj=t;l i+;j-;l fun(a,i,j);l ll main()lint x=2,6,1,8,i;l fun(x,0,3);l for(i=0;i4;i+)printf(“%2d”,xi);l printf(“n”);l lA.1 2 6 8B.8
19、 6 2 1 C.8 1 6 2 D.8 6 1 233l11-5有以下程序l int f(int n)l if(n=1)return 1;l else return f(n-1)+1;ll main()l int i,j=0;l for(i=1;i3;i+)j+=f(i);l printf(“%dn”,j);ll程序运行结果lA.4B.3C.2D.134l11-6有以下程序l void f(int a,int i,int j)l int t;l if(ij)l t=ai;ai=aj;aj=t;l f(a,i+1,j-1);l ll main()lint i,aa5=1,2,3,4,5;l f
20、(aa,0,4);l for(i=0;i5;i+)printf(“%d,”,aai);l printf(“n”);l程序执行结果lA.5,4,3,2,1B.5,2,3,4,1C.1,2,3,4,5lD.1,5,4,3,235l知识点3:指向函数的指针l1.C语言中,函数名代表一个地址值,从这个地址开始存放函数的执行代码,称为函数的入口。所以不能把函数名作为变量,重新给它赋值。l2.指向函数的指针。函数指针的定义有以下两种形式。l(1)第1种形式:l类型名(*指针变量名)();l例如,int(*fp)();。说明了fp是一个指向函数的指针变量,它可以指向任何函数值为int类型的函数。36l(2)
21、第2种形式:l类型名(*指针变量名)(类型名,类型名);l例如,int(*fp)(int,int,int);。说明了fp是一个指向函数的指针变量,它可以指向任何函数值为int类型且具有3个int类型形参的函数。l(3)注意,*fp外的一对圆括号不可省略,不能写成:int*fp(int,int,int);,此处,不再说明fp是一个指针变量,而是说明fp是一个函数名,此函数返回一个基类型为int的地址。这是一条函数说明语句。l(4)注意,若函数没有形参,说明符后面的一对括号也不能省略。37l(5)对于不同类型的指针变量,其定义格式不同。下图为有关指针的数据类型小结。定义格式含义int *pP为指针
22、变量,用于指向整型数据的指针元素组成int *pnP为指针数组,它由n个指向整型数据的指针元素组成int (*p)nP为行指针,指向一个含有n个元素的一维数组int *p()P为指针函数,该函数返回一个基类型为整型的指针int (*p)()P为函数指针,p所指函数返回一个整型值int *pP是一个指针变量,它指向一个指向整型数据的指针变量38l3.函数名作为实参。C语言中,函数名可以作为实参,这时对应的形参必须是一个类型相同的函数指针。l4.通过函数指针调用函数。l若有以下定义的说明l int findbig(int,int,int);l int(*f)(int,int,int),x,y,z,
23、big;l则可通过以下方式调用findbig函数:lf=findbig;lbig=(*f)(x,y,z);39l11-7有以下程序l int fa(int x)l return x*x;l int fb(int x)l return x*x*x;l int f(int(*f1)(int),int(*f2)(int),int x)l return(*f2)(x)-(*f1)(x);l main()l int i;i=f(fa,fb,2);printf(“%dn”,i);l程序运行后结果lA.-4B.1C.4D.840l11-8在说明语句:int *f();中,标识符f代表的是lA.一个用于指向整型数据的指针变量lB.一个用于指向一维数组的行指针lC.一个用于指向函数的指针变量lD.一个返回值为指针型的函数名