第一篇:计算机三级(C语言)上机考试题型总结与注意事项
C语言 三级上机考试题型总结与注意事项
按前面的分题型讲解,三级上机考试100道题被分为9大题型。每种题型在题库中占的比例也已经在题型名字后面的括号中注明。
题型
一、结构体数组排序问题(11%)
题型
二、对四位数先筛选再处理的问题(35%)
题型
三、整数处理问题(17%)
题型
四、对字符数组中的字符进行替换的问题(18%)
题型
五、对字符串数组进行排序的问题(6%)
题型
六、特殊排序问题(5%)
题型七、二次排序问题(2%)
题型
八、选票统计问题(3%)
题型
九、数列问题(3%)
注意事项: 应考策略:
1、首先仔细审题,看清题目要求,避免眼高手低。
2、在头文件下面,看清试题程序中已经定义的变量及其类型。
3、试题程序中已经定义的结果变量不要重复定义(中间变量没关系)。
4、看清试题程序中定义好的变量后,注意试题程序中有没有进行初始化。重复初始化没关系,但是不进行初始化会出问题。
5、按照题目要求,仔细分析,平稳答题,时间绝对够用。
6、答完题先保存,再编译,有语法错误则改正,编译通过后则运行。
7、以运行结果为准,检查是否具有题目要求的功能,以排除逻辑错误。
8、时间很充足,急着早交卷没用,确定无误后再交卷。
常见小错误
1、字符串的比较没有使用strcmp()函数。
2、把等号错写为赋值符号。
3、在程序进行中,尤其是多次循环的程序中,没有考虑到变量值的变化。
4、没有注意循环的作用范围,少写{}。
5、没有注意运算符的优先级。
还有很多其它的小错误,在上机的过程中会出现。不上机运行,总是会有想不到的错误,多上机运行,也可以发现很多小技巧。
常用运算符优先级(从高到低)
1、[ ]
。(结构体成员引用运算符)
2、++---(负号)()(强制转换运算符)*(指针运算符)&(取地址运算符)
3、*(乘)/ %
4、+
5、<<
>>
6、<
<=
>
>=
7、==!=
8、&&
9、||
10、=
+=
*=
/=
%=(赋值运算符号)
11、,(逗号)
C语言 三级上机考试中最常用的基础知识: 2010-04-22 21:
51一、上机考试题中的常用操作
上机考试题中有许多操作经常用到,以下是几种非常常用的,还有一些更细节的东西在以后的具体题目中会着重分析。
1、对数组元素进行排序
如对数组a[N]进行从小到大排列(或叫升序排列),程序如下:
int i,j,t;for(i=0;i
从数组中的第一个元素开始,与它后面的所有元素依次进行比较,如果发现前面的比后面的大,就进行交换,否则不进行处理。a[0]将是N个元素中最大的,a[1]将是除a[0]以外的元素中最大的。这样一直到倒数第二个元素。最后一个元素后面没有元素了,所以i 这种操作的特点: 当i变化以后,第i个元素之前的元素就已经确定了,只有后面的元素才会在程序往下执行时发生变化。比如对数据3,2,1,6,5进行升序排列,程序执行时数据的状态变化为: 1,x,x,x,x 1,2,x,x,x 1,2,3,x,x 1,2,3,5,6 所以说,如果要求将a[N]中最小的10个元素按从小到大的顺序排列到数组的前部的话,则只须对数组的前10个元素进行处理,相应的程序改为: int i,j,t;for(i=0;i<10;i++)for(j=i+1;j 而不必对i>=10 的元素处理。 这种操作在三级考试题中经常用到。其中的交换条件,也就是if()中的内容,根据问题的要求会有所变化;比如把从小到大改为从大到小,或者改为按元素对10求余的余数大小进行从小到大排列,相应的程序中if()语句改为: if(a[i] if(a[i]%10>a[j]%10)t=a[i],a[i]=a[j],a[j]=t; 2、将筛选出的数组元素统计个数,并存入另一数组 通常题目中会预先定义一个名为cnt的整型变量,用于个数统计。 比如,将整型数组a[200]中能被3整除的数统计个数,并存入数组b[200]中,程序如下: int i;cnt=0;(如果题目已经初始化为0了,该句就可以省了)for(i=0;i<200;i++)if(a[i]%3==0)b[cnt++]=a[i];最后一句是一种精简的写法,相当于:b[cnt]=a[i],cnt++;这里cnt也用来表示数组 b的元素号,这样可以节省定义变量的个数,不必再定义另一个变量专门表示数组b的元素号。只要a[i]满足条件a[i]%3==0,个数cnt 就加1,最后cnt 就是所有这样的元素的个数。 还是像排列顺序问题中一样,if()中内容根据问题的要求相应地进行改变。 3、整数各位数字的求法 有很多题目中都涉及到对一个四位数或三位数的各位数字进行判断,因此必然用到对整数各位数字的求解。 如对四位数x,它各位数字: 千位:qw=x/1000;百位:bw=x%1000/100;十位:sw=x%100/10;个位:gw=x%10;小知识点: 在没有进行强制类型转换的情况下,对整型变量除10,结果还是整型,没有小数,所以数字的位数就少了一位。利用这个特点,可以求出一个整数有多少位,并能能过%10的操作依次求出这个数的个位、十位、百位„„在以后的一个例题中会用到这一点。 4、结构体数组的引用 如以下程序: Typedef struct {char dm[5];char mc[10];int je;int dj;}PRO;PRO sell[100];sell[100]为结构体数组,引用其中某一元素,和数组一样,sell[i]为第i个元素;引用其中的某一元素的某一项,用sell[i].dm;sell[i].mc;sell[i].je 等。符号‘.’是结构体引用运算符,它的优先级和圆括号()、下标运算符[ ]、指向结构体运算符 —> 一样,在所有运算符中是最高的。 5、素数的判断 比如,要判断整数n是否为素数,程序如下(大致分为两部分): int i;for(i=2;i if(n%i==0)break; if(i==n)„„; // n 是素数 else „„; // n不是素数 程序思路解析: 素数也就是不能分解为两个因数相乘。从2开始检查,一直到n-1,如果n%i==0,也就是说i是n的因数,则中断循环。否则继续检查下一个数。 因此,如果中间发现了n的因数(n不是素数),for循环就中断了,则最后i的值小于n;如果从2到n-1都没有n 的因数(n是素数),则for循环会进行到底,最后i的值就等于n。最后通过判断i的值来判断n是否为素数就可以了。 在三级考试中,要注意审题,有的题目是让考生自己写判断素数的程序语句,也有个别题目在题目中给出了判断素数的子函数,因此这样的话,只需要调用题目中给出的函数就可以了,而不需要做重复工作。当然如果做了重复工作也没有关系,不会影响最后结果的正确性,只是多费点时间而已。关于判断素数,程序可以写的更精简,执行效率也可以更高,不过为了简单易懂,这里不再多写,并且在以后的题目中,也都以这种形式来判断素数。 6、return 语句。 在写子函数时,有时会要求函数返回一个值,只要用return 语句将其返回就可以了。return后面的括号可以写也可以不写。需要注意的是: 一个函数最多只能有一个返回值,并且只能执行一次返回值的操作。在执行return语句之后,函数的调用将结束,也就是说子函数中的程序将会终止运行。 也就是说,从某种意义上讲,子函数中的return语句具有类似于break语句的作用,可以用于控制子函数中的循环语句的执行。这在以后的例题中也会用到,有助于理解一些问题。 比如,要写一个判断素数的子函数,要求是素数则返回1,不是素数则返回0,程序如下: int is sushu(int n){ int i;for(i=2;i 按照上面讲的判断素数的函数原理,以及有关ruturn语句的“类似”break语句的特点,不难这个小函数。 二、常用库函数(使用频率与顺序有关): 1、strlen(str) 计算字符串的长度(不包括字符串结束标志‘ ’)。 2、strcmp(str1,str2) 比较两个字符串的大小,其实函数的返回值就是str1与str2对应位置上第一对不相等的字符的差值。显然,如果strcmp(str1,str2)>0,则str1>str2;如果strcmp(str1,str2)<0,则str1 3、strcpy(str1,str2)将str2复制到str1里面。Str2本身没有发生变化。 4、strrev(str)---------将str中字符进行倒排。 5、fabs(x)---------计算x的绝对值。 6、sqrt(x)---------计算x的开方。 7、isalpha(c)检查字符c是否为字母。是则函数返回值为1;不是则函数返回值为0。alpha是单词“alphabet”的前5个字母。 8、isalnum(c)检查字符c是否为字母或数字。是则函数返回值为1;不是则函数返回值为0。alnum是单词alphabet 和单词number 的缩写。 三、最好能看懂的有关文件操作的函数 以下是比较常见的10个,只需要能看懂的有关文件的函数,加粗的为重点。 1、fopen(“文件名”,“使用文件方式”)(引号不能漏掉,以下同)如:fopen(“1.c”, “r”)----------以读的方式打开文件 1.c。如果不能打开,则返回一个NULL。 2、fclose(文件指针)用于关闭文件。 如fclose(fp)------------关闭fp所指向的文件。 3、fgetc(文件指针) 如:c=fgetc(fp)-------从fp指向的文件中读取一个字符,赋给变量c。 4、fputc(字符,文件指针)如:fputc(c , fp)-------把字符c写到fp指向的文件中去。 5、fgets(字符串,字符个数,文件指针)如:fgets(str,n,fp)-------从fp指向的文件中读取n-1个字符,写入字符数组str,并在最后加上一个 ‘ ’。若在读完n-1个字符前遇到换行符或文件结束标志EOF则读入过程结束。 6、fputs(字符串,文件指针)如:fputs(str,fp)---------把字符串str输出到(写入)fp指向的文件中。 7、fprintf(文件指针,“格式字符串”,输出表列)如:fprintf(fp, “%d”,n)------把n按%d格式输出到(写入)fp指向的文件中。 8、fscanf(文件指针,“格式字符串”,输入表列)如:fscanf(fp, “%d”,&n)------从fp指向的文件中读取一个整数,将它赋给变量n。 9、feof(文件指针)如:feof(fp)-----检查fp指向的文件是否结束。当遇到文件结束符EOF时返回非零值,否则返回0。EOF是文件结束标志,即-1。 C语言 三级上机考试分题型讲解之题型一,结构体数组排序问题(11%)2010-04-22 22:24三级考试中的题目重复率高,只是具体条件有微小变化,如从小到大改为从大到小,按名称排列改为按代码排列,按这种关系替换改为按那种关系替换等。如果理解了每类题目的做法,只要在考试中注意审题,结合具体条件就可以了。本章详细讲解每个题型的做法,并在每一题型后面的括号中统计了这类题目在上机题库中占的比例。 题型一,结构体数组排序问题(11%) 包括两类,一类是对产品销售记录的排序(9%),另外一类是对多组(通常为200组)整数筛选并排序(2%)。 例 1、已知在文件IN1.DAT中存有100个产品销售记录,每个产品销售记录由产品代码dm(字符型4位)、产品名称mc(字符型10位)、单价dj(整型)、数量sl(整型)、金额je(长整型)五部分组成。其中:金额=单价×数量。函数ReadDat()的功能是读取这100个销售记录并存入结构数组sell中。请编制函数SortDat(),其功能要求:按产品名称从小到大进行排列,若产品名称相同,则按金额从小到大进行排列,最终排列结果仍存入结构数组sell中,最后调用函数WriteDat()把结果输出到文件OUT1.DAT中。 注意:部分源程序已给出。请勿改动主函数main()、读数据函数ReadDat()和输出数据函数WriteDat()的内容。 【试题程序】 #include 认识 #include 用到相应的库函数时,要注意必须有相应的头文件 #include #include #define MAX 100 typedef struct { char dm[5]; /*产品代码*/ char mc[11]; /*产品名称*/ int dj; /*单价*/ int sl; /*数量*/ long je; /*金额*/ }PRO; PRO sell [MAX]; void ReadDat(); void WriteDat(); void SortDat(){ } main(){ memset(sell, 0, sizeof(sell));ReadDat(); SortDat(); WriteDat(); 主函数是稍微需要能看懂的函数,最起码能看懂调用了什么子函数。在三级上机考试中,只有3%的题目要求在主函数中编写部分程序。在以后的例题中会有涉及(题型三,例1)。 } void ReadDat() { 这个函数的功能是读取文件中的数据,不必看懂详细的过程,只要了解它的功能就可以了。在三级上机考试中,只有3%的题要求编写读函数的一部分,只要会用函数fscanf()就足够了。在以后的例题中会有涉及(题型三,例8)。 其实要看懂它也很容易,只要了解第一章中提到的有关文件操作的函数就可以了,但考试中确实没有必要。 } void WriteDat(){ 这个函数的功能是将处理的结果写入目的文件,也不必看懂详细的过程。在三级上机考试中,还没有要求编写写函数的。只有一题(题型五,例4)需要看一下写函数。 } 在介绍完题型后,有专门介绍读写函数和主函数的内容,有兴趣的可以看一看。 【答案】 void SortDat() { int i,j; PRO t;for(i=0;i for(j=i+1;j if(strcmp(sell[i].mc,sell[j].mc)>0||strcmp(sell[i].mc,sell[j].mc)==0&&sell[i].je>sell[j].je) t=sell[i],sell[i]=sell[j],sell[j]=t;} 思路简析: 题目实际上是要求按一定的条件对数组sell[MAX](或写成sell[100])进行排列,用的就是第一章中的排序操作,只是把相应的进行交换的条件改了。 关键是if()中的内容。题目要求按产品名称从小到大进行排列,若产品名称相同,则按金额从小到大进行排列,那么sell[i]与sell[j]交换的条件实际上是: sell[i]的名称大于sell[j]的名称,或者sell[i]的名称等于sell[j]的名称但是se[i]的金额大于sell[j]的金额。 这里注意sell[MAX]是一个结构体数组,要注意它的引用方法。还有就是给出的程序中已定义了PRO为题目中结构体类型的符号,因此答案中用作交换的变量t直接用PRO定义就可以了。(其实这样对t定义也可以:struct t;) 表示为C语言的语句就是: sell[i].mc,sell[j].mc)>0||strcmp(sell[i].mc,sell[j].mc)==0&&sell[i].je>sell[j].je 答题时,只要看清题目要求,将例1答案中if()中的内容作相应的改动就可以了。 【练习1】 把例1中的功能要求改为:按产品代码从大到小进行排列,若产品代码相同,则按金额从大到小进行排列 【试题程序】除文件名外与例1一样,略。 【答案】 void SortDat() {int i,j; PRO t; for(i=0;i for(j=i+1;j if(strcmp(sell[i].dm,sell[j].dm)<0||strcmp(sell[i].dm,sell[j].dm)==0&&sell[i].je t=sell[i],sell[i]=sell[j],sell[j]=t;} 例 2、在文件IN38.DAT中有200组数据,每组有3个数,每个数均为三位数。函数readDat()读取这200组数存放到结构数组aa中。请编制函数jsSort(),其功能是:要求在200组数据中找出条件为每组数据中的第一个数大于第二个数加第三个数之和的数,其中满足条件的个数作为函数jsSort()的返回值,同时把满足条件的数据存入结构数组bb中,再对bb中的数按照每组数据的第一个数加第三个数之和的大小进行升序排列(第一个数加第三个数的和均不相等),排序后的结果仍重新存入结构数组bb中。最后,调用函数writeDat()把结果bb输出到文件OUT38.DAT中。 注意:部分源程序已给出。请勿改动主函数main()、读函数readDat()和写函数writeDat()的内容。 【试题程序】 #include #include #include #include typedef struct { int x1,x2,x3; }Data; Data aa[200],bb[200]; int jsSort(){ } void main(){ int count; readDat(); count=jsSort(); writeDat(count);} readDat(){略} writeDat(int count){略} 【答案】 int jsSort() {Data t; int i,j; int cnt=0; //cnt 用来表示满足条件的结构体的个数 for(i=0;i<200;i++) if(aa[i].x1>(aa[i].x2+aa[i].x3)) bb[cnt++]=aa[i]; //将满足条件的结构体存入结构体数组bb中 for(i=0;i //按要求对结构体数组bb进行排序 for(j=i+1;j if((bb[i].x1+bb[i].x3)>(bb[j].x1+bb[j].x3)) t=bb[i],bb[i]=bb[j],bb[j]=t; return(cnt);} C语言 三级上机考试分题型讲解之题型二,对四位数先筛选再处理的问题(35%) 2010-04-23 14:42这类题目比较简单,数量也多,题目的变化主要在于筛选四位数的具体条件,多数是基于四位数各位数字(千位、百位、十位、个位)的性质进行筛选(27%),有的是基于四位数与前后相邻数字的大小关系进行筛选(4%),还有的是基于四位数本身是否为素数进行筛选(2%)(这类题目都在试题中给出了判断素数的函数),还有涉及移位操作的(2%)。 对这类简单题可以多看几个,基础好的同学可以只看两三个,主要是学会用C语言把题目中的具体条件表示出来。 例 1、已知数据文件IN10.DAT中存有300个四位数,并已调用读函数readDat()把这些数存入数组a中,请编制一个函数jsValue(),其功能是:求出千位上的数减百位上的数减十位上的数减个位上的数大于零的数的个数cnt,并求出所有满足此条件的数的平均值pjz1,以及所有不满足此条件的数的平均值pjz2,并把所有满足此条件的四位数依次存入数组b中,然后对数组b中的四位数按从小到大的顺序进行排序,最后调用写函数writeDat()把数组b中的数输出到OUT10.DAT文件。 例如:9123,9-1-2-3>0,则该数满足条件存入数组b,且个数cnt=cnt+1。 9812,9-8-1-2<0,则该数不满足条件,忽略。 注意:部分源程序已给出。程序中已定义数组:a[300],b[300];已定义变量:cnt,pjz1,pjz2。请勿改动主函数main()、读函数readDat()和写函数writeDat()的内容。 【试题程序】 #include int a[300],b[300],cnt=0;double pjz1=0.0,pjz2=0.0; jsValue(){ } main(){ int i; readDat(); jsValue(); writeDat(); for(i=0;i readDat(){略} writeDat(){略} 【答案】 jsValue(){ int i,j,t; int qw,bw,sw,gw; //分别表示千位、百位、十位、个位 for(i=0;i<300;i++) {qw=a[i]/1000; bw=a[i]%1000/100; sw=a[i]%100/10; gw=a[i]%10; //求出a[i]的各位数字 if(qw-bw-sw-gw>0) b[cnt++]=a[i],pjz1+=a[i];//将满足条件的数存入数组b,并求和 else pjz2+=a[i];//对不满足条件的数求和 } pjz1/=cnt; //求满足条件的数的平均值 pjz2/=300-cnt; //求不满足条件的数的平均值 for(i=0;i //对数组b进行排序 for(j=0;j if(b[i]>b[j]) t=b[i],b[i]=b[j],b[j]=t;} 思路简析: 这类题目主要涉及整数各位数字的求法,数组的排序,以及平均值的求法。程序对a[300]中的数依次进行检查,满足条件则统计个数,并存入数组b中,同时对满足条件的数进行求和(pjz1)。不满足条件的数,也进行求和(pjz2)。最后用求得的和除以个数,得平均值(pjz1/=cnt , pjz2/=300-cnt)。最后再对数组b排序。 细节问题: 1、pjz1和pjz2在试题程序的开头已经定义好并进行了初始化,不必再定义新的变量。在答案的前半部分,pjz1用来求满足条件的数的和,pjz2用来求不满足条件的数的和,最后分别除以相应的数的个数得到平均值,这样可以节省变量。 2、满足条件的数的个数为cnt,则不满足条件的数的个数为300-cnt,不必再定义新的变量。 3、符号/=也属于赋值运算符,优先级除了逗号外是最低的,所以pjz2/=300-cnt;一句中,300-cnt 不必加括号,如果考试中不敢确定的话,也可以加上括号。 4、b[cnt++]=a[i],pjz1+=a[i]; 这是一个语句,因为只有一个分号,中间是用逗号分隔开。 如果不用逗号隔开,将这个语句写为两个语句的话,必须要将两个语句用{}括起来,像这样:{b[cnt++]=a[i]; pjz1+=a[i];} 因为它们都要在if()中的条件为真时要执行。 b[cnt++]=a[i]是一种非常简洁的写法,它相当于 b[cnt]=a[i],cnt++; pjz1+=a[i]也同样是简洁的写法,它相当于pjz1=pjz1+a[i]; 其实例1比题库中的题目要求的稍多了一点,题库中的题目,没有同时要求将满足条件的数按一定顺序存入另一数组中,又要求对满足条件的数求平均值的,如练习1和练习2。例1相当于练习1和练习2两个题目的叠加,只是复杂了点,难度并没有提高。 【练习1】 把例1中的功能要求改为:求出千位上的数加百位上的数等于十位上的数加个位上的数的个数cnt,再求出所有满足此条件的4位数的平均值pjz1,以及所有不满足此条件的4位数的平均值pjz2。 【试题程序】除文件名外与例1一样,略。 【答案】 void jsValue(){int i; for(i=0;i<300;i++) {qw=a[i]/1000; bw=a[i]%1000/100; sw=a[i]%100/10; gw=a[i]%10; if(qw+bw==sw+gw) cnt++,pjz1+=a[i]; else pjz2+=a[i];} pjz1/=cnt; pjz2/=300-cnt;} 【练习2】 把例1中的功能要求改为:求出千位上的数减百位上的数减十位上的数减个位上的数大于零的数的个数cnt,再把所有满足此条件的四位数依次存入数组b中,然后对数组b中的四位数按从小到大的顺序进行排序。 【试题程序】除文件名外与例1一样,略。 【答案】 jsValue() {int i,j,t; int qw,bw,sw,gw; //分别表示千位、百位、十位、个位 for(i=0;i<300;i++) {qw=a[i]/1000; bw=a[i]%1000/100; sw=a[i]%100/10; gw=a[i]%10; //求出a[i]的各位数字 if(qw-bw-sw-gw>0) //将满足条件的数存入数组b中 b[cnt++]=a[i];} for(i=0;i //对数组b进行排序 for(j=0;j if(b[i]>b[j]) t=b[i],b[i]=b[j],b[j]=t;} 例 2、把例1中的功能要求改为:求出所有这些四位数中素数的个数cnt,再把所有满足此条件的四位数依次存入数组b中,然后对数组b中的四位数按从小到大的顺序进行排序。 【试题程序】除文件名外与例1一样,只是在开头多了一个子函数: int isP(int m){ int i; for(i=2;i return 1;} 这个子函数应该很面熟,就是前面提到过的判断素数的函数。 【答案】 void jsValue(){ int i,j,t; for(i=0;i<300;i++) if(isP(a[i]))b[cnt++]=a[i];//按条件筛选 ? for(i=0;i //排序 for(j=i+1;j if(b[i]>b[j]) t=b[I],b[I]=b[j], b[j]=t;} 注意: 试题程序已经给出了判断素数的函数isP()(通常给出在试题程序的开头部分),因此不用再自己写判断素数的程序内容了。三级考试中牵扯到判断素数的问题,有一部分是要求考生自己写判断素数的函数,而另外一部分只是要求考生调用试题中给出函数。 通常试题中都是在程序的开头给出了这个判断素数的函数,且函数名一般为isP或isPrime。一般都是:如果是素数则返回值为1,不是素数则返回值为0。 例 3、把四位数的个数改为200,把例1中的功能要求改为:把千位数字和十位数字重新组成一个新的两位数ab(新两位数的十位数字是原四位数的千位数字,新两位数的个位数字是原四位数的十位数字),以及把个位数字和百位数字组成另一个新的两位数cd(新两位数的十位数字是原四位数的个位数字,新两位数的个位数字是原四位数的百位数字),如果新组成的两个两位数ab-cd>=10且ab-cd<=20且两个数均是偶数,同时两个新数的十位数字均不为零,则将满足此条件的四位数按从大到小的顺序存入数组b中,并要计算满足上述条件的四位数的个数cnt。 注意:部分源程序已给出。程序中已定义数组:a[200]、b[200];已定义变量:cnt。请勿改动数据文件IN.DAT中的任何数据、主函数main()、读函数readDat()和写函数writeDat()的内容。 【试题程序】除文件名外与例1一样,略 【答案】 void jsVal() {int i,j,t,ab,cd; for(i=0;i<200;i++) { qw=a[i]/1000; bw=a[i]%1000/100; sw=a[i]%100/10; gw=a[i]%10; ab=qw*10+sw; //求两个新数 cd=gw*10+bw; if(ab-cd>=10&&ab-cd<=20&&ab%2==0&&cd%2==0&&ab/10&&cd/10)//按条件筛选 b[cnt++]=a[i];} for(i=0;i for(j=i+1;j if(b[i] t=b[i],b[i]=b[j],b[j]=t;} 细节问题: “按条件筛选”一行的if语句末尾的“ab/10”和“cd/10”是一种精简写法,它相当于“ab/10!=0”和“cd/10!=0” 【练习3】 把四位数的个数改为200,把例1中的功能要求改为:把千位数字和十位数字重新组成一个新的两位数ab(新两位数的十位数字是原四位数的千位数字,新两位数的个位数字是原四位数的十位数字),以及把个位数字和百位数字组成另一个新的两位数cd(新两位数的十位数字是原四位数的个位数字,新两位数的个位数字是原四位数的百位数字),如果新组成的两个两位数均是素数,同时两个新数均不为零,则将满足此条件的四位数按从大到小的顺序存入数组b中,并要计算满足上述条件的四位数的个数cnt。 【试题程序】除文件名外与例1一样,只是在开头多了一个子函数。 int isprime(int m){ int i; for(i=2;i<=m/2;i++) if(m%i==0)return 0; return 1;} 不难看出,这个函数也是用来判断素数的。 (注意,这个函数里面写的是i<=m/2,(必须是<=,不能是<),这样写也是可以的,这是为了提高效率。因为,如果m可以分解为两个因数相乘的话,其中必有一个因数小于等于m/2,也就是说,从2到m/2之间肯定有m的因数。不过我们考试中不必考虑什么程序执行效率的问题,直接写i 【答案】 void jsVal() {int i,j,t,ab,cd; for(i=0;i<200;i++) { qw=a[i]/1000; bw=a[i]%1000/100; sw=a[i]%100/10; gw=a[i]%10; ab=qw*10+sw;//求两个新数 cd=gw*10+bw; if(isprime(ab)&&isprime(cd)&&ab&&cd)//按条件筛选 b[cnt++]=a[i];} for(i=0;i for(j=i+1;j if(b[i] t=b[i],b[i]=b[j],b[j]=t;} 细节问题: “按条件筛选”一行的if语句末尾的“ab”和“cd”是一种精简写法,它相当于“ab!=0”和“cd!=0” 例 4、下面程序的功能是:选出5 000以下符合条件的自然数。条件是:千位数字与百位数字之和等于十位数字与个位数字之和,且千位数字与百位数字之和等于个位数字与千位数字之差的10倍。计算并输出这些4位自然数的个数cnt及这些数的和sum。请编写函数countValue()实现程序的要求,最后调用函数writeDAT()把结果cnt和sum输出到文件OUT53.DAT中。 注意:部分源程序已给出。请勿改动主函数main()和写函数writeDAT()的内容。 【试题程序】 #include int cnt,sum; void countValue(){ } void main(){ cnt=sum=0; countValue(); printf(“满足条件的自然数的个数=%dn”,cnt); printf(“满足条件的自然数的值的和=%dn”,sum); writeDAT();} writeDAT(){略} 【答案】 void countValue() { int qw,bw,sw,gw,i; for(i=1000;i<5000;i++) { qw=i/1000; bw=i%1000/100; sw=i%100/10; gw=i%10; if(qw+bw==sw+gw&&qw+bw==10*(gw-qw)) cnt++,printf(“%dn”,i),sum+=i;} } 例 5、已知在文件IN55.DAT中存有若干个(个数<200)四位数字的正整数,函数ReadDat()读取这若干个正整数并存入数组xx中。请编制函数Calvalue(),其功能要求:(1)求出文件中共有多少个正整数totNum;(2)求出这些数中的各位数字之和是偶数的数的个数totCnt,以及满足此条件的这些数的算术平均值totPjz,最后调用函数WriteDat()把所求的结果输出到文件OUT55.DAT 注意:部分源程序已给出。请勿改动主函数main()、读数据函数ReadDat()和输出数据函数WriteDat()的内容。 【试题程序】 头文件略 #define MAXNUM 200 int xx[MAXNUM]; int totNum = 0; /*文件IN55.DAT中正整数个数*/ int totCnt = 0; /*符合条件的正整数的个数*/ double totPjz = 0.0;/*平均值*/ int ReadDat(void); //函数定义 void WriteDat(void); //函数定义 void Calvalue(void){ } void main(){ int i; system(“cls”);//不用管这句什么意思 for(i = 0;i < MAXNUM;i++)xx[i] = 0;//初始化数组xx各元素为0 if(ReadDat()) { printf(“数据文件IN55.DAT不能打开! 07n”);return;}//这句不必看懂 Calvalue(); printf(“文件IN55.DAT中共有正整数=%d个n”, totNum); printf(“符合条件的正整数的个数=%d个n”, totCnt); printf(“平均值=%.2lfn”, totPjz); WriteDat();} int ReadDat(void){略} void WriteDat(void){略} 【答案】 void Calvalue(void) { int i,qw,bw,sw,gw; while(xx[totNum])totNum++; //只要元素值不为0,个数就加1 for(i=0;i { qw=xx[i]/1000; bw=xx[i]%1000/100; sw=xx[i]%100/10; gw=xx[i]%10; if((qw+bw+sw+gw)%2==0) totCnt++,totPjz+=xx[i] //统计满足条件的数的个数,并求和 } totPjz/=totCnt; //求平均值 } 细节问题: 注意题目中已经定义的变量及其类型。题目中已经定义了相关变量并进行了初始化。 例 6、把例5中的功能要求改为:(1)求出这个文件中共有多少个正整数totNum。(2)求这些数右移一位后,产生的新数是奇数的数的个数totCnt,以及满足此条件的这些数(右移前的值)的算术平均值totPjz。 【试题程序】除文件名外,和例5一样,略。 【答案】 void CalValue(void) { int i; while(xx[totNum])totNum++; for(i=0;i if((xx[i]>>1)%2==1) //里面的括号不能漏掉,因为移位运算优先级低于%运算 totCnt++,totPjz+=xx[i]; totPjz/=totCnt;} 全方位练习: 已知:a[i]为四位数(有的题目中这样说,“1000到9999之间的数”,其实就是四位数) qw=a[i]/1000; bw=a[i]%1000/100; sw=a[i]%100/10; gw=a[i]%10; ab,cd代表这类题目中常出现的新两位数。 isP()是判断素数的函数 将下列表述用C语言表示出来: 1、千位数字减百位数字等于个位数字减十位数字 1、qw-bw==gw-sw 2、四位数的各位数字均为0,2,4,6,8中的数 2、qw%2==0&&bw%2==0&&sw%2==0&&gw%2==0;(也就是各位均为偶数) 或简写为 qw%2+bw%2+sw%2+gw%2==0; 3、四位数的各位数字均为1,3,5,7,9中的数 3、qw%2!=0&&bw%2!=0&&sw%2!=0&&gw%2!=0;(也就是各位都是奇数) 或简写为qw%2&&bw%2&&sw%2&&gw%2; 或简写为qw%2+bw%2+sw%2+gw%2==4; 4、四位数连续大于它前面的5个数 4、a[i]>a[i-1]&&a[i]>a[i-2]&&a[i]>a[i-3]&&a[i]>a[i-4]&&a[i]>a[i-5]; 在用for语句循环时,注意i的初值应为5; 5、四位数连续小于它后面的5个数 5、a[i] 在用for语句循环时,注意i<总个数-5; 6、四位数为素数,且能被7整除,且百位数字不为0 6、isP(a[i])!=0&&a[i]%7==0&&bw!=0 或简写为 isP(a[i])&&a[i]%7==0&&bw 7、ab的十位数字是原四位数的个位数字,个位数字是原四位数的百位数字;cd的十位数字是原四位数的十位数字,个位数字是原四位数的千位数字; 7、ab=gw*10+bw;cd=sw*10+qw; 8、ab-cd>=5且ab-cd<=20; 8、ab-cd>=5&&ab-cd<=20(不能写成5<=ab-cd<=20) 9、ab和cd都是偶数,且两个数的十位数字都不为0。 9、ab%2==0&&cd%2==0&&ab/10!=0&&cd/10!=0 或简写为ab%2+cd%2==0&&ab/10&&cd/10 10、ab和cd都是奇数,且至少有一个数能被17整除 10、ab%2!=0&&cd%2!=0&&(ab%17==0||cd%17==0); 或简写为ab%2&&cd%2&&(ab%17)*(cd%17)==0; 11、ab和cd一个是奇数,一个是偶数,11、(ab%2&&cd%2==0)||(ab%2==0&&cd%2);(括号可省略) 或简写为ab%2+cd%2==1; 12、ab和cd两数中只有一个能被17整除 12、(ab%17&&cd%17==0)||(ab%17==0&&cd%17);(括号可省略) 13、ab和cd最多有一个能被5整除,且两数的个位数字都小于十位数字 13、(ab%5&&cd%5)||(ab%5==0&&cd%5)||(ab%5&&cd%5==0);(括号可省略) 或简写为ab%5+cd%5!=0; 14、ab和cd中只有一个素数,且两数都不为0 14、isP(ab)==1&&isP(cd)==0||iaP(ab)==0&&isP(cd)==1; 或简写为isP(ab)&&isP(cd)==0||iaP(ab)==0&&isP(cd); 或简写为isP(ab)+isP(cd)==1; C语言 三级上机考试分题型讲解之题型三,整数处理问题(17%) 2010-04-23 14:50这类问题彼此之间的相似性不大,但好在难度都很小。因为题目之间相似性不大,所以这一题型列举的例题会多一点,但是用到的东西都是题型二中涉及到的。 例 1、请编制程序,要求:将文件IN40.DAT中的200个整数读入数组xx中,求出数组xx中奇数的个数cnt1和偶数的个数cnt2,并计算数组xx下标为偶数的元素值的算术平均值pj(保留2位小数),结果cnt1、cnt2、pj输出到文件OUT40.DAT中。 注意:部分程序、读函数read_dat(int xx[200])及输出格式已给出。【试题程序】 头文件略 #define N 200 void read_dat(int xx[N]){略} void main(){ int cnt1,cnt2,xx[N];float pj;FILE *fw;int i,k=0;long j;system(“cls”);fw=fopen(“OUT40.DAT”,“w”); //打开数据文件 read_dat(xx); //读取数据 /*┅┅┅┅┅┅┅┅found┅┅┅┅┅┅┅┅┅┅ */(从下一行开始接着写) printf(“nncnt1=%d,cnt2=%d,pj=%6.2fn”,cnt1,cnt2,pj);//输出结果 fprintf(fw,“%dn%dn%6.2fn”,cnt1,cnt2,pj); //将结果写入目的文件 fclose(fw);} 【答案】 /*┅┅┅┅┅┅┅┅found┅┅┅┅┅┅┅┅┅┅ */ cnt1=cnt2=0; //初始化 pj=0.0; //初始化 for(i=0;i<200;i++) //从第一个元素开始 {if(xx[i]%2)cnt1++; //统计奇数的个数 else cnt2++; //统计偶数的个数 if(i%2==0)pj+=xx[i]; //求下标为偶数的元素的和 } pj/=100; //求下标为偶数的元素的平均值 „„„„ 思路简析: 注意题目中已经定义的变量及其类型,注意对要使用的变量进行初始化。题目中定义的变量j和k没有用到,这个没关系。其实题目中的变量除了最后要写入目的文件的几个外,都可以不用,也都可以用自己定义的变量。细节问题: 题目要求pj保留两位小数,但是在后面的printf()和fprintf()中,已经写好了最后输出的和写入文件的数据格式,%6.2f就是总共6位、两位小数的浮点型格式。 例 2、把例1中的要求改为:求出数组xx中最大数max及最大数的个数cnt,并计算数组xx中值能被3整除或能被7整除的数的算术平均值pj(保留两位小数),结果max、cnt、pj输出到文件OUT42.DAT中。【试题程序】 头文件略 #define N 200 void read_dat(int xx[N]){略} void main(){ int i,k,cnt,xx[N],max;float pj;FILE *fw;long j=0;system(“cls”);fw=fopen(“OUT42.DAT”,“w”);read_dat(xx);/*┅┅┅┅┅┅┅┅found┅┅┅┅┅┅┅┅┅┅ */ printf(“nnmax=%d,cnt=%d,pj=%6.2fn”,max,cnt,pj);fprintf(fw,“%dn%dn%6.2fn”,max,cnt,pj);fclose(fw);} 【答案】 /*┅┅┅┅┅┅┅┅found┅┅┅┅┅┅┅┅┅┅ */ k=0,cnt=0,pj=0.0; //对各变量初始化 max=xx[0]; //将数组的第一个元素赋给max,以便和其它元素比较 for(i=0;i<200;i++)if(max //统计数组中等于max的元素的个数 if(xx[i]%3==0||xx[i]%7==0)//判断是否能被3或7整除 k++,pj+=xx[i];} //统计能被3或7整除的数的个数,并求这些数的和 pj/=k; //求这些数的平均值 „„„„ 思路简析: 这个题目也很简单,不过还是要注意题目中已经定义的变量及其类型,并要记得初始化。最后关于pj的格式题目中也是已经给出了。【练习1】 编写一个函数findStr(),该函数统计一个长度为2的子字符串在另一个字符串中出现的次数。例如:假定输入的字符串为“asd asasdfg asd as zx67 asd mklo”,子字符串为“as”,函数返回值为6。 函数readwriteDat()的功能是实现从文件IN90.DAT中读取两个字符串,并调用函数findStr(),最后把结果输出到文件OUT90.DAT中。 注意:部分源程序已给出。请勿改动主函数main()和函数ReadWrite()的内容。【试题程序】 头文件略 #define N 81 int findStr(char *str,char *substr){ } main(){ char str[81],substr[3];int n;system(“cls”);printf(“Enter a string : ”);gets(str);//从键盘输入一个字符串 printf(“Enter a substring: ”);gets(substr);//再输入要统计个数的子字符串 puts(str);puts(substr); //输出刚才输入的两个字符串 n=findStr(str,substr); //求长字符串中子字符串的个数 printf(“n=%dn”,n); //输出求得的个数 ReadWrite();} ReadWrite(){略} 【答案】 int findStr(char *str,char *substr){int i,s,n=0;s=strlen(str); //测量字符串长度 for(i=0;i 这个题目是关于字符串的,之所以把它放到这里,一是因为这个题目和例2有相似之处,都涉及统计数组中特定单元的个数,二是因为这个题目简单却不好分类,因此把它放到了这里。如果题目中改为“长度为3的子字符串”,则if()中只需加一点:&&str[i+2]=substr[2]。 例 3、下列程序的功能是:将大于整数m且紧靠m的k个素数存入数组xx。请编写函数num(int m,int k,int xx[])实现函数的要求,最后调用函数readwriteDAT()把结果输出到文件OUT47.DAT中。例如:若输入17,5,则应输出:19,23,29,31,37。 注意:部分源程序已给出。请勿改动主函数main()和函数readwriteDAT()的内容。【试题程序】 头文件略 void readwriteDAT(); //函数定义 void num(int m,int k,int xx[]){ } main(){ int m, n, xx[1000];system(“cls”);printf(“nPlease enter two integers:”);//请输入两个整数 scanf(“%d,%d”, &m, &n);//从键盘输入两个整数,逗号隔开 num(m, n, xx); //求紧靠m的n个素数 for(m = 0;m < n;m++)printf(“%d ”, xx[m]);//将结果输出 printf(“n”);readwriteDAT();} void readwriteDAT(){略} 【答案】 void num(int m,int k,int xx[]){ int i,j,t;for(i=m+1,t=0;t //这个for()语句用来判断i是否为素数 if(i%j==0)break;if(j==i)xx[t++]=i; //将素数存入数组xx } } 思路简析: 关于素数的判断,前面已经多次提到。这个题目主要是循环的控制。虽然for()中变量i和变量t都有,并且每次i都自加,但是循环次数是由变量t控制的,t 下列程序的功能是:找出所有100以内(含100)满足I、I+ 4、I+10都是素数的整数I(I+10也是在100以内)的个数cnt,以及这些整数之和sum。请编制函数countValue()实现程序要求,最后调用函数writeDAT()把结果cnt和sum输出到文件OUT48.DAT中(数值1不是素数)。 注意:部分源程序已给出。请勿改动主函数main()和输出数据函数writeDAT()的内容。【试题程序】 #include //1不是素数 return 0; //返回0 for(i=2;tag && i<=number/2;i++)// tag==0循环立即终止 if(number%i==0)tag=0; //发现number的因数,则tag=0 return tag; //返回最终tag的值 } void countValue(){ } void main(){ cnt=sum=0;countValue();printf(“满足条件的整数的个数=%dn”,cnt);printf(“满足条件的整数的和值=%dn”,sum);writeDAT();} writeDAT(){略} 【答案】 void countValue(){ int i;for(i=2;i<=90;i++)if(isPrime(i)&&isPrime(i+4)&&isPrime(i+10))cnt++,sum+=i;} 思路简析: 需要注意的是,试题程序中已经给出了判断素数的函数int isPrime(int number),当 number为素数时,函数返回值为1。所以要编写的函数直接调用这个函数就可以了。【练习3】 下列程序的功能是:计算500~800之间素数的个数cnt,并按所求素数的值从小到大的顺序,再计算其间隔加、减之和,即第1个素数—第2个素数+第3个素数—第4个素数+第5个素数„„的值sum。请编写函数countValue()实现程序的要求,最后调用函数writeDat()把结果cnt和sum输出到文件OUT49.DAT中。 注意:部分源程序已给出。请勿改动主函数main()和写函数writeDAT()的内容。【试题程序】 #include 【答案】 void countValue(){int i,j,t=1; //t代表素数的符号(1或-1),第一个素数符号为正(1)for(i=500;i<800;i++) //检查500到800之间的每一个数 { for(j=2;j if(i%j==0)break;if(j==i) //如果是素数 {cnt++; //个数加1 sum+=t*i; //将素数乘上它的符号(1或-1)再求和 t*=-1;} //下一个素数的符号相反(乘-1)} 思路简析: 还是判断素数,不同的是求和的时候考虑符号。用素数乘变量t再求和就可以了。因为第一个素数符号为正,所以变量t刚开始是1,每发现一个素数都要先乘t再求和,然后变量t乘-1,下一个素数符号相反。题目的说“从小到大”是多余的,本来就是从小到大。【练习4】 下面程序的功能是:选取出100以上1 000以下(说白了就是所有的三位数)所有个位数字与十位数字之和被10除所得余数恰是百位数字的素数(如293)。计算并输出上述这些素数的个数CNT以及这些素数值的和sum。请编写函数countvalue()实现程序要求,最后调用函数writeDAT()把结果cnt和sum输出到文件OUT50.DAT中。 注意:部分源程序已给出。请勿改动主函数main()和输出函数writeDAT()的内容。【试题程序】 #include 【答案】 void countvalue(){ int i,j;for(i=100;i<1000;i++){for(j=2;j if(i%j==0)break; if(j==i&&((i%10+i%100/10)%10==i/100))//是素数且各位数字满足条件 cnt++,sum+=i; //统计个数并求和 } } 思路简析: 还是判断素数,不过多加了一点对三位数各位数字的判断,在题型二中已经多次提到求各位数字的方法。对于三位数i,i%10是个位,i%100/10是十位,i/100是百位。 例 4、下面程序的功能是:在三位整数(100至999)中寻找符合下面条件的整数,并依次从小到大存入数组中;它既是完全平方数,又有两位数字相同,例如144、676等。请编制函数实现此功能,满足该条件的整数的个数通过所编制的函数返回,最后调用函数writeDat()把结果输出到文件OUT51.DAT中。 注意:部分源程序已给出。请勿改动主函数main()和写函数writeDat()的内容。【试题程序】 #include 【答案】 int jsvalue(int bb[]){ int i,j,t,cnt=0;int gw,sw,bw; //代表个位、十位、百位 for(i=100;i<1000;i++){gw=i%10;sw=i%100/10;bw=i/100;for(j=10;j<=i/10;j++)//从10到i/10逐个判断是否为i的开方(也可以写j //如果发现某个j的平方等于i,则循环终止 if(j<=i/10&&(gw==sw||sw==bw||bw==gw))//如果i是完全平方数且各位数字满足条件 bb[cnt++]=i; //将i存入数组bb中并统计个数 } for(i=0;i //对数组bb中的元素从小到大排列 for(j=i+1;j //将满足条件的数的个数作为返回值返回 } 思路简析: 与判断素数类似,判断素数的时候是判断i%j是否为0,这里判断完全平方数则是判断i是否等于j*j。其它没有什么不同。细节问题: (gw==sw||sw==bw||bw==gw)的外括号不能漏掉,因为&&的优先级比||高。 最后的return语句不能漏掉,并且只能放在最后。前面讲过,在子函数中,return语句有类似于break语句的作用,它的执行将使整个子函数的调用结束,如果它后面还有语句的话,则那些语句将不被执行。 例 5、下面程序的功能是:寻找并输出11至999之间的数m,它满足m、m2和m3均为回文数。所谓回文数是指其各位数字左右对称的整数,例如121,676,94249等。满足上述条件的数如m= 11、m2=121、m3=1331皆为回文数。请编制函数int jsvalue(long n)实现此功能,如果是回文数,则函数返回1,反之则返回0。最后把结果输出到文件OUT52.DAT中。 注意:部分源程序已给出。请勿改动主函数main()的内容。【试题程序】 #include if(jsvalue(m)&&jsvalue(m*m)&&jsvalue(m*m*m)) { printf(“m=%4ld,m*m=%6ld,m*m*m=%8ldn”,m,m*m,m*m*m); fprintf(out,“m=%4ld,m*m=%6ld,m*m*m=%8ldn”,m,m*m,m*m*m); } } fclose(out);} 【答案】 int jsvalue(long n){ int cnt=0,j=0,a[10];// cnt用来统计n的位数 while(n) //只要n!=0 {a[cnt++]=n%10; //将个位数字存入数组a并统计位数 n/=10;} //把n的最后一位去掉 for(j=0;j if(a[j]!=a[cnt-1-j]) //如果发现某个元素与对称位置的元素不相等 return 0; //返回0(不是回文数) return 1; //如果上面一直没有发现不对称的情况,则返回1(是回文数)} 思路简析: 首先要注意,题目要求我们编写的子函数的功能是判断某个数n是否为回文数。虽然题目中要求找出11到999中m、m的平方、m的立方都是回文数的数,但这是对整个程序的要求。并且试题程序中的主函数中的for()语句就是在对11到999之间的数逐个检查,通过调用题目要求我们写的子函数,判断每个数本身及它的平方、它的立方是不是回文数,这 程序的思路是,首先测量n的位数,并将各位数依次存入定义的数组a[10]中。然后再判断对称位置元素是否都相等。过程详解: 分离n的各位数字是利用整型数据的特点,即整型除整型得到的商还是整型,没有小数部分。因此,整型数据n(long为长整型,范围更大,不过也是整型)除10后,它的个位数字便被去掉了,它的位数也就少了一位。这一点在第一章中提到过。 这样下去,n的位数不断减少,直到n变为0为止。每减少一位,统计位数的变量cnt就加1,并且把n的新个位数字(也就是上一次n的十位数字)存入数组a中。到最后就测量出了n的位数,并且把n的各位数字存入了数组a中(是反向存入的,个位数字在前,高位数字在后,不过这里没有关系,因为是判断对称的位置上数字是否相等)。 然后就可以对数组中前一半元素进行判断了,看它是否与对称位置元素相等。只要发现有不相等的,就说明n不是回文数,则返回0,子函数的调用立即终止。如果没有发现对称位置元素不相等的情况,则语句return 0不会被执行,也说明n是回文数,则后面的return 1会被执行,函数返回1。细节问题: 因为这里的m小于1000,所以n的最大值小于1000的立方,即10的9次方,所以n最多不过9位,定义含10个元素的数组a已经足够了。 这个题目学校原订题库书中是将数字转换为字符型,再用字符串的函数进行处理,没有必要,也比较繁琐。至于它是怎么写的,这里也不再写了。 例 6、已知在文件IN54.DAT中存有N个(个数<200)实数,函数ReadDat()读取这N个实数并存入数组xx中。请编制函数Calvalue(),其功能要求:(1)求出这N个实数的平均值aver;(2)分别求出这N个实数的整数部分之和sumint以及小数部分之和sumdec,最后调用函数WriteDat()把所求的结果输出到文件OUT54.DAT中。 注意:部分源程序已给出。请勿改动主函数main()、读数据函数ReadDat()和输出数据函数WriteDat()的内容。【试题程序】 头文件略 #define MAXNUM 200 float xx[MAXNUM];int N= 0; /*文件IN54.DAT中实数的个数*/ double aver=0.0; /*平均值*/ double sumint=0.0;/*整数部分之和*/ double sumdec=0.0;/*小数部分之和*/ int ReadDat(void);// 函数定义 void WriteDat(void);//函数定义 void Calvalue(void){ } void main(){ int i;system(“cls”);for(i = 0;i< MAXNUM;i++)xx[i] = 0;if(ReadDat()){ printf(“数据文件IN54.DAT不能打开! 07n”);return;} Calvalue(); printf(“文件IN54.DAT中共有实数=%d个n”, N); printf(“平均值=%.2lfn”, aver); printf(“整数部分之和=%.2lfn”, sumint); printf(“小数部分之和=%.2lfn”, sumdec); WriteDat();} int ReadDat(void){略} WriteDat(void){略} 【答案】 void Calvalue(void){ int i;while(xx[N])N++; //统计实数的个数 for(i=0;i {aver+=xx[i]; //求所有实数的和 sumint+=(int)xx[i];} //求整数部分的和 sumdec=aver-sumint; //求小数部分的和 aver/=N; //求所有实数的平均值 } 思路简析: 求整数部分的和是用了强制类型转换,将浮点型数据转换成整型数据,这样小数部分自动丢失,只保留整数部分。而求小数部分的和是用所有实数的和减去整数部分的和。 强制类型转换是将目的类型用括号括起来,而不是数据。比如把整型数据n转换成字符型数据c,应该这样写:c=(char)n,而不是c=char(n)。这点要弄清楚。 例 7、请编写函数countvalue(),它的功能是:求n以内(不包括n)同时能被3和7整除的所有自然数之和的平方根s,并作为函数值返回,最后结果s输出到文件OUT94.DAT中。例如若n为1 000时,函数值应为:s=153.909064。 注意:部分源程序已给出。请勿改动主函数main()和输入输出数据函数progReadWrite()的内容。【试题程序】 头文件略 double countvalue(int n){ } main(){ system(“cls”);printf(“自然数之和的平方根=%fn”,countvalue(1000));progReadWrite();} progReadWrite(){略} 【答案】 double countvalue(int n){ int i;double s=0.0;for(i=1;i //这个题主要是要了解这个库函数 return s;} 【练习5】 请编写函数void countValue(int *a,int *n),它的功能是:求出1到1 000之内能被7或11整除但不能同时被7和11整除的所有整数,并存放在数组a中,通过n返回这些数的个数。注意:部分源程序已给出。请勿改动主函数main()和写函数writeDAT()的内容。【试题程序】 头文件略 void countValue(int *a,int *n){ } main(){ int aa[1000],n,k;system(“cls”);countValue(aa,&n);for(k=0;k 【答案】 void countValue(int *a,int *n){int i;*n=0;for(i=1;i<1000;i++)if((i%7)*(i%11)==0&&(i%7+i%11))a[*n]=i,(*n)++;} 思路简析: 这个题目是所有题目中唯一一个无法避免使用指针的题目。因为函数名和函数形参题目中都已经写好了。int *a,int*n说明a和n都是指针,通俗地说,就是a和n都是地址,其中a在题目中是数组的首地址,也就是数组名,而n在题目中则是表示这些数的个数的变量的地址。 虽然答案中用到了指针,但是只是用到了指针的定义。对于指针其实很简单,n是指针,那么*n就是指针所指向的变量,就把*n作为一个整体看待就可以了,*n代表满足条件的数的个数。如果有的同学以指针太不了解的话,不防把*n换成cnt理解算了。细节问题: 最后一行的(*n)++括号不能漏掉,因为*n作为一个整体代表一个整型变量,可以使用自加运算,而表达式是不能自加的。如果不加括号,可以这样写:*n+=1。 子函数的形参可以是值传递,也可以是地址传递,这个题目使用的是地址传递,把主函数中的数组aa的首地址和变量n的地址传递给形参。注意,主函数中的n是整型变量,而题目要求写的子函数中的n则是一个指针(地址)变量,它们两个是不一样的。 例 8、请编制函数ReadDat(),实现从文件IN59.DAT中读取1000个十进制整数到数组xx中;请编制函数Compute()分别计算出xx中偶数的个数even、奇数的个数odd、奇数的平均值ave1、偶数的平均值ave2以及所有偶数的方差totfc的值,最后调用函数WriteDat()把结果输出到OUT59.DAT文件中。计算方差的公式如下: 设N为要计算方差的数的个数,x[i]为要计算方差的各个数,aver为这些数的平均值。 原始数据文件存放的格式是:每行存放10个数,并用逗号隔开(每个数均大于0且小于等于2 000)。注意:部分源程序已给出。请勿改动主函数main()和输出数据函数WriteDat()的内容。【试题程序】 头文件略 #define MAX 1000 int xx[MAX],odd=0,even=0; //注意,题目中是否已对变量初始化 double ave1=0.0,ave2=0.0,totfc=0.0;void WriteDat(void);int ReadDat(void){ FILE *fp;int I,j;if((fp=fopen(“IN59.DAT”,“r”))==NULL)return 1; fclose(fp);return 0;} void Compute(void){ } void main(){ int i;for(i=0;i xx[i]=0;if(ReadDat()){ printf(“数据文件IN59.DAT不能打开! 07n”);return;} Compute();printf(“OVEN=%dnAVE1=%fnAVE2=%1fnTOTFC=%lfn”,even,ave1,ave2,totfc);WriteDat();} void WriteDat(void){略} 【答案】 int ReadDat(void){ „„ for(i=0;i //从fp所指向的文件(IN59.DAT)读取1000个整数 fscanf(fp,“%d,”,&xx[i]);„„ } void Compute(void){ int i; for(i=0;i //统计奇数的个数并求和 odd++,ave1+=xx[i];else even++,ave2+=xx[i]; //统计偶数的个数并求和 } ave1/=odd;ave2/=even;for(i=0;i //计算偶数的方差 } 思路简析: 这类题目是题库中唯一要求考生写部分读函数的类型,但是非常简单,只需要写一个语句。 虽然题目中说“原始数据文件存放的格式是:每行存放10个数,并用逗号隔开(每个数均大于0且小于等于2 000)”,但是这句话可以认为是废话。因为所有的数据都是整数,对整数进行输入时,不用管scanf()中写的是什么格式,也不用管数据文件中数据的存放形式,只要能将两个数分开就行,用空格、回车、逗号都可以,实际输入或者在文件中存放数据的形式完全可以和scanf()中的格式描述不一致。所以答案中简单地写“for(i=0;i 这个题目主要让考生写的还是后面那个子函数,也很简单。在最后求方差的那部分程序中要注意,题目让求偶数的方差,所以要判断xx[i]是否为偶数。【练习6】 把例 8中子函数compute的功能稍微改一下:分别计算出xx中奇数的个数odd、偶数的个数even、平均值aver及方差totfc的值。【答案】 int ReadDat(void){和例8中的答案一样} void Compute(void){int i;for(i=0;i //求所有数的和 aver/=MAX;for(i=0;i //计算所有数的方差 } 细节问题: 注意审题,题目只要求分别求奇、偶数的个数,而平均值是求所有数的,方差也是求所有数的。 例 9、下列程序的功能是:计算出自然数SIX和NINE的个数cnt,它们满足的条件是SIX+SIX+SIX=NINE+ NINE,并计算满足此条件的所有SIX与NINE的和SUM。请编写函数countvalue()实现程序的要求,最后调用函数writeDat()把结果cnt和sum输出到文件OUT100.DAT中。其中S、I、X、N、E各代表一个十进制数字。 注意:部分源程序已给出。请勿改动主函数main()的内容。【试题程序】 #include cnt=sum=0;countvalue();printf(“满足条件的个数=%dn”,cnt);printf(“满足条件所有的SIX与NINE的和=%dn”,sum);writeDat();} writeDat(){略} 【答案】 void countvalue(){int s,i,x,n,e;int p,q;for(s=1;s<10;s++)for(i=0;i<10;i++)for(x=0;x<10;x++)for(n=1;n<10;n++)for(e=0;e<10;e++){p=s*100+i*10+x;q=n*1000+i*100+n*10+e;if(3*p==q*2)cnt++,sum+=p+q;} } 思路简析: s,i,x,n,e分别代表5个独立的数字,答案中的循环嵌套实际上是这5个数字独立变化时的各种组合,只有满足3*six==2*nine的组合是要进行统计的。需要注意的是,s和n不能从0开始,因为它们分别是两个数的最高位。 C语言 三级上机考试分题型讲解之题型四,对字符数组中的字符进行替换的问题(18%)2010-04-23 14:53这类问题的变化主要在于题目要求的替代关系和进行替代的条件,其中有按f(p)=p*11%256替代的(10%),还有按其它关系替代的(8%)。 例 1、函数ReadDat()的功能是实现从文件ENG63.IN中读取一篇英文文章,存入到字符串数组xx中。请编制函数encryptChar(),按给定的替代关系对数组xx中的所有字符进行替代,结果仍存入数组xx对应的位置上,最后调用函数WriteDat()把结果xx输出到文件PS63.DAT中。 替代关系:f(p)=p*11 mod 256(p是数组xx中某一个字符的ASCII值,f(p)是计算后新字符的ASCII值),如果计算后f(p)的值小于等于32或大于130,则该字符不变,否则将f(p)所对应的字符进行替代。注意:部分源程序已给出。原始数据文件存放的格式是:每行的宽度均小于80个字符。请勿改动主函数main()、读函数ReadDat()和写函数WriteDat()的内容。 【试题程序】 头文件略 unsigned char xx[50][80];int maxline = 0;/* 文章的总行数 */ int ReadDat(void);void WriteDat(void);void encryptChar(){ } main(){ system(“cls”); //不用管这句是什么意思 if(ReadDat()){ printf(“数据文件ENG63.IN不能打开!n 07”);return;} encryptChar();WriteDat();} int ReadDat(void){略} void WriteDat(void){略} 【答案】 void encryptChar(){int i,j,t;for(i=0;i //按替代关系得到新字符 if(t<=32||t>130); //根据题中条件,决定替换与否 else xx[i][j]=t;} } 思路简析: 定义i,j来引用二维数组xx,定义t来表示按替代关系得到的字符。如果满足题中条件,则字符不变,即不作处理,所以答案中if()后面是一个空语句,只有一个分号。如果不满足条件,那么进行替换。细节问题: (1)题目所说的mod就是求余的意思。相当于“%”。 (2)试题程序中已经定义并求出了二维数组的有效行数maxline,注意审题。 (3)答案中定义的变量t不是字符字符型,而是整型。因为在C语言中,整型和字符型可以通用。把t定义为unsigned char 型也是可以的。字符型变量参与运算时就相当于它的ASCII值。 【练习1】 替代关系和例1一样:f(p)=p*11 mod 256,把字符保持不变的条件改为:如果原字符是数字字符0至9或计算后f(p)的值小于等于32,则该字符不变。 【试题程序】 除文件名外与例1一样,略。【答案】 void encryChar(){int i,j,t;for(i=0;i 注意:if()中’0’和 ‘9’上的单引上千万不能漏掉。因为阿拉伯数字的身份比较特殊,它既是数字也是ASCII表中的字符。如果不加单引号,它的值就是我们常见的数字值,而加上单引号,它的值就是它在ASCII表中的代码。‘0’的代码是48,‘1’的代码是49,‘2’的代码是50,„„漏掉引号是常见的典型错误,也是我们学校订的题库书中的一个错误。如果把条件“原字符是数字字符”改为“原字符是小写字母”,或“原字符是大写字母”,则程序中相应位置改为“xx[i][j]>=’a’&&xx[i][j]<=’z’”或“xx[i][j]>=’A’&&xx[i][j]<=’Z’”。不同题目有不同的要求。 例 2、把例1中的替代关系改为:以行为单位(即不涉及行间的问题,对每一行都执行相同的操作),把字符串中所有字符的ASCII值右移4位,然后把右移后的字符ASCII值再加上原字符的ASCII值。得到的新字符仍存入原字符串对应的位置上。最后把已处理的字符串仍按行重新存入字符串数组xx中(这句话其实是废话,因为字符串xx[i]本来就是字符串数组xx中的一行)。【试题程序】除文件名外与例1一样,略。【答案】 void StrCharJR(void){int i,j;for(i=0;i 思路简析: 可能有的同学对左移右移的操作不大熟悉,例2和后面的练习 2、练习3都是关于移位操作的。【练习2】 把例1中的替代关系改为:以行为单位,把字符串中的所有字符的ASCII值左移4位,如果左移后,其字符的ASCII值小于等于32或大于100,则原字符保持不变;否则就把左移后的字符ASCII值再加上原字符的ASCII值。 得到的新字符仍存入到原字符串对应的位置。最后把已处理的字符串仍按行重新存入字符串数组xx中。 【试题程序】除文件名外与例1一样,略。【答案】 void StrCharJL(void){int i,j;for(i=0;i 思路简析: 本题在练习例2的思路基础上,多加了一步判断。【练习3】 把例1中的替代关系改为:以行为单位,把字符串的每一个字符的ASCII值右移4位后加上前一个字符的ASCII值,第一个字符的ASCII值加上原最后一个字符的ASCII值。 得到的新字符分别存放在原字符串对应的位置上。最后把已处理的字符串仍按行重新存入字符串数组xx中。 【试题程序】除文件名外与例1一样,略。【答案】 void CharConvA(void){int i,j,s;char t;for(i=0;i //测量xx[i] 这一行的字符数 t=xx[i][s-1]; //把最后一个元素取出来,存在变量t中 for(j=s-1;j>0;j--) //从最后一个元素开始,按题中要求进行替换 xx[i][j]=(xx[i][j]>>4)+xx[i][j-1];//这一行中的括号一定不可以漏掉 xx[i][0]+=t; //对第一个元素进行替换 } } 思路简析: 对每一行,首先要知道这一行有多少个字符。因为对第一字符进行处理时要用到最后一个字符,而程序要从最后一个字符开始替换,替换之后最后一个字符已经不再是原来的字符了,所以首先要把最后一个字符取出来,保存到别的地方。然后,从最后一个字符开始进行替换操作,这样一直到第二个字符xx[i][1]。最后,再对第一个字符xx[i][0]进行替换。注意: (1)这个例题中,第一个字符的处理与其它字符稍有差别,没有用到移位操作。如果题目对第一个字符的要求与其它字符一样,改为:“第一个字符的ASCII值右移四位后加上原最后一个字符的ASCII值”,程序的最后一句就要相应地改为:xx[i][0]=(xx[i][0]>>4)+t;因为实际考试中的题目未必与辅导书题库中的题目一模一样,答题的时候要注意审题。 (2)程序倒数第二行xx[i][j]=(xx[i][j]>>4)+xx[i][j-1];中的括号是不可以漏掉的,因为“+”的优先级高于“>> ”,如果不加括号,则程序执行的时候会先算“+”再算“>>”,相应地结果就错了。【练习4】 把例1中的替代关系改为:以行为单位,把字符串中的每一个字符的ASCII值加上后面一个字符的ASCII值,最后一个字符的ASCII值加原第一个字符的ASCII值。 得到的新字符仍存放在原字符串的对应位置上。然后把已处理的字符串逆转后按行重新存入字符串数组xx中(这句话不是废话,它要求将处理后的字符串逆转)。【试题程序】除文件名外与例1一样,略。【答案】 void ChA(void){ int i,j,s;char t;for(i=0;i //取出第一个元素,存入变量t s=strlen(xx[i]);for(j=0;j //处理最后一个元素 strrev(xx[i]);} } 思路简析: 与练习3类似,没有用到移位,只是ASCII值相加,复杂程度更低一点。不过最后一行使用了一个库函数,strrev(),rev是reverse的前3个字母,这个函数的功能是实现字符串的倒排。【练习5】 把例1中的替代关系改为:以行为单位,把字符串中的所有小写字母改写成该字母的下一个字母,如果是字母z,则改写成字母a。大写字母和其他字符不变。【试题程序】除文件名外与例1一样,略。【答案】 void ConvertCharA(void){int i,j;for(i=0;i 细节问题: 程序中字母上的单引号千万不可漏掉。 如果题中要求把小写字母改写成该字母的上一个字母,字母a改写成字母z,程序相应地改为: „„ {if(xx[i][j]=='a')xx[i][j]=z';else if(xx[i][j]>='b'&&xx[i][j]<='z')xx[i][j]--;„„ 例 3、请编制函数chg(char *s),功能为:把s字符串中所有的字符左移一个位置,串中的第一个字符移到最后。 例如:s字符串中原有内容为Mn,123xyZ,则调用该函数后,结果为n,123xyZM。【答案】 void chg(char *s) //s为要处理的字符串的名称 {int i;char t;t=s[0]; //把第一个字符取出,存入变量t for(i=0;i //把t赋给最后一个元素 } 思路简析: 这个题目非常简单,其本质也是字符的替换。必须注意的是,字符必须从左边开始依次左移,方向不能反过来,如果从右边开始,前面得到的都是最后一个字符。 所以说,如果题目变一下,把左移改成右移,最后一个字符字符移到最前面,则程序应为: 而绝不能写成: void chg(char *s) void chg(char *s){ int i; { int i;char t; char t;t= s[strlen(s)-1]; t= s[strlen(s)-1]; for(i=strlen(s)-1;i>0;i--) for(i=0;i s[i+1]=s[i];s[0]=t; s[0]=t;} } 细节问题: 答案最后一行s[strlen(s)-1]=t;可以简写为s[i]=t;因为循环结束后,i的值就是strlen(s)-1了。 【练习6】 把例3中的功能要求改为:把s字符串中的所有字母改写成该字母的下一个字母,字母z改写成字母a、字母Z改成字母A。其他字符不做改变。 例如:s字符串中原有的内容为:Mn.123Zxy,则调用该函数后,结果为No.123Ayz。【答案】 void chg(char*s){int j;for(j=0;j 细节补充: 如果要求把大写字母改写成小写字母,则s[j]+=32;大写字母与对应的小写字母相差32。A的ASCII码值为65,a的ASCII码值为97。 C语言 三级上机考试分题型讲解之题型五,对字符串数组进行排序的问题(6%)2010-04-23 14:59这类题目通常是对二维字符数组的每一行进行排序,本质上和前面讲的排序问题是一样的。例 1、函数readDat()实现从文件IN76.DAT中读取20行数据存放到字符串数组xx中(每行字符串长度均小于80)。请编制函数jsSort(),其功能是:以行为单位,对字符串变量下标为奇数位置上的字符按其ASCII值从小到大的顺序进行排序,排序后的结果仍按行重新存入字符串数组xx中,最后调用函数writeDat()把结果xx输出到文件OUT76.DAT中。 例如:位置: 0 源字符串: h g f e d c b a 则处理后字符串:h a f c d e b g 注意:部分源程序已给出。请勿改动主函数main()、读数据函数readDat()和输出数据函数writeDat()的内容。【试题程序】 #include 全国计算机二级C语言考试上机题型总汇 (一)关于“******”问题 1、将字符串中的前导*号全部删除,中间和后面的*号不删除。void fun(char *a){ char *p=a;while(*p= =’*’)p++;for(;*p!=’ ’;p++,a++)*a=*p;*a=’ ’;} 2、只删中间* int i;for(i=0;a[i]= =’*’;i++)for(;h 3、只删尾* while(*a!=’ ’)a++;a--;while(*a= =’*’)a--;*(a+1)=’ ’; 4、只留前* int i , j=0;for(i=0;a=’*’;i++);j=i;for(;a;i++)if(a!=’*’)a[j++]=a[i];a[j]=’ ’; 5、只留中间* int i,j=0;for(i=h;i第二篇:计算机二级C语言上机题型总结