收藏 分销(赏)

编程与综合练习题-c指针.doc

上传人:xrp****65 文档编号:9005703 上传时间:2025-03-11 格式:DOC 页数:17 大小:201KB
下载 相关 举报
编程与综合练习题-c指针.doc_第1页
第1页 / 共17页
编程与综合练习题-c指针.doc_第2页
第2页 / 共17页
点击查看更多>>
资源描述
17 第五章 数组与指针习题 二、编程与综合练习题 5.3 打印杨辉三角形(10行)。使用二维数组并利用每个系数等于其肩上两系数之和。 解:好的算法无特例,二维数组共用11列,第1列全0,方便计算 #include<iostream> using namespace std; int main(){ int a[10][11]={0,1},i,j; //初始化时写好第1行,其余各行全0 for(i=1;i<10;i++) //为了全部算法无特例,共用11列,第1列全0,方便计算 for(j=1;j<=i+1;j++) a[i][j]=a[i-1][j-1]+a[i-1][j]; for(i=0;i<10;i++){ for(j=1;j<=i+1;j++) cout<<a[i][j]<<'\t'; cout<<endl; } return 0; } 5.4 将[例5.5]改用一维数组,附加行、列参数,实现通用算法。 解:用一维数组,附加行、列参数,实现通用算法难度大。 #include <iostream> #include <iomanip> using namespace std; void inverse(int [], int [],int,int);//注意数组最高维可缺省,例5.5因初学未省 void multi(int [], int [], int [],int,int,int); void output(int [],int,int); int main(){ int middle[6*3], result[6*4];//注意写作6*3等可清楚看出矩阵的行列 int matrix1[3*6]={8,10,12,23,1,3,5,7,9,2,4,6,34,45,56,2,4,6}; int matrix2[3*4]={3,2,1,0,-1,-2,9,8,7,6,5,4}; output(matrix1,3,6); inverse(matrix1,middle,3,6); output(middle,6,3); output(matrix2,3,4); multi(middle,matrix2,result,6,3,4); output(result,6,4); return 0; } void inverse(int matrix1_1[],int middle_1[],int a,int b){ int i,j; for (i=0;i<a;i++) for (j=0;j<b;j++) middle_1[i+j*a]=matrix1_1[i*b+j]; return; } void multi(int middle_1[],int matrix2_1[],int result_1[],int a,int b,int c){ int i,j,k; for (i=0;i<a;i++){ for (j=0;j<c;j++){ result_1[i*c+j] = 0; for (k=0;k<b;k++) result_1[i*c+j]+=middle_1[i*b+k]*matrix2_1[k*c+j]; } } return; } void output(int max_1[],int a,int b){ for (int i=0;i<a;i++){ for (int j=0;j<b;j++) cout <<setw(4)<<max_1[i*b+j]<<" "; cout<<'\n'; } cout<<endl; return; } 5.5 编写函数int atoi(char s[ ]),将字符串s转化为整型数返回。注意负数处理方法。 解:用指针处理字符串非常方便。使用符号位来处理负数。 #include<iostream> using namespace std; int atoi(char s[]){ int temp=0,f=1,i=0; while(s[i]!='\0'&&s[i]!='-'&&(s[i]<'0'||s[i]>'9')) i++;//去除串前部无效字符 if(s[i]=='-'){//读负号 f=-1; i++; } if(s[i]<'0'||s[i]>'9') cout<<"error!"<<endl;//串非法时,输出提示,返回0 while(s[i]>='0'&&s[i]<='9'){//转换数字串 temp=temp*10+s[i]-48; i++; } return f*temp; } int main(){ char num[20]; cin.getline(num,19); cout<<atoi(num)<<'\n'; return 0; } 5.6 有如下定义: int ival=60021; int *ip; double *dp; 下面哪些赋值非法或可能带来错误,并加以讨论。 ival=*ip; ival=ip; *ip=ival; ip=ival; *ip=&ival; ip=&ival; dp=ip; dp=*ip; *dp=*ip; 解:ival=*ip; 错,未确定指针ip初值,用随机内存地址中的数据给ival赋值是危险的。但语法对。 ival=ip; 错,赋值类型错,指针型不能赋给整型。 *ip=ival; 错,未确定指针ip初值,用ival给随机内存赋值是危险的。但语法对。 ip=ival; 错,赋值类型错,整型不能赋给指针型。 *ip=&ival; 错,赋值类型错,地址(指针型)不能赋给整型。 ip=&ival; 对,地址赋给指针型。 dp=ip; 错,整型指针不能赋给双精度指针。 dp=*ip; 错,赋值类型错,整型不能赋给指针型。 *dp=*ip; 对,赋值类型转换 5.7 编程定义一个整型、一个双精度型、一个字符型的指针,并赋初值,然后显示各指针所指目标的值与地址,各指针的值与指针本身的地址及各指针所占字节数(长度)。 *其中地址用十六进制显示。 解:注意:字符指针输出是字符串,必须强制转换为无类型指针 #include<iostream> using namespace std; int main(){ int *ip,ival=100; double *dp,dval=99.9; char *cp,cval='A'; ip=&ival; dp=&dval; cp=&cval; cout<<*ip<<'\t'<<&*ip<<'\t'<<sizeof(*ip)<<endl; cout<<*dp<<'\t'<<&*dp<<'\t'<<sizeof(*dp)<<endl; cout<<*cp<<'\t'<<(void*)&*cp<<'\t'<<sizeof(*cp)<<endl; //字符指针输出是字符串,必须强制转换为无类型指针 cout<<*cp<<'\t'<<&*cp<<'\t'<<sizeof(*cp)<<endl; //输出A开头的字符串 cout<<ip<<'\t'<<&ip<<'\t'<<sizeof(ip)<<endl; cout<<dp<<'\t'<<&dp<<'\t'<<sizeof(dp)<<endl; cout<<(void*)cp<<'\t'<<&cp<<'\t'<<sizeof(cp)<<endl; return 0; } 一个典型的运行结果: 变量 内容 首地址 长度(字节) cval ‘A’ 0x0012ff64 1 cp 0x0012ff64 0x0012ff68 4 dval 99.9 0x0012ff6c 8 dp 0x0012ff6c 0x0012ff74 4 ival 100 0x0012ff78 4 ip 0x0012ff78 0x0012ff7c 4 内存分配解释:速度优化时通常以字(4字节)为单位(开始地址可被4整除)给变量安排内存。cval仅用一个字节,也安排了4个字节。 5.8 分别编写下列字符串处理函数 (1)char *strcat1(char *s,const char *ct); 将串ct接到串s的后面,形成一个长串。【例6.7】以数组为参数,现用指针为参数。 (2)int strlen1(const char * s); 求字符串长度的函数,返回串长(不包括串结束符)。 (3)char * reverse (char *); 反置字符串s,即可将“break”成为“kaerb”。 (4)char * strchr( const char *cs,char c); 查找字符c在串cs中第一次出现的位置,返回指向该字符的指针,若没有出现则返回NULL。 (5)char *strstr (const char *cs1,const char *cs2); 返回串cs2作为子串在cs1中第一次出现的位置,若没有出现则返回NULL。 解:为了函数的通用性,有些可不要返回值的函数,也保留返回值。反置字符串函数,从串两头的指针同时向中间移动,重合或交错时停止。查找子串,先找子串的第一个字符,再核对子串其他字符。 #include<iostream> using namespace std; char* strcat1(char* s,const char* ct){ char* st=s; while(*s) s++;//*s作为条件,等效*s!=0 while(*s++=*ct++); return st; } int strlen1(const char* s){ int i=0; while(*s++) i++; return i; } char* reverse (char* s){ char temp,* temp1=s,* temp2=s; while(*temp2) temp2++; temp2--; //指针移回串尾 while(temp2-temp1>0){//注意此处,从串两头的指针同时向中间移动,重合或交错时停止 temp=*temp1; *temp1=*temp2; *temp2=temp; temp1++; temp2--; } return s; } char* strchr( const char*cs,char c){ while(*cs!=c&&*cs) cs++; if(*cs==0) cs=NULL; //未找到返回NALL return (char*)cs; } char *strstr (const char *cs1,const char *cs2){ char *temp; char *temp1=(char*)cs2; while(*cs1){ //只要主串还有字符未查,则继续 while(*cs1!=*cs2&&*cs1) cs1++; //找到主串含有子串的第一个字符,或主串查完停止 temp=(char*)cs1; temp1=(char*)cs2; if(*cs1){ //核对子串其他字符 while(*cs1++==*temp1++||*temp1); if(*temp1==0) return temp; //找到子串返回 } } return NULL; //未找到返回NAL } int main(){ char a[40]="李明"; char b[20]="是东南大学学生"; char c[40]="Southeast University"; char *cp; cout<<a<<endl; cout<<b<<endl; strcat1(a,b); cout<<"字符串连接后:"<<endl; cout<<a<<endl; //打印字符数组a cout<<"字符串长度为:"<<strlen1(a)<<endl; cout<<c<<endl; cp=strchr(c,'U'); if(cp==NULL) cout<<"未找到"<<endl; else cout<<cp<<endl; //找到输出由该字符开始的剩余串 cp=strchr(c,'A'); if(cp==NULL) cout<<"未找到"<<endl; else cout<<cp<<endl; cout<<reverse(c)<<endl; cp=strstr(a,"东南"); if(cp!=NULL) cout<<cp<<endl; //找到输出由该字符串开始的剩余串 else cout<<"未找到"<<endl; cp=strstr(a,"西北"); if(cp==NULL) cout<<"未找到"<<endl; else cout<<cp<<endl; return 0; } 5.9 使用递归和非递归的两种方法编写函数 char *itoa (int n,char *string); 将整数n转换为十进制表示的字符串。(在非递归方法中,可使用reverse()函数。) 解:递归方法分析。难度大,可用图解法: 每次调用除以10,以去除最后一位,以n=3657为例。 由此图可见,由string指向应填入的字符数组的相应位置。 由调用的最底层开始,回归时填入,每次回归,指针后移一位,由此得 char * itoal(int n,char *string){ if(n/10) string=itoal(n/10,string); *string++=n%10+48;//字符,ASCII码 return string; } 考虑,数字串结束符和负数,得完整的函数。 char * itoal(int n, char *string){ if(n<0){ *string++=’_’; n=-n; } if(n/10)string=itoal(n/10,string); *string++=n%10+48; *string=’\0’; return string; } 源代码: #include<iostream> using namespace std; char* reverse (char* s){ char temp,* temp1=s,* temp2=s; while(*temp2) temp2++; temp2--;//指针移回串尾 while(temp2-temp1>0){//注意此处,从串两头的指针同时向中间移动,重合或交错时停止 temp=*temp1; *temp1=*temp2; *temp2=temp; temp1++; temp2--; } return s; } char *itoa (int n,char *string){ char *temp=string; if(n<0){ *temp++='-'; n=-n; } do{//注意个位放在前了 *temp++=n%10+48; }while(n=n/10);//显式的循环 *temp='\0'; if(*string=='-') temp=string+1;//有负号仅反转数字部分 else temp=string; reverse(temp);//个位放到后面 return string; } char *itoa1 (int n,char *string){ if(n<0){ *string++='-'; n=-n; } if(n/10) string=itoa1(n/10,string);//隐式循环 *string++=n%10+48; //第一次是数字最高位放串的最前面的字符(不含符号),注意指针移动在后 *string='\0'; return string;//注意返回的指针已后移一字符 } char *itoa0 (int n,char *string){ itoa1(n,string); return string; } int main(){ int num; char st[20]; cin>>num; cout<<"输出数字串:"<<itoa(num,st)<<endl; cin>>num; cout<<"输出数字串:"<<itoa0(num,st)<<endl; return 0; } 5.10 头文件<ctime>中定义一个日期时间的结构: struct tm{ int tm_sec; //秒 int tm_min; //分 int tm_hour; //时 int tm_mday; //日 int tm_mon; //月 int tm_year; //年,实际放的是与1970年的差,如1990年为20 int tm_wday; //星期 int tm_yday; //一年中的第几天 int tm_isdst; //是否夏时制 }; 函数 time_t time(time_t *tp)是提取当前时间,time_t即长整型,代表从1970年1月1日00:00:00开始计算的秒数(格林尼治时间),放在首地址为tp的单元内。 函数 tm *localtime(const time_t *tp) 将tp地址单元中的时间转换为日期时间结构的当地时间;(函数 tm *gmtime(const time_t *tp)转换为日期时间结构的格林尼治时间;) 函数 char *asctime(tm *tb)将tb地址单元中的tm结构的日期时间转换为字符串(供显示),它有固有格式,如: Sun Sep 16 01:03:52 1973 利用以上资源,重新设计一个日期时间类(DataTime),要求定义对象时取当前时间进行初始化,显示时重取显示时刻的时间并显示出来。 解: #include<iostream> #include<ctime> using namespace std; class datatime{ tm *timedata; long allsecond; char *tmp; public: datatime(){ time(&allsecond); timedata=localtime(&allsecond); tmp=asctime(timedata); cout<<tmp<<endl; } void gettime(){ allsecond=time(NULL);//time有两种用法 timedata=localtime(&allsecond); tmp=asctime(timedata); cout<<tmp<<endl; } }; int main(){ char ch; datatime dt; cout<<"需要知道现在的日期和时间吗?(Y或N)"<<endl; cin>>ch; if(ch=='y'||'Y') dt.gettime(); return 0; } 5.11 完善自定义字符串类mystring,函数包括:构造函数、拷贝构造函数、析构函数,并重载运算符[ ],=(分别用mystring和C字符串拷贝),+(strcat),+=,<,==(strcmp)。 解: 此例既是对第4章的复习也是一个提高。拷贝构造函数的应用请参阅4.4.2节末尾两项说明,本例形参使用引用,仅在返回时调用了拷贝构造函数。运算符的重载请参阅4.5节。 #include<iostream> using namespace std; const int n=256; class mystring{ char str[n]; //存放字符串的数组容器 int maxsize; //最大可用元素数,可防止数组出界,提高健壮性 int last; //已用元素最大下标 public: mystring(){ last=0; maxsize=n; str[0]='\0'; cout<<"缺省构造函数"<<endl; } mystring(char *s){//当C字符串过长,初始化时采用截尾处理 last=-1; maxsize=n; do{ last++; str[last]=s[last]; }while(s[last]!='\0'&&last<maxsize-1); str[last] ='\0'; //截尾处理时,必须加串结束符 cout<<"构造函数"<<endl; } mystring(mystring & ms){ last=-1; maxsize=n; do{ last++; str[last]=ms.str[last]; }while(last<ms.last); cout<<"拷贝构造函数"<<endl; } ~mystring(){ cout<<"析构函数"<<endl; } void show(){//如需重载<<,则请参见9.3.3节,暂时未学到,替代方法是用show()函数 cout<<str<<endl; } char & operator[](int i){ //返回引用,可读可写 if(i>last) last=i; //下标运算符,可添加长度但不查边界 return str[i]; } mystring operator=(mystring &); mystring & operator=(char * ms);//这里重载的=是把C风格字符串赋给mystring mystring operator+(mystring &); mystring operator+=(mystring &); bool operator<(mystring &); bool operator==(mystring &); }; mystring mystring::operator=(mystring & ms){ last=-1; do{ last++; str[last]=ms.str[last]; }while(last<ms.last); return *this; } mystring & mystring::operator=(char* ms){ //这里返回值为引用,不调用拷贝构造函数 last=-1; do{ last++; str[last]=ms[last]; }while(ms[last]!='\0'&&last<maxsize-1); str[last] ='\0'; //截尾处理时,必须加串结束符 return *this; } mystring mystring::operator+(mystring & ms){//注意+和+=的不同 mystring temp(*this);//+必须在一份拷贝上进行 int i=-1; temp.last--;//串的结尾是结束符,连接时要覆盖掉 do{ temp.last++; i++; temp.str[temp.last]=ms.str[i]; }while(i<ms.last&& temp.last<maxsize-1); temp.str[temp.last] ='\0'; //截尾处理时,必须加串结束符 return temp;//拷贝的临时变量生命期在调用它的表达式中 } mystring mystring::operator+=(mystring & ms){//+=在对象自身进行 int i=-1; last--;//串的结尾是结束符,连接时要覆盖掉 do{ last++; i++; str[last]=ms.str[i]; }while(i<ms.last&&last<maxsize-1); str[last] ='\0'; //截尾处理时,必须加串结束符 return *this; } bool mystring::operator<(mystring & ms){ //重载<运算符 int i=0,k; do{ k=str[i]-ms.str[i]; i++; }while(k==0&&i<last&&i<ms.last); if(k<0) return true; if(i==last&&i!=ms.last) return true; return false; } bool mystring::operator==(mystring & ms){ int i=0,k; if(last!=ms.last) return false; do{ k=str[i]-ms.str[i]; i++; }while(k==0&&i<last); if(k!=0) return false; else return true; } int main(){ int i; char *sp1="东南大学",*sp2="交通学院",*sp3="学生",*sp4="教师"; mystring ms1(sp1),ms2(sp2),ms3(sp3);//ms1,ms2,ms3是用构造函数生成 mystring ms4(ms3),ms5=ms3,ms6; //ms4,ms5用拷贝构造函数生成;ms6用缺省构造函数 ms6=sp4; //ms6赋值是返回引用,不用拷贝构造函数 ms1.show(); ms2.show(); ms3.show(); ms4.show(); ms5.show(); ms6.show(); ms4=ms1+ms2+ms6;//注意temp和临时变量由拷贝构造函数生成 ms4.show(); ms1+=ms2+=ms3; ms1.show(); if(ms1<ms4) {ms1.show();cout<<"应排在"<<endl;ms4.show();cout<<"之前"<<endl;} else {ms1.show();cout<<"应排在"<<endl;ms4.show();cout<<"之后"<<endl;} ms6=ms1;//ms6赋值不是返回引用,必须调用拷贝构造函数建立临时对象 if(ms1==ms6) cout<<"串ms1与串ms6相同"<<endl; ms1="C++ programming language"; i=0; while(ms1[i]!='\0') cout<<ms1[i++];//读出 cout<<endl; ms1[i++]='.';//写入 ms1[i]='\0'; i=0; ms1.show(); return 0; } 5.12 将习题5.8中的字符串处理函数移植到mystring类中,其中strcat已重载为+运算符, 请将其它4个转为成员函数。对比成员函数与独立函数构造上有何不同? 解:这四个函数因mystring内部有串长,又要求下标索引,再加上str字符数组可直接使用,构造大不相同。 #include<iostream> using namespace std; const int n=256; class mystring{ char str[n]; //存放字符串的数组容器 int maxsize; //最大可用元素数,可防止数组出界,提高健壮性 int last; //已用元素最大下标 public: mystring(){ last=-1; maxsize=n; str[0]='\0'; cout<<"缺省构造函数"<<endl; } mystring(char *s){//当C字符串过长,初始化时采用截尾处理 last=-1; maxsize=n; do{ last++; str[last]=s[last]; }while(s[last]!='\0'&&last<maxsize-1); str[last] ='\0'; //截尾处理时,必须加串结束符 cout<<"构造函数"<<endl; } mystring(mystring & ms){ last=-1; maxsize=n; do{ last++; str[last]=ms.str[last]; }while(last<ms.last); cout<<"拷贝构造函数"<<endl; } ~mystring(){ cout<<"析构函数"<<endl; } void show(){//如需重载<<,则参见9.3.3节,暂时未学到,替代方法是用show()函数 cout<<str<<endl; } int strlen(){return last;}; void reverse(); int strchr(char c); int strstr (mystring str1); char & operator[](int i){ //返回引用,可读可写 if(i>last) last=i; //下标运算符,可添加长度但不查边界 return str[i]; } mystring & operator=(mystring &); mystring & operator=(char * ms);//这里重载的=是把C风格字符串赋给mystring mystring operator+(mystring &); //这里返回不能用引用 mystring & operator+=(mystring &); bool operator<(mystring &); bool operator==(mystring &); }; void mystring::reverse(){ int i=0,j=last-1; char temp; while(j>i){//注意此处,从串两头同时向中间移动,重合或交错时停止 temp=str[i]; //头尾交换 str[i]=str[j]; str[j]=temp; i++; j--; } } int mystring::strchr(char c){ int i; for(i=0;i!=last;i++) if(str[i]==c) return i; return -1; //未找到返回-1 } int mystring::strstr(mystring str1){ int i=0,k=1; while(str[i]!='\0'){//只要主串还有字符未查,则继续 while(str[i]!=str1[0]&&str[i]!='\0') i++;//找到主串含有子串的第一个字符,或主串查完停止 if(str[i]!='\0'){//核对子串其他字符 while(str[i+k]==str1.str[k]&&k<str1.last) k++;//字符串结束符不比较 if(k==str1.last) return i;//找到子串返回 k=1; i++; } } return -1; //未找到返回-1 } mystring & mystring::operator=(mystring & ms){//这里返回值改为引用,不调用拷贝构造函数 last=-1; do{ last++; str[last]=ms.str[last]; }while(last<ms.last); return *this; } mystring & mystring::operator=(char* ms){ //这里返回值为引用,不调用拷贝构造函数 last=-1; do{ last++; str[last]=ms[last]; }while(ms[last]!='\0'&&last<maxsize-1); str[last] ='\0'; //截尾处理时,必须加串结束符 return *this; } mystring mystring::operator+(mystring & ms){//注意+和+=的不同 mystring temp(*this);//+必须在一份拷贝上进行 int i=-1; temp.last--;//串的结尾是结束符,连接时要覆盖掉 do{ temp.last++; i++; temp.str[temp.last]=ms.str[i]; }while(i<ms.last&& temp.last<maxsi
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手

当前位置:首页 > 考试专区 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服