C语言程序设计
第九周
1重复数字检查(4分)
题目内容:
从键盘输入一个数,检查这个数中是否有重复出现的数字。如果这个数中有重复出现的数字,则显示“Repeated digit!”;否则显示“No repeated digit!”。
已知函数原型:
int CountRepeatNum(int count[], int n);
若有重复数字,则该函数返回重复出现的数字;否则返回-1.
#include <stdio.h>
int CountRepeatNum(int count[],int n);
int main()
{
int a[100],n,k;
printf("Input n:\n");
scanf("%d",&n);
if(CountRepeatNum(a[100],n)!=-1)
{
printf( "Repeated digit!\n") ;
}
else
{
printf("No repeated digit!\n");
}
return 0;
}
int CountRepeatNum(int count[],int n)
{
int k=n,i=0;
do
{
count[i]=k%10;
k= k/10;
i++;
}while(k);
for(int j=0;j<i-1;j++)
{
for(int s=j+1;s<i;s++)
{
if(count[j]==count[s])
{
return count[j];
}
}
}
return -1;
}
2教授的课(4分)
题目内容:
教授正在为一个有N个学生的班级讲授离散数学课。他对某些学生缺乏纪律性很不满意,于是决定:如果课程开始后上课的人数小于K,就取消这门课程。从键盘输入每个学生的到达时间,请编程确定该课程是否被取消。如果该门课程被取消,则输出“Yes”,否则输出“No”。假设教授在时刻0开始上课。如果一个学生的到达时间是非正整数,则表示该学生在上课前进入教室。如果一个学生的到达时间是正整数,则表示该学生在上课后进入教室。如果一个学生在时刻0进入教室,也被认为是在上课前进入教室。假设到达时间的绝对值不超过100,学生数N不超过1000。要求在输入学生的到达时间之前,先输入N和K。
#include <stdio.h>
int IsCancel(int a[],int n,int k);
int main()
{
int a[100],n,k;
printf("Input n,k:\n");
scanf("%d,%d",&n,&k);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
if((IsCancel(a,n,k))==1)
{
printf("YES");
}
else
{
printf("NO");
}
}
int IsCancel(int a[],int n,int k)
{
int sum=0;
for(int i=0;i<n;i++)
{
if(a[i]<=0)
{
sum++;
}
}
if(sum>=k)
{
return 0;
}
else
{
return 1;
}
}
3寻找鞍点(4分)
题目内容:
请编程找出一个M*N矩阵中的鞍点,即该位置上的元素是该行上的最大值,是该列上的最小值。如果矩阵中没有鞍点,则输出“No saddle point!”
已知函数原型:
void FindSaddlePoint(int a[][N], int m, int n);
在该函数中输出有无鞍点的信息。
参考自https://blog.csdn.net/jqq125/article/details/105912576
https://blog.csdn.net/jqq125/article/details/105912576
由于二维数组在定义或者函数参数传递的时候,必须要知道该数组的列,那应该怎么做呢,在计算机对数组进行访问的时候按照行进行访问二维数组的值,那么就可以定义一个指针作为二维数组的首地址,然后对二维数组进行访问
#include <stdio.h>
void FindsaddlePoint(int *a,int m,int n);
int main()
{
int M,N ;
printf("Input m,n:\n");
scanf("%d,%d",&M,&N);
int a[M][N];
printf("Input matrix:\n" );
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
{
scanf("%d",&a[i][j]);
}
}
FindsaddlePoint(&a[0][0],M,N);
}
void FindsaddlePoint(int *a,int m,int n)
{
int p,q,flag=0;
for(int i=0;i<m;i++)
{
p=0;q=i;
for(int j=0;j<n;j++)
{
if(*(a+i*n+j)>*(a+i*n+p))
{
p=j;
}
}
for(int k=0;k<m;k++)
{
if(*(a+k*n+p)<*(a+q*n+p))
{
q=k;
}
}
if(q==i)
{
flag=1;printf("a[%d][%d] is %d\n",q,p,*(a+q*n+p));
}
}
if(flag!=1)
{
printf("No saddle point!\n");
}
}
4计算三位阶乘和数(4分)
题目内容:
试求出所有三位阶乘和数:m=a!+b!+c!(其中a为百位数字,b为十位数字,c为个位数字。约定0!=1,并输出所有的m)
输入格式: 无
输出格式:"%ld\n"
#include <stdio.h>
long int factorial(int x);
int main()
{
int a,b,c;
long int m;
for(int i=100;i<1000;i++)
{
a=i/100;
b=i%100/10;
c=i%10;
m=factorial(a)+factorial(b)+factorial(c);
printf("%ld\n",m);
}
}
long int factorial(int x)
{
long int result=1;
if(x==0)
{
result=1;
}
else
{
for(int i=x;i>0;i--)
{
result*=i;
}
}
return result ;
}
1二分法求根(4分)
题目内容:
用二分法求下面的一元三次方程在区间[-10, 10]上误差不大于的根。
用二分法求方程的根的基本原理是:若函数有实根,则函数曲线应当在根x*这一点上与x轴有一个交点,并且由于函数是单调的,在根附近的左右区间内,函数值的符号应当相反。利用这一特点,可以通过不断将求根区间二分的方法,每次将求根区间缩小为原来的一半,在新的折半后的区间内继续搜索方程的根,对根所在区间继续二分,直到求出方程的根为止。
该方法的关键在于要解决如下两个问题:
1)如何对区间进行二分,并在二分后的左右两个区间中确定下一次求根搜索的区间?
假设区间端点为x1和x2,则通过计算区间的中点x0,即可将区间[x1, x2]二分为[x1, x0]和[x0, x2]。这时,为了确定下一次求根搜索的区间,必须判断方程的根在哪一个区间内,由上图可知方程的根所在区间的两个端点处的函数值的符号一定是相反的。也就是说,如果f(x0)与f(x1)是异号的,则根一定在左区间[x1, x0]内,否则根一定在右区间[x0, x2]内。
2)如何终止这个搜索过程?即如何确定找到了方程的根?
对根所在区间继续二分,直到,即|f(x0)|≈0时,则认为x0是逼近函数f(x)的根。
程序中所有变量的数据类型均为float。
#include <stdio.h>
#include<math.h>
float f(float a);
int main()
{
float a,b,c;
scanf("%f,%f",&a,&b);
c=(a+b)/2;
while(fabs(f(c))>1e-6)
{
if(f(a)*f(c)<0)
{
b=c;
c=(a+c)/2;
}
else if(f(a)*f(c)>0)
{
a=c;
c=(c+b)/2;
}
else
{
break;
}
}
printf("x=%6.2f\n",c);
}
float f(float a)
{
float x;
x=pow(a,3)-a-1;
return x;
}
2矩阵转置(4分)
题目内容:
某二维数组存放的数据构成一个nn的方阵,其中n<=5。写程序,从键盘输入n的值(n<=5),该nn矩阵中各元素的值按下面的公式计算:
a[i][j] = i * n + j + 1
其中,a[i][j]表示第i行第j列的元素。要求分别输出该矩阵和它的转置矩阵。
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int a[n][n];
printf("The original matrix is:\n");
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
a[i][j]=i*n+j+1;
printf("%3d",a[i][j]);
}
printf("\n");
}
printf("The changed matrix is:\n");
for(int j=0;j<n;j++)
{
for(int i=0;i<n;i++)
{
printf("%3d ",a[i][j]);
}
printf("\n");
}
}
4蛇形矩阵(4分)
题目内容:
从键盘任意输入一个自然数n(n表示矩阵的大小,假设不超过100),请编程输出一个nn的蛇形矩阵。如果输入的n不是自然数或者输入了不合法的数字,则输出"Input error!"。
函数原型: void ZigzagMatrix(int a[][N], int n);
函数功能:计算nn的蛇形矩阵
提示:用两个双重循环分别计算n*n矩阵的左上三角和右下三角,设置一个计数器从1开始记录当前要写入矩阵的元素值,每次写完一个计数器加1,在计算左上角和右下角矩阵元素时,分奇数和偶数两种情况考虑待写入的元素在矩阵中的行列下标位置。
#include <stdio.h>
void ZigzaMatrix(int a[][100],int n);
int main()
{
int n,a[100][100]={0},n1;
printf("Input n:\n");
n1=scanf("%d",&n);
if(n>100||n<=0||n1!=1)
{
printf("Input error!\n");
}
else
{
ZigzaMatrix(a, n);
}
return 0;
}
void ZigzaMatrix(int a[][100],int n)
{
int s=0,x=1,i,j,c=1;
while(c<=n*(n+1)/2)
{
for(i=s,j=0;i>=0;i--,j++)
{
if(s%2==0)
{
a[i][j]=c++;
}
else
{
a[j][i]=c++;
}
}
s++;
}
while(c<=n*n)
{
s=s-2;
for(i=n-1,j=x;j<n;i--,j++)
{
if(s%2==0)
a[i][j]=c++;
else
a[j][i]=c++;
}
s--;
x++;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
}
5 亲密数_1
题目内容:
2500年前数学大师毕达哥拉斯就发现,220与284两数之间存在着奇妙的联系:
220的真因数之和为:1+2+4+5+10+11+20+22+44+55+110=284
284的真因数之和为:1+2+4+71+142=220
毕达哥拉斯把这样的数对称为相亲数。相亲数,也称为亲密数,如果整数A的全部因子(包括1,不包括A本身)之和等于B,且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。
从键盘任意输入两个整数m和n,编程判断m和n是否是亲密数。若是亲密数,则输出“Yes!”,否则输出“No!”
程序运行示例1```
```c
#include <stdio.h>
int qin(int m);//返回m的真英数之和
int main()
{
int m,n;
printf("Input m, n:\n");
scanf("%d,%d",&m,&n);
if(m==qin(n)&&n==qin(m))
{
printf("Yes!\n");
}
else
{
printf("No!\n");
}
return 0;
}
int qin(int m)
{
int s=0;
for(int i=1;i<m;i++)
{
if(m%i==0)
{
s+=i;
}
}
return s;
}
6 亲密数_2
题目内容:
2500年前数学大师毕达哥拉斯就发现,220与284两数之间存在着奇妙的联系:
220的真因数之和为:1+2+4+5+10+11+20+22+44+55+110=284
284的真因数之和为:1+2+4+71+142=220
毕达哥拉斯把这样的数对称为相亲数。相亲数,也称为亲密数,如果整数A的全部因子(包括1,不包括A本身)之和等于B,且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。
从键盘任意输入一个整数n,编程计算并输出n以内的全部亲密数
#include <stdio.h>
int qin(int m);//返回m的真英数之和
int main()
{
int n;
printf("Input n:\n");
scanf("%d",&n);
int a[n];
for(int i=2;i<=n;i++)
{
a[i]=qin(i);
}
for(int j=2;j<=n;j++)
{
for(int i=2;i<=n;i++)
{
if(a[j]==i&&a[i]==j&&i!=j&&i>j)
{
printf("(%d,%d)\n",j,i);
}
}
}
return 0;
}
int qin(int m)
{
int s=0;
for(int i=1;i<m;i++)
{
if(m%i==0)
{
s+=i;
}
}
return s;
}
7 完全数(4分)
题目内容:
完全数(Perfect Number),又称完美数或完数,它是指这样的一些特殊的自然数。它所有的真因子(即除了自身以外的约数)的和,恰好等于它本身,即m的所有小于m的不同因子(包括1)加起来恰好等于m本身。注意:1没有真因子,所以1不是完全数。计算机已经证实在10300以下,没有奇数的完全数。例如,因为6 = 1 + 2 + 3,所以6是一个完全数。
从键盘任意输入一个整数m,编程判断m是否是完全数。若m是完全数,则输出“Yes!”,并同时打印出每一个完美数的全部因子,以验证这个数确实是一个完美数。若m不是完全数,则输出“No!”
#include <stdio.h>
int main()
{
int n,s=0,a[100],j=0;
printf("Input n:\n");
scanf("%d",&n);
if(n==1)
{
printf( "No!\n");
}
else
{
for(int i=1;i<n;i++)
{
if(n%i==0)
{
s+=i;
a[j]=i;
j++;
}
}
if(s==n)
{
printf("Yes!\n");
for(int k=0;k<j;k++)
{
printf("%d,",a[k]);
}
}
else
{
printf("No!\n");
}
}
return 0;
}
8 回文素数
题目内容:
所谓回文素数是指对一个素数n,从左到右和从右到左读是相同的,这样的数就称为回文素数,例如11,101,313等。编程计算并输出不超过n(100<=n<1000)的回文素数,并统计这些回文素数的个数,其中n的值从键盘输入。
#include <stdio.h>
int su(int m);//判断是否是素数
int daoxiang(int n);//判断正着读和倒着读是否一样
int main()
{
int n,s=0;
printf("Input n:\n");
scanf("%d",&n);
for(int i=11;i<=n;i++)
{
if(su(i))
{
if(daoxiang(i))
{
printf("%4d",i);
s++;
}
}
}
printf( "\ncount=%d\n",s);
return 0;
}
int su(int m)
{
int flag=1;
if(m==1||m==2)
return 0;
else
{
for(int i=2;i<m;i++)
{
if(m%i==0)
{
flag=0; break;
}
}
if(flag)
{
return 1;
}
else
{
return 0;
}
}
}
int daoxiang(int n)
{
int a[10],i=0,m=n,flag=1;
do
{
a[i]=m%10;
i++;
m=m/10;
}while(m);
for(int k=0,j=i-1;k<j;k++,j--)
{
if(a[k]!=a[j])
{
flag=0; break;
}
}
if(flag)
{
return 1;
}
else
{
return 0;
}
}
9 梅森尼数
题目内容:
形如2i-1的素数,称为梅森尼数。编程计算并输出指数i在[2,n]中的所有梅森尼数,并统计这些梅森尼数的个数,其中n的值由键盘输入,并且n的值不能大于50。其中,2i表示2的i次方,请不要使用pow(2,i)编程计算,应采用循环累乘求积的方式计算2^i。
提示:当i 超过30以后,2^i-1的值会很大,不能用long型变量来存储,必须使用double类型来存储。对于double类型变量x(不是整型)不能执行求余运算,即不能用 x % i == 0来判断x是否能被i整除,可以使用 x / i == (int)(x/i)来判断x是否能被i整除。
#include <stdio.h>
int su(double m);//判断是否是素数
double nci(int n);//计算2的n次方减一
int main()
{
int n,s=0;
printf("Input n:\n");
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
if(su(nci(i)))
{
printf( "2^%d-1=%.0lf\n",i,nci(i));
s++;
}
}
printf("count=%d\n",s);
}
int su(double m)
{
int flag=1;
if(m==1||m==2)
return 0;
else
{
for(int i=2;i<m;i++)
{
if(m/i==(int)(m/i))
{
flag=0; break;
}
}
if(flag)
{
return 1;
}
else
{
return 0;
}
}
}
double nci(int n)
{
double x=1;
for(int i=0;i<n;i++)
{
x*=2;
}
return x-1;
}
10 工资统计
题目内容:某公司有职员(最多50人),试编写程序打印最高工资、最低工资和平均工资。公司人数在主函数给出,职工工资输入请调用Input函数,计算最高工资、最低工资和平均工资调用Compute函数,打印最高工资、最低工资和平均工资在主函数。请在给定的框架下写出完整程序。
注意:这里输入员工工资,不要打换行,换行就又多输入一个值了
#include<stdio.h>
void Input(float wage[], int n);
float Compute(float wage[], int n, float *pmaxwage, float *pminwage);
int main()
{
float wage[50],maxwage,minwage,avewage;
int n;
printf("Please input n:\n");
scanf("%d",&n);
Input(wage,n);
avewage=Compute(wage,n,&maxwage,&minwage);
printf("maxwage=%.2f, minwage=%.2f, avewage=%.2f\n",maxwage,minwage,avewage);
return 0;
}
void Input(float wage[], int n)
{
for(int i=0;i<n;i++)
{
scanf("%f",wage+i);
}
}
float Compute(float wage[], int n, float *pmaxwage, float *pminwage)
{
*pmaxwage=wage[0];
*pminwage=wage[0];
int s=0;
for(int i=0;i<n;i++)
{
if(*pmaxwage<wage[i])
{
*pmaxwage=wage[i];
}
if(*pminwage>wage[i])
{
*pmaxwage=wage[i];
}
s+=wage[i];
}
return s/n;
}