常考题型归纳:
一:数值类
题型1:素数问题
素数:只能被自己与1整除的数,最小的素数是2,比如3,5,7等都是素数
算法:任意输入一个数判断是否是素数
#include <stdio.h>
#include <conio.h>
int prime(int n) // 实现判断素数函数
{for(int k=2;k<n;k++) //核心程序
{if(n%k==0) return 0;}
return 1;}
void main()
{int n;
scanf(“%d”,&n);
if(prime(n))
printf(“%s”,”yes”);
else
printf(“%s”,”no”);
getch(); clrscr(); //清屏}
题型2:整数拆分
整数拆分是将整数n的每一个数取出,在取数的过程中,不断使用”%”和”/”运算符号
算法:输入整数n,求出n的各个位数相加之和,如输入3476,结果为20
#include <stdio.h>
main()
{
int n, x, sum=0;
scanf(“%d”,&n);
while(n!=0) //此while程序为关键
{x=n%10;
sum+=x;
n=n/10;}
printf(“%d\n”,sum);}
题型3:回文数(反读与正读相同的数,比如121,313等)
编程题:
(1)在给定范围内查找k使得用公式k^2+k+17生成的整数满足以下条件:该数的十进制表示中低3位数字相同,去掉低3位后的整数是回文数。例如,当k=461时用公式生成的整数是212999,该数满足所给条件。
【编程要求】
1.编写函数int findnum(int n1,int n2,long a[][2])实现以下功能:k依次取n1~n2范围内的每个整数,分别用每个k及公式k^2+k+17生成整数y,若y满足给定条件,则将k值及y值保存到a指向的数组中,函数返回a数组中k的个数。
2.编写函数main实现以下功能:声明二维数组a和变量n1、n2,输入两个整数并保存到n1、n2中,用 n1、n2及a数组作实参调用findnum函数,按所给格式输出a数组中的数据到屏幕及文件myf2.out中。最后将考生本人的准考证号输出到文件myf2.out中 。
【测试数据与运行结果】
输入:n1=1,n2=10000
输出:k number
461 212999
586 343999
3839 14741777
#include <stdio.h>
int findnum(int n1,int n2,long a[][2])
{ int i=0,j;
long x1,x2,x3,y,k;
for(k=n1;k<=n2;k++)
{y=k*k+k+17;
x1=x2=y/1000;x3=0;
while(x1>0) //本while循环将x1逆序变为x3
{x3=x3*10+x1%10;x1=x1/10;}
if(x2==x3&&y%10==y/10%10&&y%10==y/100%10) //判断是否是回文数同时低3位数是相同的
{ a[i][0]=k;a[i++][1]=y;}
}
return i;
}
main()
{int i,j;long a[10][2],n1,n2; FILE *fp;
fp=fopen("Myf2.out","w");
scanf("%d%d",&n1,&n2);
j=findnum(n1,n2,a);
printf("\n k\t number");
for(i=0;i<j;i++)
prinff("\n%ld\t%ld",a[i][0],a[i][1]);
fprintf(fp,"\n k \t number");
for(i=0;i<j;i++)
fprintf(fp,"\n%ld\t%ld",a[i][0],a[i][1]);
fprintf(fp,"\n My exam number is :0112400123");
fclose(fp);getch();
}
题型4:排序问题
(1)简单选择排序法
规律:(1)首先将第一个数a[0]与后面的每一个元素比较,比较时将比a[0]小的数和a[0]交换
(2)接着在除了a[0]以外的所有元素中,将a[1]与其之后的每一个元素比较,找到次小数放在a[1]位置。
(3)重复这个过程a-1遍,最后构成递增序列
#include <stdio.h>
void sort(int a[ ],int n) //简单选择排序法
{ int k;
for(int i=0; i<n-1; i++)
{k=i;
for(int j=i+1;j<n;j++)
if(a[k]>a[j]) k=j;
if(k!=i)
{temp=a[i]; a[i]=a[k]; a[k]=temp;}}
}
void print(int b[ ], int n)
{for( int i=0; i<n; i++)
printf(“%6d”, b[i]);}
void main()
{int a[ ]={6,3,1,2,5,0,9,3,7,6};
sort(a,10);
print(a,10);
}
(2)冒泡排序法:
冒泡排序:(1)始终比较的是相邻数字
(2)每趟排序后,最大数移到后面,最小数移到前面,注意与快速排序法的区别。
编写基于冒泡排序法的排序函数对10个整数进行升序排序
#include <stdio.h>
void sort(int a[ ], int n)
{int temp;
for( int i=0; i<n-1; i++)
{for( int j=0; j<n-i; j++)
{if(a[j]>a[j+1])
{temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;}}
}}
void print(int b[ ], int n)
{for(int i=0; i<n ; i++)
{printf(“%6d”, b[i]);}
}
main()
{int a[10]={6,7,4,10,2,5,9,8,3,1};
sort(a,10);
print(a,10);}
(3)插入排序法:
插入排序法是将数据一个一个地插入到已经有序的数列中,并保证每插入一个数后数列仍然有效。
插入排序的思想是:1先确定n个数x插到数组中的位置k,因为原本的数组有序,所以从第一个起到n-1个为止逐个比较,一直遇到比x大的数为止,这个位置就是x插入的位置
2确定应插入到位置k后,后面的元素要向后顺移一个位置以空出一个位置放入x
算法实现:
#include <stdio.h>
#include <conio.h>
void main()
{int i, n, x;
void insert(int *, int , int *);
int a[ ]={-3,2,6,9,14,19};
n=6;
scanf(“%d”,&x);
insert(a,x,&n);
for( i=0; i<n; i++)
printf(“%d”, a[i]);}
void insert(int *b, int y, int *m) //插入排序法
{int i,j, k;
for(i=*m-1; i>=0; i--)
{if(y<*(b+i))
*(b+i+1)=*(b+i);
else
break;
}
*(b+i+1)=y; (*m)++;
}
历年真题
投要求合并两个字符串。
【编程要求】
1.编写函数void fun(char *a,char *b,char *c),其功能是先将b指向的字符串逆存放,然后按a[0],b[0],a[1],b[1],…的顺序合并a字符串和b字符串到c指向的数组中,a或b中剩余字符拼接在c数组的尾部。
2.编写main函数,声明三个一维数组s1、s2和s,接收键盘输入的两个字符串并保存数组sl和s2中,调用fun函数对s2字符串做逆序变换,再合并sl字符串和s2字符串到s数组中。将合并后产生的数组s中的字符串输出到屏幕
【测试数据与运行结某】
测试数据:s1字符串为"abcdefg",s2字符串为"ABCD"
运行结果:aDbCcBdAefg
#include<stdio.h>
#include<string.h>
void fun(char *a,char *b,char *c)
{ int i,j;
char ch;
i=0;j=strlen(b)-1;
while(i<j) //本while循环实现逆序
{ ch=b[i];b[i]=b[j];b[j]=ch;
i++; j--;
}
while(*a || *b) //本while循环实现将a与b放到c里面
{if(*a){*c=*a;c++;a++;}
if(*b){*c=*b;c++;b++;}
}
*c='\0';
}
void main()
{
char s1[80],s2[80],s[200];
prinff("\nEnter sl string:");
gets(s1);
prinff("\nEnter s2 string:");
gets(s2);
fun(sl,s2,s);
prinff("\nThe resuIt is:%s\n",s);
}
二:字符串类
题型1:字符串与整数问题
例题:编写一个函数,将一个数字字符串转换为一个相应的整数
例如:输入字符串”-1234”,则函数把它转换为整数-1234
#include <stdio.h>
#include <string.h>
long fun(char *p)
{int i=1;
long n=0;
if(*p==’-‘) {p++;i=-1;}
else if(*p==’+’) p++;
while(*p>=’0’ && *p<=’9’) //关键转换算法
n=n*10+*p++-‘0’;
return n*i;
}
void main()
{
fun(“-1234”);
}
题型2:字符串的子串问题
例题:函数fun的功能是:求出在字符串中最后一次出现子字符串的位置,通过函数值返回,若未找到,则函数值为-1
int fun(char *str, char *t)
{char *p,*r,*s=str;
int a=-1;
while(*s)
{p=s;
r=t;
while(*r)
if(*r==*p) {r++;p++}
else break;
if(*r==’\0’) a=s-str+1;
s++;
}
return a;
}
void main()
{int p;
char s[100],t[100];
scanf(“%s”,s); scanf(“%s”,t);
p=fun(s,t);
printf(“The result is:%d”,p);
}
题型3:出现次数问题
函数void fun(char *tt, int *pp)的功能是:统计在tt所指字符串中’a’—‘z’26个字母各自出现的次数,并依次放在pp所指数组中,要求只统计小写字母
例如:当输入字符串”abcde”后,程序的输出结果应该是
11 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#include <stdio.h>
#include <string.h>
void fun(char *tt, int *pp)
{
int i,k=0;
char c;
for(c=’a’;c<=’z’;c++)
{pp[k]=0;
for(i=0;i<strlen(tt);i++)
if(tt[i]==c) pp[k]++;
k++;
}
}
void main()
{char aa[1000];
int bb[26];
scanf(“%s”,aa);
fun(aa,bb);
for(k=0;k<26;k++) printf(“%d”,bb[k]);
printf(“\n”);
}
三:二维数组问题
题型1:最值问题与矩阵转换
例题:随机输入五个数,判断最大值
#include <conio.h>
#include <stdio.h>
main()
{int a[5],max,i;
for(i=0;i<5;i++)
scanf(“%d”, &a[i]);
max=a[1];
for(i=0;i<5;i++)
if(max<a[i]) /*这边为判断最大数的关键一步,如果把max换成max>a[i]就变成求最小值了*/
max=a[i];
printf(“%d”,max);
getch(); clrscr(); //清屏}
历年真题:
改错题(对数值处理试题)
【程序功能】
已知x数组中存储的n阶矩阵有一个鞍点(鞍点是指该位置上的数是所在行的最大数。同时也是所在列的最小数),程序实现将矩阵中鞍点所在列移动到最右侧。
【测试数据与运行结果】
测试数据;
1 3 2 0
4 6 5 -1
7 9 8 0
-1 l0 3 2
运行结果;
An dian;a[0][1]
1 2 0 3
4 5 -1 6
7 8 0 9
-1 3 2 10
【含有错误的源程序】
#include<stdio.h>
#define N=4
void exchange(int a[ ][N])
{int i,j,k,f,t,m,mj;
for(i=0;i<N;i++)
{m=a[i][0]; mj=0;f=1;
for(j=0;j<N;j++) //寻找所在行的最大值下标
if(a[i][j]>m)
{m=a[i][j]; mj=j;}
for(k=0;k<N&&f;k++) // 判断是否符合在列中也是最小的
if(a[k][mj]>m)
f=0;
if(k>=N)break;
}
if(f)
{printf("An dian;a[%d][%d]\n",i,mj);
for(i=0;i<N;i++) //鞍点所在列移动到最右侧
{ t=a[i][mj];
for(j=mj;j<N-1;j++)
a[i][mj]=a[i][mj+1];
a[i][N-1]=t;
}
}
}
void main()
{int x[N][N]={{1,3,2,0},{4,6,5,-1),{7,9,8,0),{-1,10,3,2}},i,j;
for(i=0;i<N;i++)
{for(j=0;j<N;j++)
printf("%3d",x[i][j]);
printf("\n");
}
printf("\n");
exchange(int x[N][N]);
for(i=0;i<N;i++)
{for(j=0;j<N;j++)
printf("%3d",x[i][j]);
printf("\n");
}
}
本程序四个错误点:
(1)#define N=4 修改为:#define N 4 (2)if(a[k][mj]>m) 修改为:if(a[k][mj]<m)
(3)a[i][mj]=a[i][mj+1] 修改为:a[i][j]=a[i][j+1] (4)exchage(int x[N][N])修改为:exchange(x)
题型2:穷举法
穷举法的基本思想是不重复、遗漏的列举所有可能情况,从中寻找满足条件的结果。
例题:输出所有的水仙花数。水仙花数是一个三位数,且这个三位数的每一位的立方和等于该数。如153=13+53+3^3
#include <stdio.h>
void main()
{int i,j,k,t;
for(i=1;i<=9;i++) //实现百位数,三个for实现了循环900次
for(j=0;j<=9;j++) //实现十位数
for(k=0;k<=9;k++) //实现个位数,
{ t=i*100+j*10+k;
if(i*i*i+j*j*j+k*k*k==0)
printf(“%d”,t);
}
}
}
题型3:字符处理次数试题
改错题三:
程序功能:
函数mergeu的功能是:合并两个字符集合为一个新集合,每个字符串在新集合中仅出现一次,函数返回新集合中字符串的个数
[测试数据与运行结果]
测试数据:
s1集合{“while”,”for”,”switch”,”if”,”continue”}
s2集合{“for”,”case”,”do”,”else”,”char”,”switch”}
运行结果:
while for switch if break continue case do else char
[含有错误的源代码]
#include <stdio.h>
#include <string.h>
int merge(char s1[ ][10],char s2[ ][10],char s3[ ][10],int m,int n)
{int i,j,k=0;
for(i=0;i<m;i++)
s3[k++]=s1[i];
for(i=0;i<n;i++)
{for(j=0;j<m;j++)
if(strcmp(s2[i],s1[j]))
break;
if(j>m)
strcpy(s3[k++],s2[i]);
}
return k;
}
void main()
{int i,j;
char s1[6][10]={“while”,”for”,”switch”,”if”,”break”,”continue”},
s2[6][10]={“for”,”case”,”do”,”else”,”char”,”switch”},s3[20][10];
j=merge(s1[][10],s2[][10],s3[ ][10],6,6);
for(i=0;i<j;i++)
printf(“%s “,s3[i]);
}
错误点为:
(1)s3[k++]=s1[i] 修改为:strcpy(s3[k++],s1[i]);
(2) if(strcmp(s2[i],s1[j])) 修改为: if(strcmp(s2[i],s1[j])==0)
(3) if(j>m) 修改为: if(j>m-1)
(4) merge(s1[][10],s2[][10],s3[ ][10],6,6); 修改为: merge(s1,s2,s3,6,6);
分类汇总求平均值,函数sort_aver的形参a指向的二维数组(简称a数组)第一列元素的值代表类别,a数组已按第一列的值从小到大有序排列,sort_aver函数对a数组的n行元素中第一列元素值相同的所有行按列求平均值,并将类别值和除第一列外的各列平均值依次保存到b指向的数组
含有错误的源代码:
#include <stdio.h>
int sort_aver(int a[ ][3],n,b[ ][3])
{int i,j,k=0,c[10];
for(i=0;i<3;i++) b[0][i]=a[0][i];
c[0]=1;
for(i=1;i<n;i++)
{ if(b[k][0]==a[i][0])
{for(j=1;j<3;j++)
b[k][j]+=a[i][j];
c[k]++;
}
else
{c[++k]=0;
for(j=0;j<3;j++)
b[k][j]=a[i][j];
}
}
for(i=0;i<=k;i++)
for(j=1;j<3;j++)
b[i][j]/=c[i];
return k;
}
void main()
{int x[10][3]={{1,3,3},{1,1,3},{2,3,5},{3,5,4},{3,3,6}},i,j,n;
n=sort_aver(x,5,b);
for(i=0 ;i<n ;i++)
{for(j=0 ;j<n ;j++) printf(“%3d “,b[i][j]);
printf(“\n”);
}
}
错误点:
(1) ort_aver(int a[ ][3],n,b[ ][3]) 修改为: int sort_aver(int a[ ][3],int n,b[ ][3])
(2)c[++k]=0; 修改为:c[++k]=1; (3) return k 修改为:return ++k;
(4)在int x[10][3]={{1,3,3},{1,1,3},{2,3,5},{3,5,4},{3,3,6}},i,j,n;增加 int b[3][3];
三:结构体类试题
改错题1:
[程序功能]
输入两个正确日期且年份在1900-9999范围内,计算并输出两个日期之间间隔的天数,例如:2008-8-1和2009-8-1之间间隔的天数为365
提示:能被4整除并且不能被100整除的年份是闰年,能被400整除的年份也是闰年,其他年份则是平年
[测试数据与运行结果]
显示:first date:
输入:1980-2-1
显示:second date:2009-8-1
输出:10774 days
[含有错误的源程序]
#include <stdio.h>
#define leap(int y) ((y)%4==0 && (y)%100!=0||(y)%400==0)
struct d
{int y,m,d;};
int days(struct d d1,struct d d2)
{int mon[2][13]=
{{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}};
int i; long td=0;
for(i=d1.y;i<d2.y;i++) //判断是闰年还是平年然后将天数相加
td=leap(i)?366:365;
for(i=1;i<d1.m;i++) //减去初始年份中月份的天数
td-=mon[leap(d1.y)][i];
td-=d1.d-1;
for(i=1;i<d2.m;i++) //加上最后年份中月份天数
td+=mon[leap(d2.y)][i];
td+=d2.d-1;
return td;
}
void main()
{struct d d1,d2;
long td;
printf("first date:");
scanf("%d-%d-%d",d1.y,d1.m,d1.d);
printf("second date:");
scanf("%d-%d-%d",&d2.y,&d2.m,&d2.d);
td=days(&d1,&d2);
printf("%lddays",td);
}
四个错误点为:
(1) #define leap(int y) 修改为:#define leap(y)
(2) td=leap(i)?366:365; 修改为: td+=leap(i)?366:365;
(3) scanf("%d-%d-%d",d1.y,d1.m,d1.d); 修 改为 : scanf("%d-%d-%d"&,d1.y,&d1.m,&d1.d);
(4) td=days(&d1,&d2); 修改为: td=days(d1,d2);
其他常见算法:
(1)累加与累乘
实现1+2+3+4+5+6+7+8+9+10
main()
{ int sum,i;
sum=0;
for(i=1; i<=10;i++)
{sum=sum+i}
}
实现123456789*10
main()
{int sum,i;
sum=1;
do
{sum=sum*i; i=i+1;
}while(i<=10)
}
(2)交换位置
a=5, b=8,实现a与b交换数值
#include <conio.h>
main()
{int a,b,c;
scanf(“%d %d”,&a,&b);
c=a;a=b;b=c;
printf(“a=%d b=%d”,a,b);
getch();
}
(3)递推法:
递推的关键是通过前一个数值推导出后面一个数值
例题:已知某数列的前五项为1,1,2,3,5,请找出规律并求出其后的10项
解题:规律为第一项加第二项等于第三项,第二项加第三项等于第四项,以此类推1+1=2, 1+2=3,2+3=5
#include <stdio.h>
main()
{int t[15]={1,1,2,3,5};
int i,j;
for(i=5;i<15;i++)
{t[i]=t[i-1]+t[i-2]; //实现了第三个数等于第一个数加第二个数}
for( i=0;i<14;i++)
{printf(“%d”,a[i]);}
}
(5)递归法:
在调用一个函数过程中又出现直接或间接的调用该函数本身。递归与递推非常相似,递归是自己调用自己。是很重要的算法
例题:求n的阶乘 即n!
#include <stdio.h>
void main()
{float fac(int n);
int n;float x,y;
printf(“input an integer number:”);
scanf(“%d”,&n);
y=fac(n);
printf(“%d!=%10.0f\n”,n,y);
}
float fac(int n)
{float f;
if(n<0)
printf(“n<0,dataerror!”);
else
if(n==0||n==1)
f=1;
else
f=fac(n-1)*n;
return (f);
}
}
(6)求最大公约数
最大公约数:两个数最大的约数
int fun(int a,int b)
{ int r,t;
r=a%b ;
while(r !=0)
{a=b ;b=r ;r=a%b ;}
return b;
}
void main()
{ int num1,num2;
scanf(“%d%d”,&num1,&num2);
a=fun(num1,num2);
printf(“%d”,a);
}
(7)迭代法
迭代法是用计算机解决问题的一个基本方法,它利用计算机运算速度快,适合做重复性操作的特点,让计算机对一组指令重复执行。
例题:设方程为4xx-3*x-7=0,给出不精确的初始根x0=2,利用公式:xn+1=xn-f(x0)/f’(xn) n=0,1,2…求出方程的近似根,直到|xn+1-xn|<0.00001。
#include <stdio.h>
#include <math.h>
main()
{float x0,x1;
x0=2;
do
{x1=x0;
x0=x1-(4*x1*x1-3*x1-7)/(8+x1-3);
}while(fabs(x0-x1)>0.00001);
printf(“%f”, x0);
}
在本式中,x0是迭代变量,从最初的x0=2一步步的计算出新值并将老值置换。
改错题常见语法错误:
(1)缺少包含头文件
(2)宏定义出错:#define ,如#define N 3; 应该是 #define N 3 没有;号
(3)主函数中缺少函数声明
(4)从主函数调用子函数时参数数组出错 (是常见错误)
(5)对字符型二维数组赋值用strcpy,而不是用= (常见错误)
(6)for或do循环结束条件问题
(7)定义二维数组出错
(8)=与的区别
(9)strcmp错,比较两个字符串时应该用strcmp不能用号
(10) 对变量初始化错误,如int j,如果变量没有初始化默认是随机数,所以int j=0这样是标准写法
(11)用scanf函数给变量赋值时,变量前需要加&
(12)如果函数中出现return说明函数一定不是void类型