《C语言程序设计》-第10章-字符串课件_第1页
《C语言程序设计》-第10章-字符串课件_第2页
《C语言程序设计》-第10章-字符串课件_第3页
《C语言程序设计》-第10章-字符串课件_第4页
《C语言程序设计》-第10章-字符串课件_第5页
已阅读5页,还剩101页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

哈尔滨工业大学计算机科学与技术学院第10章字符串哈尔滨工业大学第10章字符串1第10章学习内容字符串常量字符数组和字符指针字符串处理函数向函数传递字符串从函数返回字符串指针2/53第10章学习内容字符串常量2/532字符串常量用双引号括起的一串字符是字符串常量,C语言自动为其添加'\0'结束符"Howareyou"Howareyou\0一串以'\0'结尾的字符在C语言中被看作字符串3/53字符串常量用双引号括起的一串字符是字符串常量,C语言自动为其3字符串的存储C语言没有提供专门的字符串数据类型使用字符数组和字符指针来处理字符串字符数组每个元素都是字符类型的数组charstr[80];Howareyou\0Howareyou是字符数组,但不一定代表字符串数组的最后一个元素必须是'\0'才表示字符串4/53字符串的存储C语言没有提供专门的字符串数据类型Ho4字符数组的初始化用字符常量的初始化列表对数组初始化

charstr[6]={'C','h','i','n','a','\0'};用字符串常量直接对数组初始化

charstr[6]={"China"};charstr[6]="China";charstr[]="China";5/53字符串的存储字符数组的初始化5/53字符串的存储5字符指针还可以用字符指针来指向一个字符串如果让字符指针指向一个字符串常量

HelloChina\0字符指针就是指向字符串首地址的指针"HelloChina";pStrchar*pStr=6/53字符指针还可以用字符指针来指向一个字符串Hel6字符指针

HelloChina\0pStr"HelloChina";char*pStr=字符串保存在只读的常量存储区pStr是一个指向常量存储区中的字符串的指针变量char*pStr;pStr

="HelloChina";可修改pStr的值(指向),但不可以对它所指向的存储单元进行写操作*pStr=

'W';7/53如果让字符指针指向一个字符数组中的字符串呢?字符指针HelloCh7字符指针

HelloChina\0"HelloChina";charstr[]

=

函数内定义,保存在动态存储区数组中存储的字符可以被修改数组名str的值不可修改,是地址常量

str函数外定义,或定义为静态数组,字符串保存在静态存储区str=

"HelloChina";str[0]=

'W';8/53字符指针HelloCh8字符指针

HelloChina\0pStr"HelloChina"charstr[]

=

str*pStr='W';char*pStr;pStr=str;pStr=&str[0];pStr的值(指向)可以被修改,它所指向的字符串也可以被修改str[0]='W';pStr[0]='W';9/53字符指针HelloCh9字符指针正确使用和区分字符数组和字符指针须牢记以下基本原则:明确字符串被保存到了哪里明确字符指针指向了哪里10/53字符指针正确使用和区分字符数组和字符指针10/5310按字符逐个输入/输出for(i=0;str[i]!='\0';i++){ putchar(str[i]);}putchar('\n');charstr[10];一般不用字符串长度控制,如i<10字符串的访问和输入/输出11/53按字符逐个输入/输出for(i=0;str[i]!='\11按字符串整体输入/输出scanf("%s",str);printf("%s",str);charstr[10];gets(str);puts(str);不能输入带空格的字符串可以输入带空格的字符串字符串的访问和输入/输出12/53按字符串整体输入/输出scanf("%s",str);ch12#include<stdio.h>intmain(void){charc[80];printf("Inputastring:");scanf("%s",c);printf("%s\n",c);

return0;}用%d输入数字或%s输入字符串时,忽略空格、回车或制表符等空白字符,读到这些字符时,系统认为读入结束,因此不能输入带空格的字符串字符串的访问和输入/输出13/53#include<stdio.h>用%d输入数字或%s输入13#include<stdio.h>intmain(void){charc[80];printf("Inputastring:");

gets(c);printf("%s\n",c);

return0;}可输入带空格的字符串,因为空格和制表符都是字符串的一部分此外,两个字符串输入函数对回车符的处理也不同字符串的访问和输入/输出14/53#include<stdio.h>可输入带空格的字符串,因14#include<stdio.h>intmain(void){charc[80];

printf("Inputastring:");scanf("%s",c);printf("%s\n",c);printf("Inputastring:");gets(c);printf("%s\n",c);return0;}空格和制表符都是字符串的一部分,以回车作为字符串的终止符,同时将回车从缓冲区读走,但不作为字符串的一部分字符串的访问和输入/输出15/53#include<stdio.h>空格和制表符都是字符串的15#include<stdio.h>intmain(void){charc[80],ch;printf("Inputastring:");scanf("%s",c);printf("%s\n",c);

printf("Inputacharacter:");ch=getchar();printf("%c\n",ch);return0;}scanf()不读走回车,回车仍留在缓冲区中,回车被getchar()读走字符串的访问和输入/输出16/53#include<stdio.h>scanf()不读走回车16#include<stdio.h>intmain(void){charc[80],ch;printf("Inputastring:");gets(c);printf("%s\n",c);

printf("Inputacharacter:");ch=getchar();printf("%c\n",ch);return0;}字符串的访问和输入/输出17/53#include<stdio.h>字符串的访问和输入/输出17#include<stdio.h>intmain(void){intn,ret; do{ printf("Inputn:"); ret=scanf("%d",&n); }while(ret!=1); printf("n=%d\n",n); return0;}假如格式不匹配,输入了非数字字符?scanf()按指定格式读取缓冲区中的数据,如果读取失败,则缓冲区中的非数字字符不会被读走,一直处于判断、读取、退出,判断、读取、退出,……(死机)字符串的访问和输入/输出18/53#include<stdio.h>假如格式不匹配,输入了非18#include<stdio.h>intmain(void){intn,ret;

do{ printf("Inputn:"); ret=scanf("%d",&n);

if(ret!=1) {

while(getchar()!='\n'); } }while(ret!=1); printf("n=%d\n",n); return0;}清空缓冲区键盘输入都被保存在输入缓冲区中,直到用户输入回车,输入函数才去读缓冲区中的数据判断scanf()返回成功读取的数据的个数,可以避免死机问题,但还需清空缓冲区字符串的访问和输入/输出19/53#include<stdio.h>清空缓冲区键盘输入都被保19#include<stdio.h>intmain(void){ charch,c[80];

printf("Inputastring:"); scanf("%s",c); printf("%s\n",c);

printf("Inputacharacter:");

scanf(""); scanf("%c",&ch); printf("%c\n",ch);

return0;}清空缓冲区中的空白符等价于scanf("%c",&ch);字符串的访问和输入/输出20/53#include<stdio.h>清空缓冲区中的空白符等价20#include<stdio.h>intmain(void){ charch,c[80];

printf("Inputastring:"); scanf("%s",c); printf("%s\n",c);

printf("Inputacharacter:");

scanf(""); scanf("%c",&ch); printf("%c\n",ch);

return0;}在这里可以换成getchar();字符串的访问和输入/输出21/53#include<stdio.h>在这里可以换成getch21#include<stdio.h>intmain(void){ charch,c[80];

printf("Inputastring:");

gets(c); printf("%s\n",c);

printf("Inputacharacter:");

scanf("%c",&ch); printf("%c\n",ch);

return0;}无需再清空缓冲区字符串的访问和输入/输出22/53#include<stdio.h>无需再清空缓冲区字符串的22【例】从键盘输入一个人名把它显示在屏幕上Why?23/53#include<stdio.h>#defineN12intmain(void){charname[N];printf("Enteryourname:");scanf("%s",name);printf("Hello%s!\n",name);return0;}【例】从键盘输入一个人名把它显示在屏幕上Why?23/5323【例】从键盘输入一个人名把它显示在屏幕上24/53#include<stdio.h>#defineN12intmain(void){charname[N];printf("Enteryourname:");scanf("%s",name);printf("Hello%s!\n",name);

scanf("%s",name);/*读取输入缓冲区中余下的上次未被读走的字符*/printf("Hello%s!\n",name);return0;}【例】从键盘输入一个人名把它显示在屏幕上24/53#inc24#include<stdio.h>#defineN12intmain(void){charname[N];printf("Enteryourname:");

gets(name);printf("Hello%s!\n",name);return0;}【例10.2】使用函数gets(),从键盘输入一个带有空格的人名,然后把它显示在屏幕上25/53#include<stdio.h>【例10.2】使用函数g25#include<stdio.h>#defineN12intmain(void){charname[N];

char*ptrName=name;/*声明了一个指向数组name的字符指针ptrName*/printf("Enteryourname:");

gets(ptrName);/*输入字符串存入字符指针ptrName所指向的内存*/printf("Hello%s!\n",ptrName);return0;}【例10.2】使用函数gets(),从键盘输入一个带有空格的人名,然后把它显示在屏幕上26/53#include<stdio.h>【例10.2】使用函数g26#include<stdio.h>#defineN12intmain(void){charname[N];

charstr[]="\"Hello\",Isaidto";printf("Enteryourname:");fgets(name,sizeof(name),stdin);printf("%s%s.\n",str,name);return0;}【例10.3】从键盘输入一个带有空格的人名,然后在显示人名的前面显示"Hello",Isaidto27/53#include<stdio.h>【例10.3】从键盘输入27#include<stdio.h>#defineN12intmain(void){charname[N];

char*ptr="\"Hello\",Isaidto";printf("Enteryourname:");fgets(name,sizeof(name),stdin);printf("%s%s.\n",ptr,name);return0;}【例10.3】从键盘输入一个带有空格的人名,然后在显示人名的前面显示"Hello",Isaidto28/53#include<stdio.h>【例10.3】从键盘输入28字符串处理函数#include<string.h>strcpy(目的字符串,源字符串);stringcopystrlen(字符串);stringlengthstrcat(目的字符串,源字符串);stringcombinationstrcmp(字符串1,字符串2);stringcomparison29/53字符串处理函数#include<string.h>strc29计算字符串长度#include<string.h>strlen(字符串);stringlengthcharstr[10]={"China"};printf("%d",

strlen(str));打印结果是5,6,还是10?China\0\0\0\0\0不包括\0的实际字符的个数30/53计算字符串长度#include<string.h>strl30计算字符串长度#include<string.h>strlen(字符串);stringlengthlen=

strlen(str);for(i=0;i<len;i++){ putchar(str[i]);}putchar('\n');用长度控制字符串输出31/53计算字符串长度#include<string.h>strl31字符串复制#include<string.h>strcpy(目的字符串,源字符串);stringcopy字符串能否用=整体复制?str2=str1;strcpy(str2,str1);注意复制的方向!str2必须足够大!32/53字符串复制#include<string.h>strcpy32字符串连接#include<string.h>strcat(目的字符串,源字符串);stringcombinationstrcat(str2,str1);str2必须足够大!Hello\0\0\0\0\0\0

\0

China\0HelloChina\0

\033/53字符串连接#include<string.h>strcat33字符串比较#include<string.h>strcmp(字符串1,字符串2);stringcomparison字符串能否用>,<,==比较大小?if(str2==str1)if(strcmp(str2,str1)==0)34/53字符串比较#include<string.h>strcmp34字符串比较#include<string.h>strcmp(字符串1,字符串2);stringcomparison字符串是如何比较大小的?当出现第一对不相等的字符时,就由这两个字符决定所在字符串的大小,返回其ASCII码比较的结果值comparecomputer判断compare小于computer?

strcmp(str1,str2)<0为真35/53字符串比较#include<string.h>strcmp35#include<stdio.h>#include<string.h>#defineMAX_LEN10/*字符串最大长度*/#defineN150/*字符串个数*/voidSortString(charstr[][MAX_LEN],intn);intmain(void){ inti,n;

charname[N][MAX_LEN];/*定义二维字符数组*/ printf("Howmanycountries?"); scanf("%d",&n);

getchar();/*读走输入缓冲区中的回车符*/ printf("Inputtheirnames:\n"); for(i=0;i<n;i++) {

gets(name[i]);/*输入n个字符串*/ }

SortString(name,n);/*字符串按字典顺序排序*/ printf("Sortedresults:\n"); for(i=0;i<n;i++) {

puts(name[i]);/*输出排序后的n个字符串*/ } return0;}

【例10.4】按奥运会参赛国国名在字典中的顺序对其入场次序进行排序36/53#include<stdio.h>【例10.4】按奥36voidSortString(charstr[][MAX_LEN],intn){ inti,j; chartemp[MAX_LEN]; for(i=0;i<n-1;i++) { for(j=i+1;j<n;j++) { if(strcmp(str[j],str[i])<0) {

strcpy(temp,str[i]);

strcpy(str[i],str[j]);

strcpy(str[j],temp); } } }}

【例10.4】按奥运会参赛国国名在字典中的顺序对其入场次序进行排序37/53voidSortString(charstr[][MAX37缓冲区溢出攻击网络黑客常常针对系统和程序自身存在的漏洞,编写相应的攻击程序其中,最常见的就是对缓冲区溢出漏洞的攻击几乎占到了网络攻击次数的一半以上世界上第一个缓冲区溢出攻击Internet蠕虫,曾造成全球多台网络服务器瘫痪何谓缓冲区溢出攻击?利用缓冲区溢出漏洞进行的攻击38/53缓冲区溢出攻击网络黑客常常针对系统和程序自身存在的漏洞,编写38缓冲区溢出攻击易引起缓冲区溢出攻击、不安全的函数gets()、scanf()、strcpy()等不限制字符串长度,不对数组越界进行检查和限制,导致有用的堆栈数据被覆盖,给黑客攻击以可乘之机对缓冲区溢出漏洞进行攻击的后果程序运行失败、系统崩溃和重启等利用缓冲区溢出,执行非授权指令,甚至取得系统特权,进而进行各种非法操作防止和检测缓冲区溢出攻击成为防御网络入侵和入侵检测的重点之一39/53缓冲区溢出攻击易引起缓冲区溢出攻击、不安全的函数39/5339缓冲区溢出攻击实例#include<stdio.h>#include<string.h>intmain(void){ charpassword[8]="secret",input[8]; while(1) { printf("Enteryourpassword:"); gets(input); if(strcmp(input,password)==0) { printf("Welcome!\n"); break; } else{ printf("Sorry!\n"); } } return0;}40/53缓冲区溢出攻击实例#include<stdio.h>40/40字符串的安全输入方法#include<stdio.h>#include<string.h>intmain(void){ charpassword[8]="secret",input[8]; while(1) { printf("Enteryourpassword:");

scanf("%7s",input); if(strcmp(input,password)==0) { printf("Welcome!\n"); break; } else{ printf("Sorry!\n"); } } return0;}41/53字符串的安全输入方法#include<stdio.h>4141字符串的安全输入方法#include<stdio.h>#include<string.h>intmain(void){ charpassword[8]="secret",input[8]; while(1) { printf("Enteryourpassword:");

fgets(input,sizeof(input),stdin); if(strcmp(input,password)==0) { printf("Welcome!\n"); break; } else{ printf("Sorry!\n"); } } return0;}限制输入字符串的长度,更灵活42/53字符串的安全输入方法#include<stdio.h>限制42字符串处理函数43/53字符串处理函数43/5343向函数传递字符串向函数传递字符串时既可用字符数组作函数参数也可用字符指针作函数参数传地址调用传字符串的首地址,而非字符串中的全部字符44/53向函数传递字符串向函数传递字符串时44/5344例10.5:字符串拷贝—用字符数组编程voidMyStrcpy(chardstStr[],charsrcStr[]){

inti=0;

while(srcStr[i]!='\0') {

dstStr[i]=srcStr[i];

i++; } dstStr[i]='\0';}

HelloChina\0

srcStr[i]dstStr[i]Hi=0ei=1li=2li=3oi=4i=5Ci=6hi=7ii=8ni=9ai=10\0srcStr[i]=='\0'45/53i=11例10.5:字符串拷贝—用字符数组编程voidMySt45voidMyStrcpy(char*dstStr,char*srcStr){

while(*srcStr!='\0') {

*dstStr=*srcStr;

srcStr++; dstStr++; } *dstStr='\0';}例10.5:字符串拷贝—用字符指针编程

HelloChina\0

*srcStr*dstStrHelloChina\0*srcStr=='\0'srcStr++srcStrdstStr++dstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStr46/53voidMyStrcpy(char*dstStr,c46例10.6:计算实际字符个数unsignedintMyStrlen(charstr[]){ inti; unsignedintlen=0;

for(i=0;str[i]!='\0';i++) {

len++;

}

returnlen;}unsignedintMyStrlen(char*pStr){ unsignedintlen=0;

for(;*pStr!='\0';pStr++) {

len++;

}

returnlen;

}用字符指针实现用字符数组实现实际字符个数(不含'\0')47/53str[i]=='\0'

Hello\0

stri++i=0len=1i=1len=2i=2len=3i=3len=4i=4len=5i=5str[i]=='\0'

Hello\0

strpStr++pStrlen=1pStrlen=2pStrlen=3pStrlen=4pStrlen=5pStr例10.6:计算实际字符个数unsignedint47#include<stdio.h>#defineN80char*MyStrcat(char*dstStr,char*srcStr);intmain(void){ charfirst[2*N];/*这个数组应该足够大*/ charsecond[N];

char*result=NULL; printf("Inputthefirststring:"); gets(first); printf("Inputthesecondstring:"); gets(second);

result=MyStrcat(first,second); printf("Theresultis:%s\n",result); return0;}从函数返回字符指针【例】编程实现strcat()的功能48/53#include<stdio.h>从函数返回字符指针【例48从函数返回字符指针49/53

*dstStrHelloChina\0*srcStr=='\0'

Hello\0

*dstStrdstStr++srcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStrsrcStrdstStr

China\0

*srcStrsrcStr++dstStr++while(*dstStr!='\0'){ dstStr++;}dstStrdstStrdstStrdstStrdstStrdstStrwhile(*srcStr!='\0'){ *dstStr=*srcStr;srcStr++;dstStr++;}*dstStr='\0';【例】编程实现strcat()的功能从函数返回字符指针49/53*dstStrHelloChi49char*MyStrcat(char*dstStr,char*srcStr){ char*pStr=dstStr; while(*dstStr!='\0') { dstStr++; } while(*srcStr!='\0'){ *dstStr=*srcStr;srcStr++;dstStr++;}*dstStr='\0'; returnpStr;}从函数返回字符指针【例】编程实现strcat()的功能返回字符串首地址50/53

HelloChina\0dstStrpStrchar*MyStrcat(char*dstStr,c50小结明确字符串被保存到了哪里明确字符指针指向了哪里指向字符串常量的字符指针指向字符数组的字符指针向函数传递字符串向函数传递字符数组向函数传递字符指针字符串处理函数51/53小结明确字符串被保存到了哪里51/5351本章知识点小结和MOOC对应的视频52/52本章知识点小结和MOOC对应的视频52/5252Thankyouforyourattention!SuXiaoHongQ&A53/53ThankyouforSuXiaoHongQ&A53/53哈尔滨工业大学计算机科学与技术学院第10章字符串哈尔滨工业大学第10章字符串54第10章学习内容字符串常量字符数组和字符指针字符串处理函数向函数传递字符串从函数返回字符串指针55/53第10章学习内容字符串常量2/5355字符串常量用双引号括起的一串字符是字符串常量,C语言自动为其添加'\0'结束符"Howareyou"Howareyou\0一串以'\0'结尾的字符在C语言中被看作字符串56/53字符串常量用双引号括起的一串字符是字符串常量,C语言自动为其56字符串的存储C语言没有提供专门的字符串数据类型使用字符数组和字符指针来处理字符串字符数组每个元素都是字符类型的数组charstr[80];Howareyou\0Howareyou是字符数组,但不一定代表字符串数组的最后一个元素必须是'\0'才表示字符串57/53字符串的存储C语言没有提供专门的字符串数据类型Ho57字符数组的初始化用字符常量的初始化列表对数组初始化

charstr[6]={'C','h','i','n','a','\0'};用字符串常量直接对数组初始化

charstr[6]={"China"};charstr[6]="China";charstr[]="China";58/53字符串的存储字符数组的初始化5/53字符串的存储58字符指针还可以用字符指针来指向一个字符串如果让字符指针指向一个字符串常量

HelloChina\0字符指针就是指向字符串首地址的指针"HelloChina";pStrchar*pStr=59/53字符指针还可以用字符指针来指向一个字符串Hel59字符指针

HelloChina\0pStr"HelloChina";char*pStr=字符串保存在只读的常量存储区pStr是一个指向常量存储区中的字符串的指针变量char*pStr;pStr

="HelloChina";可修改pStr的值(指向),但不可以对它所指向的存储单元进行写操作*pStr=

'W';60/53如果让字符指针指向一个字符数组中的字符串呢?字符指针HelloCh60字符指针

HelloChina\0"HelloChina";charstr[]

=

函数内定义,保存在动态存储区数组中存储的字符可以被修改数组名str的值不可修改,是地址常量

str函数外定义,或定义为静态数组,字符串保存在静态存储区str=

"HelloChina";str[0]=

'W';61/53字符指针HelloCh61字符指针

HelloChina\0pStr"HelloChina"charstr[]

=

str*pStr='W';char*pStr;pStr=str;pStr=&str[0];pStr的值(指向)可以被修改,它所指向的字符串也可以被修改str[0]='W';pStr[0]='W';62/53字符指针HelloCh62字符指针正确使用和区分字符数组和字符指针须牢记以下基本原则:明确字符串被保存到了哪里明确字符指针指向了哪里63/53字符指针正确使用和区分字符数组和字符指针10/5363按字符逐个输入/输出for(i=0;str[i]!='\0';i++){ putchar(str[i]);}putchar('\n');charstr[10];一般不用字符串长度控制,如i<10字符串的访问和输入/输出64/53按字符逐个输入/输出for(i=0;str[i]!='\64按字符串整体输入/输出scanf("%s",str);printf("%s",str);charstr[10];gets(str);puts(str);不能输入带空格的字符串可以输入带空格的字符串字符串的访问和输入/输出65/53按字符串整体输入/输出scanf("%s",str);ch65#include<stdio.h>intmain(void){charc[80];printf("Inputastring:");scanf("%s",c);printf("%s\n",c);

return0;}用%d输入数字或%s输入字符串时,忽略空格、回车或制表符等空白字符,读到这些字符时,系统认为读入结束,因此不能输入带空格的字符串字符串的访问和输入/输出66/53#include<stdio.h>用%d输入数字或%s输入66#include<stdio.h>intmain(void){charc[80];printf("Inputastring:");

gets(c);printf("%s\n",c);

return0;}可输入带空格的字符串,因为空格和制表符都是字符串的一部分此外,两个字符串输入函数对回车符的处理也不同字符串的访问和输入/输出67/53#include<stdio.h>可输入带空格的字符串,因67#include<stdio.h>intmain(void){charc[80];

printf("Inputastring:");scanf("%s",c);printf("%s\n",c);printf("Inputastring:");gets(c);printf("%s\n",c);return0;}空格和制表符都是字符串的一部分,以回车作为字符串的终止符,同时将回车从缓冲区读走,但不作为字符串的一部分字符串的访问和输入/输出68/53#include<stdio.h>空格和制表符都是字符串的68#include<stdio.h>intmain(void){charc[80],ch;printf("Inputastring:");scanf("%s",c);printf("%s\n",c);

printf("Inputacharacter:");ch=getchar();printf("%c\n",ch);return0;}scanf()不读走回车,回车仍留在缓冲区中,回车被getchar()读走字符串的访问和输入/输出69/53#include<stdio.h>scanf()不读走回车69#include<stdio.h>intmain(void){charc[80],ch;printf("Inputastring:");gets(c);printf("%s\n",c);

printf("Inputacharacter:");ch=getchar();printf("%c\n",ch);return0;}字符串的访问和输入/输出70/53#include<stdio.h>字符串的访问和输入/输出70#include<stdio.h>intmain(void){intn,ret; do{ printf("Inputn:"); ret=scanf("%d",&n); }while(ret!=1); printf("n=%d\n",n); return0;}假如格式不匹配,输入了非数字字符?scanf()按指定格式读取缓冲区中的数据,如果读取失败,则缓冲区中的非数字字符不会被读走,一直处于判断、读取、退出,判断、读取、退出,……(死机)字符串的访问和输入/输出71/53#include<stdio.h>假如格式不匹配,输入了非71#include<stdio.h>intmain(void){intn,ret;

do{ printf("Inputn:"); ret=scanf("%d",&n);

if(ret!=1) {

while(getchar()!='\n'); } }while(ret!=1); printf("n=%d\n",n); return0;}清空缓冲区键盘输入都被保存在输入缓冲区中,直到用户输入回车,输入函数才去读缓冲区中的数据判断scanf()返回成功读取的数据的个数,可以避免死机问题,但还需清空缓冲区字符串的访问和输入/输出72/53#include<stdio.h>清空缓冲区键盘输入都被保72#include<stdio.h>intmain(void){ charch,c[80];

printf("Inputastring:"); scanf("%s",c); printf("%s\n",c);

printf("Inputacharacter:");

scanf(""); scanf("%c",&ch); printf("%c\n",ch);

return0;}清空缓冲区中的空白符等价于scanf("%c",&ch);字符串的访问和输入/输出73/53#include<stdio.h>清空缓冲区中的空白符等价73#include<stdio.h>intmain(void){ charch,c[80];

printf("Inputastring:"); scanf("%s",c); printf("%s\n",c);

printf("Inputacharacter:");

scanf(""); scanf("%c",&ch); printf("%c\n",ch);

return0;}在这里可以换成getchar();字符串的访问和输入/输出74/53#include<stdio.h>在这里可以换成getch74#include<stdio.h>intmain(void){ charch,c[80];

printf("Inputastring:");

gets(c); printf("%s\n",c);

printf("Inputacharacter:");

scanf("%c",&ch); printf("%c\n",ch);

return0;}无需再清空缓冲区字符串的访问和输入/输出75/53#include<stdio.h>无需再清空缓冲区字符串的75【例】从键盘输入一个人名把它显示在屏幕上Why?76/53#include<stdio.h>#defineN12intmain(void){charname[N];printf("Enteryourname:");scanf("%s",name);printf("Hello%s!\n",name);return0;}【例】从键盘输入一个人名把它显示在屏幕上Why?23/5376【例】从键盘输入一个人名把它显示在屏幕上77/53#include<stdio.h>#defineN12intmain(void){charname[N];printf("Enteryourname:");scanf("%s",name);printf("Hello%s!\n",name);

scanf("%s",name);/*读取输入缓冲区中余下的上次未被读走的字符*/printf("Hello%s!\n",name);return0;}【例】从键盘输入一个人名把它显示在屏幕上24/53#inc77#include<stdio.h>#defineN12intmain(void){charname[N];printf("Enteryourname:");

gets(name);printf("Hello%s!\n",name);return0;}【例10.2】使用函数gets(),从键盘输入一个带有空格的人名,然后把它显示在屏幕上78/53#include<stdio.h>【例10.2】使用函数g78#include<stdio.h>#defineN12intmain(void){charname[N];

char*ptrName=name;/*声明了一个指向数组name的字符指针ptrName*/printf("Enteryourname:");

gets(ptrName);/*输入字符串存入字符指针ptrName所指向的内存*/printf("Hello%s!\n",ptrName);return0;}【例10.2】使用函数gets(),从键盘输入一个带有空格的人名,然后把它显示在屏幕上79/53#include<stdio.h>【例10.2】使用函数g79#include<stdio.h>#defineN12intmain(void){charname[N];

charstr[]="\"Hello\",Isaidto";printf("Enteryourname:");fgets(name,sizeof(name),stdin);printf("%s%s.\n",str,name);return0;}【例10.3】从键盘输入一个带有空格的人名,然后在显示人名的前面显示"Hello",Isaidto80/53#include<stdio.h>【例10.3】从键盘输入80#include<stdio.h>#defineN12intmain(void){charname[N];

char*ptr="\"Hello\",Isaidto";printf("Enteryourname:");fgets(name,sizeof(name),stdin);printf("%s%s.\n",ptr,name);return0;}【例10.3】从键盘输入一个带有空格的人名,然后在显示人名的前面显示"Hello",Isaidto81/53#include<stdio.h>【例10.3】从键盘输入81字符串处理函数#include<string.h>strcpy(目的字符串,源字符串);stringcopystrlen(字符串);stringlengthstrcat(目的字符串,源字符串);stringcombinationstrcmp(字符串1,字符串2);stringcomparison82/53字符串处理函数#include<string.h>strc82计算字符串长度#include<string.h>strlen(字符串);stringlengthcharstr[10]={"China"};printf("%d",

strlen(str));打印结果是5,6,还是10?China\0\0\0\0\0不包括\0的实际字符的个数83/53计算字符串长度#include<string.h>strl83计算字符串长度#include<string.h>strlen(字符串);stringlengthlen=

strlen(str);for(i=0;i<len;i++){ putchar(str[i]);}putchar('\n');用长度控制字符串输出84/53计算字符串长度#include<string.h>strl84字符串复制#include<string.h>strcpy(目的字符串,源字符串);stringcopy字符串能否用=整体复制?str2=str1;strcpy(str2,str1);注意复制的方向!str2必须足够大!85/53字符串复制#include<string.h>strcpy85字符串连接#include<string.h>strcat(目的字符串,源字符串);stringcombinationstrcat(str2,str1);str2必须足够大!Hello\0\0\0\0\0\0

\0

China\0HelloChina\0

\086/53字符串连接#include<string.h>strcat86字符串比较#include<string.h>strcmp(字符串1,字符串2);stringcomparison字符串能否用>,<,==比较大小?if(str2==str1)if(strcmp(str2,str1)==0)87/53字符串比较#include<string.h>strcmp87字符串比较#include<string.h>strcmp(字符串1,字符串2);stringcomparison字符串是如何比较大小的?当出现第一对不相等的字符时,就由这两个字符决定所在字符串的大小,返回其ASCII码比较的结果值comparecomputer判断compare小于computer?

strcmp(str1,str2)<0为真88/53字符串比较#include<string.h>strcmp88#include<stdio.h>#include<string.h>#defineMAX_LEN10/*字符串最大长度*/#defineN150/*字符串个数*/voidSortString(charstr[][MAX_LEN],intn);intmain(void){ inti,n;

charname[N][MAX_LEN];/*定义二维字符数组*/ printf("Howmanycountries?"); scanf("%d",&n);

getchar();/*读走输入缓冲区中的回车符*/ printf("Inputtheirnames:\n"); for(i=0;i<n;i++) {

gets(name[i]);/*输入n个字符串*/ }

SortString(name,n);/*字符串按字典顺序排序*/ printf("Sortedresults:\n"); for(i=0;i<n;i++) {

puts(name[i]);/*输出排序后的n个字符串*/ } return0;}

【例10.4】按奥运会参赛国国名在字典中的顺序对其入场次序进行排序89/53#include<stdio.h>【例10.4】按奥89voidSortString(charstr[][MAX_LEN],intn){ inti,j; chartemp[MAX_LEN]; for(i=0;i<n-1;i++) { for(j=i+1;j<n;j++) { if(strcmp(str[j],str[i])<0) {

strcpy(temp,str[i]);

strcpy(str[i],str[j]);

strcpy(str[j],temp); } } }}

【例10.4】按奥运会参赛国国名在字典中的顺序对其入场次序进行排序90/53voidSortString(charstr[][MAX90缓冲区溢出攻击网络黑客常常针对系统和程序自身存在的漏洞,编写相应的攻击程序其中,最常见的就是对缓冲区溢出漏洞的攻击几乎占到了网络攻击次数的一半以上世界上第一个缓冲区溢出攻击Internet蠕虫,曾造成全球多台网络服务器瘫痪何谓缓冲区溢出攻击?利用缓冲区溢出漏洞进行的攻击91/53缓冲区溢出攻击网络黑客常常针对系统和程序自身存在的漏洞,编写91缓冲区溢出攻击易引起缓冲区溢出攻击、不安全的函数gets()、scanf()、strcpy()等不限制字符串长度,不对数组越界进行检查和限制,导致有用的堆栈数据被覆盖,给黑客攻击以可乘之机对缓冲区溢出漏洞进行攻击的后果程序运行失败、系统崩溃和重启等利用缓冲区溢出,执行非授权指令,甚至取得系统特权,进而进行各种非法操作防止和检测缓冲区溢出攻击成为防御网络入侵和入侵检测的重点之一92/53缓冲区溢出攻击易引起缓冲区溢出攻击、不安全的函数39/5392缓冲区溢出攻击实例#include<stdio.h>#include<string.h>intmain(void){ charpassword[8]="secret",input[8]; while(1) { printf("Enteryourpassword:"); gets(input); if(strcmp(input,password)==0) { printf("Welcome!\n"); break; } else{ printf("Sorry!\n"); } } return0;}93/53缓冲区溢出攻击实例#include<stdio.h>40/93字符串的安全输入方法#include<stdio.h>#include<string.h>intmain(void){ charpassword[8]="secret",input[8]; while(1) { printf("Enteryourpassword:");

scanf("%7s",input); if(strcmp(input,password)==0) { printf("Welcome!\n"); break; } else{ printf("Sorry!\n"); } } return0;}94/53字符串的安全输入方法#include<stdio.h>4194字符串的安全输入方法#include<stdio.h>#include<string.h>intmain(void){ charpassword[8]="secret",input[8]; while(1) { printf("Enteryourpassword:");

fgets(input,sizeof(input),stdin); if(strcmp(input,password)==0) { printf("Welcome!\n"); break; } else{ printf("Sorry!\n"); } } return0;}限制输入字符串的长度,更灵活95/53字符串的安全输入方法#include<stdio.h>限制95字符串处理函数96/53字符串处理函数43/5396向函数传递字符串向函数传递字符串时既可用字符数组作函数参数也可用字符指针作函数参数传地址调用传字符串的首地址,而非字符串中的全部字符97/53向函数传递字符串向函数传递字符串时44/5397例10.5:字符串拷贝—用字符数组编程voidMyStrcpy(chardstStr[],charsrcStr[]){

inti=0;

while(srcStr[i]!='\0') {

dstStr[i]=srcStr[i];

i++; } dstStr[i]='\0';}

HelloChina\0

srcStr[i]dstStr[i]Hi=0ei=1li=2li=3oi=4i=5Ci=6h

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论