第8周编程题在线测试
NOTE:
- 数组的初始化函数 memset(void *buffer,int ch,size_t n)
- 功能: 函数拷贝ch 到buffer 从头开始的n个字节里, 并返回buffer指针。memset() 可以应用在将一段内存初始化为某个值。例如:memset( the_array, 0, sizeof(the_array) ),这是将一个数组的所以分量设置成零的很便捷的方法。
- 注: 并不能将任何整数都赋值给数组,如下:
从Debug中我们可以看到程序运行到断点的时候,memset函数将20个字节的内存按每个字节都放了1,1的二进制为0000 0001,所以四个字节的1为0000 0001 0000 0001 0000 0001 0000 0001,转换成十进制就是16843009,即每个数组元素的值为16843009;同理我们便可以知道为什么0和-1可以正确的赋值,以-1为例,-1在计算机中按补码的形式存储,即1111 1111,所以memset函数初始化后20个字节的内存里的二进制数仍是全1,所以结果转换成十进制仍是-1,同理0。
- 数组赋值函数 void *memcpy( void *to, const void *from, size_t n )
- 功能:函数从from中复制n个字节到to中,并返回to指针。 如果to 和 from 重叠,则函数行为不确定。
- 数组赋值函数 void *memmove( void *to, const void *from, size_t count )
- 功能: 与mencpy相同,不同的是当to 和 from 重叠,函数正常仍能工作。
memcpy()和memmove()的区别:
如上图所示,当两块内存区域处于上图中的情况时,很明显memcpy的实现存在问题,因为目标内存块的内容会将源内存块中后面还没有拷贝的那部分内存中的内容覆盖掉,导致后面部分的源内存块内容出错。而memmove()函数中多了一个内存重叠的检查,当出现上述情况时:先将内容复制到类似缓冲区的地方,再用缓冲区中的内容覆盖to指向的内存。
- 数组下标越界问题可用哨兵的使用规避;字符数组永远留意’\0’,比如要存储hello这个字符串,那么要申请array[6]。
- 用数组作为函数参数(Call-by-Reference)的时候,是将实参数组的首地址传给形参,形参数组和实参数组在内存中共享相同的存储单元,因此对形参数组元素值的修改也就相当于是对实参数组元素值的修改,这是与简单变量作为函数参数(Call-by-Value)的一个本质区别,其实与指针有关。
- 在声明函数的二维数组形参时,不能省略数组第二维的长度,因为必须知道列数才能正确计算array[i][j]在数组中相对于第一个元素的偏移位置。
- 在二分查找算法中 mid = (low + high) / 2 存在有符号整数数值溢出的可能,使mid值变为一个负数,改进方法为 mid = (high - low) / 2 + low 。
经典数组题:杨辉三角
用函数编程计算并输出如图所示的杨辉三角形。按要求在空白处填写适当的表达式或语句,使程序完整并符合题目要求。
#include<stdio.h>
#define N 20
void CaculateYH(int a[][N], int n);
void PrintYH(int a[][N], int n);
int main()
{
int a[N][N] = {0}, n;
printf("Input n(n<20):");
scanf("%d", &n);
CaculateYH(a, n);
PrintYH(a, n);
return 0;
}
/* 函数功能:计算杨辉三角形前n行元素的值 */
void CaculateYH(int a[][N], int n)
{
int i, j;
for (i = 0; i < n; i++)
{
a[i][0] = 1;
a[i][i] = 1;
}
for (i = 2; i < n; i++)
{
for (j = 1; j <= i - 1; j++)
{
a[i][j] = a[i-1][j-1] + a[i-1][j];
}
}
}
/* 函数功能:输出杨辉三角形前n行元素的值 */
void PrintYH(int a[][N], int n)
{
int i, j;
for (i=0; i<n; i++)
{
for (j = 0; j <= i; j++)
{
printf("%4d", a[i][j]);
}
printf("\n");
}
}
1. 摘苹果
题目内容:
陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个30厘米高的板凳,当他不能直接用手摘到苹果的时候,就会踩到板凳上再试试。现在已知10个苹果到地面的高度(已知在100cm到200cm之间,包括100cm和200cm),以及陶陶把手伸直时能达到的最大高度(已知在100cm到120cm之间,包括100cm和120cm),请你编写程序帮助陶陶计算一下他能摘到的苹果数目。假设他碰到苹果,苹果就会掉下来。
函数原型: int GetApple(int a[], int height, int n);
函数功能: 计算淘淘能摘到的苹果数目
函数参数: 数组a保存苹果到地面的高度;height代表陶陶把手伸直时能到的最大高度;n为苹果数
函数返回值: 淘淘能摘到的苹果数目
#include<stdio.h>
#include<string.h>
#define N 100
int GetApple(int a[], int height, int n);
int main()
{
int a[N];
int height;
printf("%d",GetApple(a,height,10));
return 0;
}
int GetApple(int a[], int height, int n)
{
int h,count = 0;
memset(a,0,sizeof(a));
for(int i = 0;i < n; i++)
{
scanf("%d",&a[i]);
}
getchar();
scanf("%d",&height);
h = height + 30;
for(int i = 0;i < n; i++)
{
if(h >= a[i])
count++;
}
return count;
}
2. 好数对
题目内容:
已知一个集合A,对A中任意两个不同的元素求和,若求得的和仍在A内,则称其为好数对。例如,集合A={1 2 3 4},1+2=3,1+3=4,则1,2和1,3 是两个好数对。编写程序求给定集合中好数对的个数。
#include<stdio.h>
#include<string.h>
#define N 1000
int main()
{
int a[N],n,count = 0;
scanf("%d",&n);
getchar();
for(int i = 0;i < n; i++)
{
scanf("%d",&a[i]);
}
for(int i = 0; i < n - 1; i++)
{
for(int j = i + 1; j < n; j++)
{
for(int k = 0; k < n; k++)
{
if(a[k] == a[i] + a[j])
count++;
}
}
}
printf("%d",count);
return 0;
}
3. 组合三位数
题目内容:
将0到9这十个数字分成三个3位数,要求第一个3位数,正好是第二个3位数的1/2,是第三个3位数的1/3。问应当怎样分,编写程序实现。
#include<stdio.h>
int main()
{
int i ;
for(i = 100;i <= 333; i++)
{
int num[10] = {0};
int sec,third,a,b,c,j = 0,cnt = 0;
a = i/100;
c = i%10;
b = (i/10)%10;
if(a != 0 && a != b && a != c && b != c)
{
num[a] = num[b] = num[c] = 1;
sec = i*2;
third = i*3;
num[sec/100] = num[sec%10] = num[(sec/10)%10] = 1;
num[third/100] = num[third%10] = num[(third/10)%10] = 1;
for(;j < 10; j++)
{
if(num[j] == 1)
cnt++;
}
if(cnt == 9)
printf("%d,%d,%d\n",i,sec,third);
}
}
return 0;
}
4. 求100以内的最大素数
题目内容:
编程计算n(n<=500)以内的10个最大素数及其和,分别输出这最大的10个素数及其和。n的值要求从键盘输入。要求10个素数按从大到小的顺序输出。
#include<stdio.h>
#include<math.h>
int IsPrime(int n);
int main()
{
int n,count = 0;
int sum = 0;
printf("Input n(n<=500):");
scanf("%d",&n);
for(int i = n;i >= 2 && count < 10; i--)
{
if(IsPrime(i))
{
printf("%6d",i);
sum += i;
count++;
}
}
printf("\nsum=%d\n",sum);
return 0;
}
int IsPrime(int n)
{
if(n <= 1)return 0;
for(int i = 2;i <= sqrt(n); i++)
{
if(n%i == 0)return 0;
}
return 1;
}
第8周练兵区编程题
1. 三天打渔两天晒网
题目内容:
中国有句俗语叫“三天打鱼两天晒网”,某人从1990年1月1日起开始“三天打鱼两天晒网”,即工作三天,然后再休息两天。问这个人在以后的某一天中是在工作还是在休息。从键盘任意输入一天,编程判断他是在工作还是在休息,如果是在工作,则输出:He is working,如果是在休息,则输出:He is having a rest,如果输入的年份小于1990或者输入的月份和日期不合法,则输出:Invalid input。
#include<stdio.h>
int IsLeap(int n);
int main()
{
int a[2][12] = {{31,28,31,30,31,30,31,31,30,31,30,31},
{31,29,31,30,31,30,31,31,30,31,30,31}};
int year,month,day,i,dis = 0;
scanf("%4d-%2d-%2d",&year,&month,&day);
if(year < 1990 || month>12||month<1)printf("Invalid input");
else if(IsLeap(year) == 1 &&(day > a[1][month - 1])||(day <= 0))printf("Invalid input");
else if(IsLeap(year) == 0 &&(day > a[0][month - 1])||(day <= 0))printf("Invalid input");
else
{
for(i = 1990;i < year; i++)
{
if(IsLeap(i) == 0)
dis += 365;
else
dis += 366;
}
for(i = 1; i < month; i++)
{
if(IsLeap(year) == 0)
dis += a[0][i - 1];
else
dis += a[1][i - 1];
}
dis += day;
dis = dis%5;
if(dis==1||dis==2||dis==3)
printf("He is working");
else
printf("He is having a rest");
}
return 0;
}
int IsLeap(int n)
{
if((n%4 == 0 && n%100 != 0)||(n%400 == 0))return 1;
else return 0;
}
2. 统计用户输入
题目内容:
从键盘读取用户输入直到遇到#字符,编写程序统计读取的空格数目、读取的换行符数目以及读取的所有其他字符数目。(要求用getchar()输入字符)
#include<stdio.h>
int main()
{
int space,newline, others;
space = newline = others = 0;
char ch;
printf("Please input a string end by #:\n");
while((ch = getchar()) != '#')
{
if (ch == ' ')
space++;
else if (ch == '\n')
newline++;
else
others++;
}
printf("space: %d,newline: %d,others: %d\n", space, newline, others);
return 0;
}
3. 统计正整数中指定数字的个数
题目内容:
从键盘输入一个正整数number,求其中含有指定数字digit的个数。例如:从键盘输入正整数number=1222,若digit=2,则1223中含有 3个2,要求用函数实现。
函数原型为: int CountDigit(int number,int digit);
#include<stdio.h>
int CountDigit(int number,int digit);
int main()
{
int m,n;
printf("Input m,n:\n");
scanf("%d,%d",&m,&n);
printf("%d\n",CountDigit(m,n));
return 0;
}
int CountDigit(int number,int digit)
{
int count = 0;
while(number != 0)
{
if(number%10 == digit)
count++;
number = number/10;
}
return count;
}
4. 玫瑰花数
题目内容:
如果一个n位正整数等于它的n个数字的n次方和,则称该数为n位自方幂数。四位自方幂数称为玫瑰花数。编程计算并输出所有的玫瑰花数。
#include<stdio.h>
#include<math.h>
int IsRose(int n);
int main()
{
for(int i = 1000;i <= 9999; i++)
if(IsRose(i))
printf("%d\n",i);
return 0;
}
int IsRose(int n)
{
int sum = 0;
int number = n;
while(n != 0)
{
sum += pow(n%10,4);
n = n/10;
}
if(sum == number) return 1;
else
return 0;
}
5. 四位反序数
题目内容:
反序数就是将整数的数字倒过来形成的整数。例如,1234的反序数是4321。设N是一个四位数,它的9倍恰好是其反序数,编程计算并输出N的值。
#include<stdio.h>
int back_seque(int n);
int main()
{
for(int i = 1000;i <= 9999; i++)
if(back_seque(i))
printf("%d\n",i);
return 0;
}
int back_seque(int n)
{
int a,b,c,d,back;
d = n%10;
c = (n/10)%10;
b = (n/100)%10;
a = n/1000;
back = d*1000 + c*100 + b*10 + a;
if(n*9 == back)
return 1;
else
return 0;
}
6. 8除不尽的自然数
题目内容:
一个自然数被8除余1,所得的商被8除也余1,再将第二次的商被8除后余7,最后得到一个商为a。又知这个自然数被17除余4,所得的商被17除余15,最后得到一个商是a的2倍。求满足以上条件的最小自然数。
#include <stdio.h>
int main()
{
int n = 0;
int a, b, flag = 0;
while(!flag)
{
if(n%8==1 && (n-1)/8%8==1 && ((n-1)/8-1)/8%8==7)
{
a = (((n-1)/8-1)/8-7)/8;
if(n%17==4 && (n-4)/17%17==15)
b = ((n-4)/17-15)/17;
}
if(b == 2 * a)
{
flag = 1;
printf("%d\n", n);
}
n++;
}
return 0;
}
7. 矩阵转置v1.0
题目内容:
用二维数组作为函数参数,编程计算并输出n×n阶矩阵的转置矩阵。其中,n的值不超过10,n的值由用户从键盘输入。
#include <stdio.h>
int main()
{
int n;
printf("Input n:");
scanf("%d",&n);
printf("Input %d*%d matrix:\n",n,n);
int a[n][n];
for(int i = 0;i < n; i++)
for(int j = 0;j < n; j++)
scanf("%d",&a[i][j]);
printf("The transposed matrix is:\n");
for(int i = 0;i < n; i++)
{
for(int j = 0;j < n; j++)
{
printf("%4d",a[j][i]);
}
printf("\n");
}
return 0;
}
8. 兔子生崽问题
题目内容:
假设一对小兔的成熟期是一个月,即一个月可长成成兔,那么如果每对成兔每个月都可以生一对小兔,一对新生的小兔从第二个月起就开始生兔子,试问从一对兔子开始繁殖,n(n<=12)月以后可有多少对兔子(即当年第n月份总计有多少对兔子,含成兔和小兔)?请编程求解该问题,n的值要求从键盘输入。
#include <stdio.h>
int Fabonaci(int n);
int main()
{
int n;
printf("Input n(n<=12):\n");
scanf("%d",&n);
for(int i = 1;i <= n; i++)
printf("%4d",Fabonaci(i));
printf("\nTotal=%d\n",Fabonaci(n));
return 0;
}
int Fabonaci(int n)
{
if(n == 1)
return 1;
else if(n == 2)
return 2;
else
return Fabonaci(n - 1) + Fabonaci(n - 2);
}
9. 抓交通肇事犯
题目内容:
一辆卡车违犯交通规则,撞人后逃跑。现场有三人目击事件,但都没记住车号,只记下车号的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的,但与前两位不同;丙是位数学家,他说:四位的车号刚好是一个整数的平方。现在请根据以上线索帮助警方找出车号以便尽快破案。
#include <stdio.h>
int main()
{
int m, k, i, j;
for(i=0;i<=9;i++)
{
for(j=0;j<=9;j++)
{
for(m=32;m<=99;m++)
{
k = 1000*i + 100*i + 10*j + j;
if(k == m*m)
{
printf("k=%d,m=%d\n",k,m);
break;
}
}
}
}
return 0;
}
10. 检验并打印幻方矩阵
题目内容:
幻方矩阵是指该矩阵中每一行、每一列、每一对角线上的元素之和都是相等的。从键盘输入一个5×5的矩阵并将其存入一个二维整型数组中,检验其是否为幻方矩阵,并将其按指定格式显示到屏幕上。
#include <stdio.h>
int IsMagic(int a[][5]);
int main()
{
int n;
int a[5][5] = {0};
for(int i = 0;i < 5; i++)
for(int j = 0;j < 5; j++)
scanf("%d",&a[i][j]);
if(IsMagic(a))
{
printf("It is a magic square!\n");
for(int i = 0;i < 5; i++)
{
for(int j = 0;j < 5; j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
}
else
printf("It is not a magic square!\n");
return 0;
}
int IsMagic(int a[][5])
{
int b[12]= {0};
int elem;
for(int i = 0;i < 5; i++)//计算5个行和
for(int j = 0;j < 5; j++)
b[i] += a[i][j];
for(int i = 0;i < 5; i++)//计算5个列和
for(int j = 0;j < 5; j++)
b[j+5] += a[i][j];
for(int i = 0;i < 5; i++)//计算左对角线和
b[10] += a[i][i];
for(int i = 0;i < 5; i++)//计算右对角线和
b[11] += a[i][4 - i];
elem = b[0];
for(int i = 1;i < 12; i++)//判断这12个和是否相等
if(elem != b[i])
return 0;
return 1;
}