【4.91】分析:分析题目,我们可以将题目进行抽象:在有放回的前提下,求全部从m个不同的元素中任取n个元素的排列。根据题目的含义,我们可以用整数0~m-1表示这m个不同的元素,将要生成的n个元素分为两部分:第一个元素和其它n-1个元素。如果n=1,即要从m个元素中任取1种,这样有m种不同得取法,我们可以直接使用循环完成。若n>1,则可以知道,第一个元素一定有m种不同的取法,可以针对第一个元素m种不同取法种的1种,对后面的n-1个元素进行同样的(递归)操作即可产生一种新的不同的排列。具体算法描述如下:
fun(指向第一个元素的指针,从m个元素中,取n个元素)
{ for ( i=0; i { 确定第一个元素的选取方法:=i; if (n>1) fun(指向下一个元素的指针,从m中,取n-1个) else 完成一种排列 } } 根据以上算法分析可以得出程序。 参考答案: #include int a[10]; fun( int *p, int m, int n ) /* 从m个元素中取n个存入数组p中 */ { int i; /* 用数0~m-1表示m个不同的元素 */ for( i=0;i { *p = i; if( n > 1 ) fun( p+1, m, n-1); else print(p); } } print( int *p ) { int *q; for( q=a;q<=p;q++ ) /* 输出结果,将整数转换为字母a起始的序列 */ printf("%c", 'a'+ *q); printf("\t"); } main( ) { int m, n; printf("\nEnter m n:"); scanf("%d%d", &m, &n); fun( a, m, n); } 【4.92】参考答案: smmt ( char s[ ] ) /* 指针s指向字符串的第一个字符 */ { char *p; p=s; while(*p!='\0') p++; p--; /* 指针p指向字符串的最后一个字符 */ if(p==s) return(1); /* 两个指针指向同一个字符表示字符串对称 */ else { if(*s!=*p) return(0); /* 两个指针指向字符不等表示字符串不对称 */ else { *p='\0'; smmt(s+1); /* 取掉首尾比较过的字符继续比较 */ } } } 【4.93】参考答案: #include int n, r, flag; /* flag:标志,=0:表示要另起一行 */ main( ) { int s; printf("Enter N,R:"); scanf("%d%d", &n, &r); printf("combinations:\n"); flag=1; combination (1,r); } combination ( s, j ) int s, j; /* 从s开始选j个元素 */ { int i,k; for( i=s;i<=n-j+1;i++ ) { if( flag ) for( k=0;k printf("%3d ", i); flag=0; if(j>1) combination ( i+1, j-1 ); else { putchar('\n'); flag=1; } } } 【4.94】分析:此题给出的参考答案使用了指针和函数递归的概念。读者在学习完指针的概念后再研究此题。放于此处主要是便于和其它排序方法比较。 合并排序法排序的步骤是:第一次将数组中相邻的2个数两两排序,第二遍4个4个地排序,第三遍8个8个地排序...... 。程序中的合并排序函数(mergesort)采用了递归调用。例如有一组数是:4,3,1,81,45,8,0,4,-9,26,7,4,2,9,1,-1 采用合并排序法的过程如下: 未排序时 4 3 1 81 45 8 0 4 -9 26 7 4 2 9 1 -1 第一遍后 3 4 1 81 8 45 0 4 -9 26 4 7 2 9 -1 1 第二遍后 1 3 4 81 0 4 8 45 -9 4 7 26 -1 1 2 9 第三遍后 0 1 3 4 4 8 45 81 -9 -1 1 2 4 7 9 26 第四遍后 -9 -1 0 1 1 2 3 4 4 4 7 8 9 26 45 81 参考答案: #define N 16 #include "stdio.h" merge(a,b,c,m) /* 数组合并函数:将长度为m的*/ int a[],b[],c[],m; /* 数组a、b合并到c */ { int i=0,j=0,k=0; while(i if(a[i]>b[j]) c[k++]=b[j++]; /* 将a[i]、*b[j]中的小 */ else c[k++]=a[i++]; /* 者存入c[k] */ while(i while(j } mergesort(w,n) /* 数组排序函数: 对长度为n */ int w[],n; /* 的数组w排序 */ { int i,t,ra[N]; for(i=1;i if(i==n) { if(n>2) /* 递归调用结束条件 */ { mergesort (w,n/2); /* 将数组w一分为二,递归调 */ mergesort (w+n/2,n/2); /* 用mergesort */ merge( w,w+n/2,ra,n/2 ); /* 将排序后的两数组重新合并 */ for(i=0;i w[i]=ra[i]; } else if(*w>*(w+1)) { t=*w; *w=*(w+1); *(w+1)=t; } } else printf("Error:size of array is not a power of 2/n"); } main( ) { int i; static int key[N]={4,3,1,81,45,8,0,4,-9,26,7,4,2,9,1,-1}; mergesort(key,N); for(i=0;i printf("%d ",key[i]); printf("\n"); } 【4.95】参考答案: #include "stdio.h" main( ) { char s[21],*p,*q; gets(s); p=s; q=s; while(*q!='\0') q++; q-=2; while(p if(*p++ != *q--) /* 指针p、q同时向中间移动,比较对称的两个字符 */ { printf("NO\n"); break; } if(p>=q) printf("YES\n"); } 【4.96】参考答案: strcut(s,m,k) char s[ ]; int m,k; { char *p; int i; p=s+m; /* 指针p指向要被删除的字符 */ while((*p=*(p+k))!='\0') /* p+k指向要前移的字符 */ p++; } 【4.97】参考答案: strchg(s) char *s; { char c,*p; p=s; while(*p!='\0') p++; p--; while(s
{ c=*s; *s++=*p; *p--=c; } } 【4.98】参考答案: insert(s1,s2,ch) char s1[],s2[],ch; { char *p,*q; p=s1; while(*p++!=ch) ; while(*s2!='\0') { q=p; while(*q!='\0') q++; while(q>=p) *(q+1)=*q--; *++q=*s2++; p++; } } 【4.99】参考答案: strcnb(s1,s2) char s1[],s2[]; { char *p; int i=1; p=s1; while(*p!='\0') p++; while((*p++=*s2++)!='\0') ; /* 将s2接于s1后面 */ p=s1; while(*p!='\0') /* 扫描整个字符串 */ { if(*p==' ') /* 当前字符是空格进行移位 */ { while(*(p+i)==' ') i++; /* 寻找当前字符后面的第一个非空格 */ if(*(p+i)!='\0') { *p=*(p+i); /* 将非空格移于当前字符处 */ *(p+i)=' '; /* 被移字符处换为空格 */ } else break; /* 寻找非空格时到字符串尾,移位过程结束 */ } p++; } } 【4.100】参考答案: #include "stdio.h" struct strnum { int i; char ch; } main( ) { char c; int i=0,k=0; struct strnum s[100]={0,NULL}; while((c=getchar())!='\n') { for(i=0;s[i].i!=0;i++) { if(c==s[i].ch) { s[i].i++; break; } } if(s[i].i==0) { s[k].ch=c; s[k++].i=1; } } i=0; while(s[i].i>0) { printf("%c=%d ",s[i].ch,s[i].i); i++; } } 【4.101】分析:程序中函数cmult的形式参数是结构类型,函数cmult的返回值也是结构类型。在运行时,实参za和zb为两个结构变量,实参与形参结合时,将实参结构的值传递给形参结构,在函数计算完毕之后,结果存在结构变量w中,main函数中将cmult返回的结构变量w的值存入到结构变量z中。这样通过函数间结构变量的传递和函数返回结构型的计算结果完成了两个复数相乘的操作。 参考答案: #include "stdio.h" struct complx { int real; /* real为复数的实部 */ int im; /* im为复数的虚部 */ }; main( ) { static struct complx za = {3,4} /* 说明结构静态变量并初始化 */ static struct complx zb = {5,6}; struct complx x, y, z; struct complx cmult();/* 说明函数cmult的返回值类型是结构complx型 */ void cpr( ); z=cmult(za, zb); /* 以结构变量调用cmult函数,返回值赋给结构变量z */ cpr (za, zb, z); /* 以结构变量调用cpr函数,输出计算结果 */ x.real = 10; x.im = 20; y.real = 30; y.im = 40; /* 下一组数据 */ z = cmult (x, y); cpr (x, y, z); } struct complx cmult(za, zb) /* 计算复数za×zb,函数的返回值为结构类型 */ struct complx za, zb; /* 形式参数为结构类型 */ { struct complx w; w.real = za.real * zb.real - za.im * zb.im; w.im = za.real * zb.im + za.im * zb.real; return (w); /* 返回计算结果,返回值的类型为结构 */ } void cpr (za,zb,z) /* 输出复数za×zb=z */ struct complx za, zb, z; /* 形式参数为结构类型 */ { printf ("(%d+%di)*(%d+%di)=", za.real, za.im, zb.real, zb.im); printf ("(%d+%di)\n", z.real, z.im); } 【4.102】参考答案一: /*这份代码经源码格式软件格式化过 yang_hx@neusoft.com */ #include "stdio.h" struct student { int n ; int mk ; } ; main() { int i,j,k,count=0,no ; struct student stu[100],*s[100],*p ; printf("\nPlease enter mark(if mark<0 is end)\n"); for(i=0;i<100;i++) { printf("No.%04d==",i+1); scanf("%d",&stu[i].mk); s[i]=&stu[i]; stu[i].n=i+1 ; if(stu[i].mk<=0)break ; for(j=0;j
for(k=j+1;k<=i;k++) if(s[j]->mk { p=s[j]; s[j]=s[k]; s[k]=p ; } } for(no=1,count=1,j=0;j
{ if(s[j]->mk>s[j+1]->mk) { printf("\nNo.%3d==%4d%4d : ",no,s[j]->mk,count); for(k=j-count+1;k<=j;k++) { printf("%03d ",s[k]->n); if((k-(j-count))%10==0&&k!=j) printf("\n "); } count=1 ; no++; } else count++; } }参考答案二: /*这份代码经源码格式软件格式化过 yang_hx@neusoft.com */ #include "stdio.h" #define N 5 struct student { int number ; int score ; int rank ; int no ; } stu[N]; main() { int i,j,k,count,rank,score ; struct student temp ; for(i=1;i<=N;i++) { printf("Enter N.o %d=",i); scanf("%d%d",&temp.number,&temp.score); for(j=i-1;j>0;j--) if(stu[j-1].score stu[j]=stu[j-1]; else break ; stu[j]=temp ; } stu[0].rank=1 ; count=1 ; k=0 ; for(i=0;i { score=stu[i].score ; rank=stu[i].rank ; if(stu[i+1].score==stu[i].score) { stu[i+1].rank=stu[i].rank ; count++; } else { for(j=0;j stu[k+j].no=count-j ; stu[i+1].rank=stu[i].rank+1 ; count=1 ; k=i+1 ; } if(i==N-2) for(j=0;j stu[k+j].no=count-j ; } for(i=0;i { rank=stu[i].rank ; count=stu[i].no ; printf("\n%3d (%3d)-%d: ",rank,stu[i].score,count); for(k=1;k<=count;k++) if((k-1)%3!=0) printf("%d ",stu[i+k-1].number); else printf("\n %d ",stu[i+k-1].number); i+=count-1 ; } }【4.103】参考答案: /*这份代码经源码格式软件格式化过 yang_hx@neusoft.com */ #include "stdio.h" struct time { int hour ; int minute ; int second ; } ; main() { struct time now ; printf("Please enter now time(HH,MM,SS)=\n"); scanf("%d,%d,%d",&now.hour,&now.minute,&now.second); now.second++; if(now.second==60) { now.second=0 ; now.minute++; } if(now.minute==60) { now.minute=0 ; now.hour++; } if(now.hour==24) now.hour=0 ; printf("\nNow is %02d:%02d:%02d",now.hour,now.minute,now.second); }【4.104】参考答案: /*这份代码经源码格式软件格式化过 yang_hx@neusoft.com */ #include #define SIZE 3 /* 定义结构 */ struct student { long num ; char name[10]; int age ; char address[10]; } stu[SIZE],out ; void fsave() { FILE*fp ; int i ; /* 以二进制写方式打开文件 */ if((fp=fopen("student","wb"))==NULL) { printf("Cannot open file.\n"); /* 打开文件的出错处理 */ exit(1); /* 出错后返回,停止运行 */ } /* 将学生的信息(结构)以数据块形式写入文件 */ for(i=0;i printf("File write error.\n"); /* 写过程中的出错处理 */ fclose(fp); /* 关闭文件 */ } main() { FILE*fp ; int i ; /* 从键盘读入学生的信息(结构) */ for(i=0;i { printf("Input student %d:",i+1); scanf("%ld%s%d%s", &stu[i].num,stu[i].name,&stu[i].age,stu[i].address); } fsave(); /* 调用函数保存学生信息 */ fp=fopen("student","rb"); /* 以二进制读方式打开数据文件 */ printf(" No. Name Age Address\n"); /* 以读数据块方式读入信息 */ while(fread(&out,sizeof(out),1,fp))printf("%8ld %-10s %4d %-10s\n", out.num,out.name,out.age,out.address); fclose(fp); /* 关闭文件 */ getch(); }【4.105】参考答案: /*这份代码经源码格式软件格式化过 yang_hx@neusoft.com */ #include main() { FILE*fp ; char str[100],filename[15]; int i ; if((fp=fopen("test","w"))==NULL) { printf("Cannot open the file.\n"); exit(0); } printf("Input a string:"); gets(str); /* 读入一行字符串 */ /* 处理该行中的每一个字符 */ for(i=0;str[i]&&i<100;i++) { /* 若是小写字母 */ if(str[i]>='a'&&str[i]<='z')str[i]-='a'-'A' ; /* 将小写字母转换为大写字母 */ fputc(str[i],fp); /* 将转换后的字符写入文件 */ } fclose(fp); /* 关闭文件 */ fp=fopen("test","r"); /* 以读方式打开文本文件 */ fgets(str,100,fp); /* 从文件中读入一行字符串 */ printf("%s\n",str); fclose(fp); getch(); }【4.106】参考答案: /*这份代码经源码格式软件格式化过 yang_hx@neusoft.com */ /*这份代码经源码格式软件格式化过 yang_hx@neusoft.com */ #include "stdio.h" FILE*fp ; void main() { int c,d ; if((fp=fopen("d:\\tc\\test8.c","r"))==NULL) exit(0); while((c=fgetc(fp))!=EOF) /* 如果是字符注释的起始字符'/' */ /* 则判断下一个字符是否为'*' */ if(c=='/')if((d=fgetc(fp))=='*')in_comment(); /* 调用函数处理(删除)注释 */ /* 否则原样输出读入的两个字符 */ else { putchar(c); putchar(d); } else /* 判断是否是字符'或" */ if(c=='\''||c=='\"')echo_quote(c); /* 调用函数处理字符'或"包含的字符 */ else putchar(c); } in_comment() { int c,d ; c=fgetc(fp); d=fgetc(fp); while(c!='*'||d!='/') { /* 连续的两个字符不是 * 和 / 则继续处理注释 */ c=d ; d=fgetc(fp); } } echo_quote(c) int c ; /* c中存放的是定界符'或" */ { int d ; putchar(c); /* 读入下一个字符判断是否是定界符c */ while((d=fgetc(fp))!=c) { putchar(c); /* 当不是定界符c时继续循环 */ /* 若出现转义字符\ */ if(d=='\\')putchar(fgetc(fp)); /* 则下一个字符不论是何均原样输出 */ } putchar(d); }
mk)