2004年全国计算机等级考试三级C语言全真上机试题解析 第1题: 函数ReadDat()实现从文件ENG.IN中读取一篇英文文章,存入到字符串数组xx中;请编制函数encryptChar(),按给定的替代关系对数组xx中的所有字符进行替代,仍存入数组xx的对应的位置上,最后调用函数WriteDat()把结果xx输出到文件PS10.DAT中。替代关系:f(p)=p*11 mod 256 (p是数组中某一个字符的ASCII值,f(p)是计算后新字符的ASCII值),如果原字符的ASCII值是偶数或计算后f(p)值小于等于32,则该字符不变,否则将f(p)所对应的字符进行替代。 void encryptChar() {int i; char *pf; for(i=0;i{pf=xx[i]; while(*pf!=0) {if(*pf==*pf/2*2||*pf*11%256<32) {pf++;continue;} *pf=*pf*11%256; pf++;}}} 注:在ReadDat()函数中由于fgets()函数读入数据时没有读入字符串结束符'\0',因而用while()循环在xx数组每一行未尾将换行符'\n'替换成结束符'\0'。编写的函数如下:该函数的基本算法是——让字符指针pf指向每一行的开头然后逐一往后移动,在移动过程中按要求进行转换。*pf=*pf/2*2用于判断是否为偶数。if()条件语句用于控制不替代字符。 第2题: 函数ReadDat()实现从文件in.dat中读取20行数据存放到字符串数组xx中(第行字符串长度均小于80)。请编制函数jsSort(),其函数的功能是:以行为单位对字符串按给定的条件进行排序,排序后的结果仍按行重新存入字符串数组xx中,最后调用函数WriteDat()把结果xx输出到文件out.dat中。 条件:从字符串中间一分为二,左边部分按字符的ASCII值升序排序,排序后左边部分与右边部分进行交换。如果原字符串长度为奇数,则最中间的字符不参加处理,字符仍放在原位置上。 例如:字符串 d c b a h g f e 则处理后字符串 h g f e a b c d void jsSort() {int i,strl,half,j,k; char ch; for(i=0;i<20;i++) {strl=strlen(xx[i]); half=strl/2; for(j=0;jfor(k=j+1;kif(xx[i][j]>xx[i][k]) {ch=xx[i][j]; xx[i][j]=xx[i][k]; xx[i][k]=ch;} for(j=half-1,k=strl-1;j>=0;j--,k--) {ch=xx[i][j]; xx[i][j]=xx[i][k]; xx[i][k]=ch;}} 注:先采用冒泡法对左边部分进行升序排序,然后将排序后的左半与右半按对应位进行调换。 第3题: 已知数据文件IN.DAT中存有300个四位数,并已调用读函数ReadDat()把这些数存入数组a中,请编制一函数jsValue(),其功能是:求出千位数上的数加百位数等于十位数上的数加个位数上的数的个数cnt,再求出所有满足此条件的四位数平均值pjz1,以及不满足此条件的四位数平均值pjz2,最后调用写函数writeDat()把结果输出到OUT.DAT文件。例如:7153,7+1=5+3,则该数满足条件计算平均值pjz1,且个数cnt=cnt+1。8129,8+1<>2+9,则该数不满足条件计算平均值pjz2. jsvalue() { int i,g,s,b,q,k=0; for(i=0;i<300;i++) {g=a[i]%10; s=a[i]%100/10; b=a[i]/100%10; q=a[i]/1000; if((q+b)==(s+g)) {cnt++;pjz1+=a[i];} else {k++;pjz2+=a[i];} } pjz1/=cnt; pjz2/=k;} 注:该题的关键在于取出一个数的个、十、百、千位上的数。a[i]%10结果为个位数,a[i]%100/10先对100求余得出后两位数然后再除10,由于为整数因此得出上一个后两位数的第一位。依此类推 第4题: 下列程序的功能是:先出5000以下符合条件的自然数。条件是:千位数字与百位数字之和等于十位数字与个位数字之和,且千位数字与百位数字之和等于个位数字与千位数字之差的确10倍。计算并输出这些四位自然数的个数cnt以及这些数的和sum。请编写函数countvalue void countValue() {int i; for(i=1000;i<5000;i++) if((i/1000+i/100%10)==(i/10%10+i%10)) if((i/1000+i/100%10)==(i%10-i/1000)*10) {cnt++; sum+=i;}} 注:该题的关键亦是如何取出各位数字 第5题: 已知在文件IN.DAT中存有100个产品销售记录,每个产品销售记录由产品代码dm(字符型4位),产品名称mc(字符型10位),单价dj(整型),数量sl(整型),金额je(长整型)四部分组成。其中:金额=单价*数量计算得出。函数ReadDat()是读取这100个销售记录并存入结构数组sell中。请编制函数SortDat(),其功能要求:按产品代码从大到小进行排列,若产品代码相同,则按金额从大到小进行排列,最终排列结果仍存入结构数组sell中,最后调用函数WriteDat()把结果输出到文件OUT10.DAT中。 void SortDat() {int i,j; PRO swap; for(i=0;ifor(j=0;j{ if(strcmp(sell[j].dm,sell[j+1].dm)<0) {swap=sell[j]; sell[j]=sell[j+1]; sell[j+1]=swap;} if(strcmp(sell[j].dm,sell[j+1].dm)==0&&sell[j].je{swap=sell[j]; sell[j]=sell[j+1]; sell[j+1]=swap; }}} 注:这时也是采用冒泡法进行排序。与前面的冒泡法在写法上有所不同请注意区分。同时注意结构体变量的引用格式。 第6题: 下列程序的功能是:选取出100以上1000以内所有个位数字与十位数字之和被10除所得余数恰是百位数字的素数(如293)。计算并输出上述这些素数的个数CNT以及这些素数值的和SUM。请编写函数COUNTVALUE()实现程序要求 void countvalue() {int i,j; for(i=100;i<1000;i++) {for(j=2;jif(i%j==0) break; if(j==i&&((i%10+i/10%10)%10==i/100)) {cnt++; sum+=i;}}} 注:内嵌的for()循环用来判断i以前的数有否能整除i的数若能则提前终止循环,第二个if()中j= =i的作用是配合前面的for()判断i是否是素数。 第7题: 下列程序的功能是:在三位整数(100至999)中寻找符合条件的整数并依次从小到大存入数组中;它既是完全平方数,又是两位数字相同,例如144、676等。 int jsvalue(int bb[]) {int i,j,k=0,g,s,b; for(i=100;i<=999;i++) {g=i%10; s=i/10%10; b=i/100; if((i==(int)sqrt(i)*(int)sqrt(i))&&(g==s//s==b//b==g)) bb[k++]=i;} } 注:注意在i==(int)sqrt(i)*(int)sqrt(i)中只有当i是完全平方数时开平方后再取整才不会丢失任何数据。 第8题: 函数ReadDat()实现从文件IN.DAT中读取一篇英文文章存 入到字符串数组xx中,请编制函数CharConvA(),其函数的功能是:以行为单位把字符串中的最后一个字符的ASCII值右移4位后加最后第二个字符的ASCII值,得到最后一个新的字符,最后第二个字符的ASCII值右移4位后加最后第三个字符的ASCII值,得到最后第二个新的字符,依此类推一直处理到第二个字符,第一个字符的ASCII值加原最后一个字符的ASCII值,得到第一个新的字符,得到的新字符分别存放在原字符串对应的位置上。最后已处理的字符串仍按行重新存入字符串数组xx中。 void CharConvA(void) {int i,j,strl; char ch; for(i=0;i{strl=strlen(xx[i]); ch=xx[i][strl-1]; for(j=strl-1;j>0;j--) {xx[i][j]>>=4; xx[i][j]+=xx[i][j-1];} xx[i][0]+=ch;}} 注:在该题中主要是控制好每一个字符的走动,由于最后要用到原来的最后一个字符故先将其存入一个字符变量中。 第9题: 现有一个10个人100行的选票数据文件IN.DAT,其数据存放的格式是每条记录的长度均为10位,第一位表示第一个人的选中情况,第二位表示第二个人的选中情况,依此类推 :内容均为字符0和1,1表示此人被选中,0表示此人未被选中,若一张选票人数小于等于5个人时被认为无效的选票。给定函数ReadDat()的功能是把选票数据读入到字符串数组xx中。请编制函数CountRs()来统计每个人的选票数并把得票数依次存入yy[0]到yy[9]中。 void countrs(void) {int i,j,count; for(i=0;i<300;i++) {count=0; for(j=0;j<10;j++) if(xx[i][j]=='1') count++; if(count<=5) continue; for(j=0;xx[i][j];j++) if(xx[i][j]=='1') yy[j]++;}} 注:题目要求将那些选了不超过5人的选票视为无效票,即一张选票中如果‘1’不超过5个则为无效选票。该题先用for()循环对100行选票进行循环,在循环内先进行用for()循环数出这张选票中选中的人数(count)再用if()判断,如果选中人数小于等于5则continue即判断下一张选票,否则用内嵌的for()对行内的数据进行判断,注意如果数据为‘1’时才对对应的人增加1。 第10题:设有n个人围坐一圈并按顺时针方向从1到n编号,从第s个人开始进行1到m的报数,报数到第个m人,此人出圈,再从他的下一个人重新开始1到m的报数,如此进行下去直到所有的人都出圈为止。现要求按出圈次序,每10人一组,给出这n个人的顺序表。请考生编制函数Josegh()实现此功能并调用函数WriteDat()把结果p输出到文件OUT.DAT中。设n=100,c=1,m=10. (1)将1到n个人的序号存入一维数组p中; (2)若第i个人报数后出圈,则将p[i]置于数组的倒数第i个位置上,而原来第i+1个至倒数第i个元素依次向前移动一个位置; (3)重复第(2)步直至圈中只剩下p[1]为止。 void Josegh(void) {int i,j,s1,w; s1=s; for(i=1;i<=n;i++) p[i-1]=i; for(i=n;i>=2;i--) {s1=(s1+m-1)%i; if(s1==0) s1=i; w=p[s1-1]; for(j=s1;jp[j-1]=p[j]; p[i-1]=w;}} 题中第一个for()循环是先对数组p赋初值。在第二个for()中用i来控制没出圈的总人数,s1=(s1+m-1)%i的作用是找出报数后出圈人的下标,其中对i求余的作用是使报 数按圈进行(即报到尾后又从头报),该算法在很多题目中都用到。由于求余的作用当报数正好到最后一个时s1为0,故而要进行if(s1==0)的判断。内嵌的for()循环是将出圈以后的人依次往前移。
|