《C语言程序设计教程》第三版 习题五

目录

一、习题

5.3 Fibonacci数列的前两个数为1, 1,以后每一个数都是其前两个数之和。求Fibonacci数列中的前20个数。用数组存放并按一行10个数的格式输出。

5.7 有17个人围成一圈(编号为1~17),从第1号开始进行1、2、3报数,凡报3者就退出,下一个人又从1开始报数……直到最后只剩下一个人时为止。请问此人原来的位置是多少号?

5.8 编写程序在屏幕上画一条正弦曲线。

5.9 用筛选法求100以内的素数。

5.10 设计选择排序的C语言程序。

5.11 有一行文字,要求删去其中某个字符。此行文字和要删除的字符均由键盘输入。

5.12 编写一个函数atoi,其作用是将一个整数字符串转换成一个整数。

5.15 数字螺旋方阵的形式如图所示。请将螺旋方阵存放在n×n的二维数组中,并将其打印输出。要求n由程序读入,数字螺旋方阵由程序自动生成。

5.16 有3行文字,找出其中共有多少空格和多少单词(规定单词之间以一个或多个空格作为间隔)。

5.17 有n个学生,每人考m门课。(1)找出成绩最高的学生的学号和课程号。(2)找出有不及格课程的学生的学号及其各门课的全部成绩。(3)求全部学生全部课程总平均分。

5.19 有n个国家名,要求按字母先后顺序排列,并按顺序输出。

二、注意

2.1 折半查找

2.2 冒泡排序

2.3


一、习题

5.3 Fibonacci数列的前两个数为1, 1,以后每一个数都是其前两个数之和。求Fibonacci数列中的前20个数。用数组存放并按一行10个数的格式输出。

#include<stdio.h>
int main(){
	int arr[20] = {0};
	int i = 0;
	arr[0] = 1;
	arr[1] = 1;
	for(i = 2; i < 20; i++){
		arr[i] = arr[i - 1] + arr[i - 2];
	}
	for(i = 0; i < 20; i++){
		if(i != 0 && i % 10 == 0){
			printf("\n");
		}
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

5.7 有17个人围成一圈(编号为1~17),从第1号开始进行1、2、3报数,凡报3者就退出,下一个人又从1开始报数……直到最后只剩下一个人时为止。请问此人原来的位置是多少号?

#include <stdio.h>
int main(){
	int num[50], n, *p, j, loop, i, m, k;
	printf("请输入这一圈人的数量:\n");
	scanf("%d", &n);
	p = num;//开始给这些人编号
	for (j = 0; j < n; j++){
		*(p + j) = j + 1;
	}
	i = 0;//i用于计数,即让指针后移
	m = 0;//m记录退出圈子的人数
	k = 0;//k报数1,2,3
	while(m < n - 1){//当退出的人数不大于总人数时,即留下的人数至少是一个人
		//这句不能写成m<n,因为假设有8人,当退出了6人时,此时还是进行人数退出,即m++,
		//这时是7<8,剩下的一个人自己喊1,2,3那么他也就退出了,将不会有输出
		if (*(p + i) != 0){//如果这个人的头上编号不是0就开始报数加1,这里采用的方法是报数为3的人头上编号重置为0
			k++;
		}
		if (k == 3){    
			k = 0;    //报数清零,即下一个人从1开始报数
			*(p + i) = 0;//将报数为3的人编号重置为0
			m++;    //退出人数加1
		}
		i++;      //指针后移
		if (i == n){//如果到了队尾,就要使指针重新指向对头//并且它只能放在i++后面,因为只有i++了才有可能i==n
			i = 0;
		}
	}
	printf("现在剩下的人是:");
	for (loop = 0; loop < n; loop++){
		if (num[loop] != 0){
			printf("%2d号\n",num[loop]);
		}
	}
	return 0;
}

5.8 编写程序在屏幕上画一条正弦曲线。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    int radian; //10倍弧度
    double y;  //y为y轴,值为-1到+1,步长为0.1;
    int x; //用62列值代表x轴;62来源于2Pi*10约等于2*3.1*10;

    //用反正弦值求x更加方便于按行输出
    for(y=1; y>=-1; y-=0.1)
    {
        radian=asin(y)*10;

        for(x=0;x<=62;x++)
        {
            if((x==radian)||(x==(31-radian)||(x==radian+61))) 
				//反余弦函数值域[0,pi]
                printf("*");
            else if(radian==0)
                printf("-");
            else
                printf(" ");

        }
        printf("\n");
    }
    return 0;
}

5.9 用筛选法求100以内的素数。

#include<stdio.h>

//非筛选法
//int main(){
//	int i, j, flag = 1;
//	for(i = 2; i < 100; i++){
//		flag = 1;
//		for(j = 2; j < i; j++){
//			if(i % j == 0){
//				flag = 0;
//				break;
//			}
//		}
//		if(flag)
//			printf("%d ", i);
//	}
//	return 0;
//}

//筛选法
int main(){
	int i, j, a[100];
	for(i = 0; i < 100; i++){
		a[i] = i + 1;
	}
	a[0] = 0;//1不是素数,挖去
	for(i = 0; i < 100; i++){
		for(j = i + 1; j < 100; j++){
			if(a[i] != 0 && a[j] != 0){//跳过已挖去的数
				if(a[j] % a[i] == 0)
					a[j] = 0;
			}
		}
	}
	printf("1-100的素数是:\n");
	for(i = 0; i < 100; i++){
		if(a[i] != 0){
			printf("%d ", a[i]);
		}
	}
	printf("\n");
	return 0;
}

5.10 设计选择排序的C语言程序。

#include<stdio.h>
int main(){
	int arr[10] = {32,5,6,10,8,13,25,17,9,12};
	int i = 0, j = 0, min, temp;
	printf("排序前:");
	for(i = 0; i < 10; i++){
		printf("%d ", arr[i]);
	}
	printf("\n");
	//选择排序
	for(i = 0; i < 9; i++){
		min = i;
		for(j = i + 1; j < 10; j++){
			if(arr[j] < arr[min]){
				min = j;
			}
		}
		if(i != min){
			temp = arr[i];
			arr[i] = arr[min];
			arr[min] = temp;
		}
	}
	printf("排序后:");
	for(i = 0; i < 10; i++){
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

5.11 有一行文字,要求删去其中某个字符。此行文字和要删除的字符均由键盘输入。

#include<stdio.h>
int main(){
	char ch, a[100];
	int i, j;
	printf("输入字符串:");
	gets(a);
	printf("输入要删除的字符:");
	scanf("%c", &ch);
	for(i = 0, j = 0; a[i] != '\0'; i++){
		if(a[i] != ch){
			a[j++] = a[i];
		}
	}
	a[j] = '\0';
	puts(a);
	return 0;
}

5.12 编写一个函数atoi,其作用是将一个整数字符串转换成一个整数。

#include<stdio.h>
char *my_itoa(int value, char str[], int radix)
{
	const char fonts[] = "0123456789abcdefghijklmnopqrstuvwxyz";
	char tmp_buff[33] = {0};
	int i = 0, j = 0;
	
	// 超出转换进制范围,退出 
	if ((radix < 2) || (radix > 36))
	{
		printf("radix err...\n");
		return NULL;
	}
	// 不是10进制的负数,退出函数
	if ((value < 0) && (radix != 10))
	{
		printf("value err...\n");
		return NULL;
	}
	// 10进制支持负数转换
	if ((value < 0) && (radix == 10))
	{
		value = -value;
		*str++ = '-';
	}
	// 转换
	while(value)
	{
		tmp_buff[i++] = fonts[value % radix];
		value /= radix;
	}
	// 逆序
	for(j=i-1; j>=0; j--)
	{
		*str++ = tmp_buff[j];
	}	
	*str = '\0';
	return str;
}
int main(void)
{
	char str1[33] = {0};
	char str2[33] = {0};	
	my_itoa(07654321, str1, 8);
	my_itoa(0x123abcde, str2, 16);
	printf("str1 = %s\n", str1);
	printf("str2 = %s\n", str2);
	return 0;
}

5.15 数字螺旋方阵的形式如图所示。请将螺旋方阵存放在n×n的二维数组中,并将其打印输出。要求n由程序读入,数字螺旋方阵由程序自动生成。

#include <stdio.h>
#define N 5
int matrix[N][N] = {0};
void left(int i, int j, int num);
void bot(int i, int j, int num);
void right(int i, int j, int num);
void top(int i, int j, int num);
 
int main(){
	int i,j;
	left(0,0,1);
	for(i = 0; i < N; i++){
		for(j = 0; j < N; j++){
			printf("%5d ",matrix[i][j]);
		}
		printf("\n");
	}
	return 0;
}
 
void left(int i, int j, int num){
	int y = i, x = j, number = num;
	if(number>N*N)
		return;
	while(y<N && matrix[y][x]==0){
		matrix[y++][x] = number++;
	}
	bot(y - 1, x + 1, number);
}
void bot(int i, int j, int num){
	int y = i, x = j, number = num;
	if(number>N*N)
		return;
	while(x<N && matrix[y][x]==0){
		matrix[y][x++] = number++;
	}
	right(y - 1, x - 1, number);
}
void right(int i, int j, int num){
	int y = i, x = j, number = num;
	if(number>N*N)
		return;
	while(y>=0 && matrix[y][x]==0){
		matrix[y--][x] = number++;
	}
	top(y + 1, x - 1, number);
}
void top(int i, int j, int num){
	int y = i, x = j, number = num;
	if(number>N*N)
		return;
	while(x>=0 && matrix[y][x]==0){
		matrix[y][x--] = number++;
	}
	left(y + 1, x + 1, number);
}

5.16 有3行文字,找出其中共有多少空格和多少单词(规定单词之间以一个或多个空格作为间隔)。

#include <stdio.h>
#include<string.h>
int word = 0, blank = 0;
void StringBracket(char *str){
	int i,len;
	len = strlen(str);
	flag = 0;//记录上一个是否为空格,是 则单词数+1,否则仍是当前单词
	for(i = 0; i < len; i++){
		if(str[i] != ' '){
			if(flag == 0){//上一个字符为空格
				word++;
				flag = 1;
			}
		}
		else{
			blank++;
			flag = 0;
		}
	}
}
int main(){
	int i,j;
	char a[100];
	
	for(i = 0; i < 3; i++){
		gets(a);
		StringBracket(a);
	}
	printf("空格:%d\n单词:%d\n", blank, word);
	return 0;
}

5.17 有n个学生,每人考m门课。
(1)找出成绩最高的学生的学号和课程号。
(2)找出有不及格课程的学生的学号及其各门课的全部成绩。
(3)求全部学生全部课程总平均分。

#include <stdio.h>
int main()
{
    int score[50][10];  
    int loster[50];//存储不及格学生的各科成绩
	int bloster,n,m,i,j,k=0,sum=0,maxi,maxj;
	//bloster 记录是否及格
	//maxi 记录学生号,maxj 记录课程号
    float avg = 0;
	printf("请输入学生数和课程数:");
    scanf("%d %d",&n,&m);
    maxi=maxj=0;
    for(i=0;i<n;i++)
    {
        bloster = 0;
        for(j=0;j<m;j++)
        {
            scanf("%d",&score[i][j]);
            if(i!=0 && j!=0)
            {
                if(score[maxi][maxj] < score[i][j])
                {
                    maxi = i;
                    maxj = j;
                }
            }
            if(score[i][j] < 60)
                bloster = 1;
            sum += score[i][j];
        }
    }    
    if(bloster)
        loster[k++] = i;
    
    printf("最高成绩的学生号和课程号分别是:%d,%d\n",maxi+1,maxj+1);
    for(i=0;i<k;i++)
    {
        printf("学生号%d的学生有不及格成绩,其各科成绩如下:\n",loster[i]+1);
        for(j=0;j<m;j++)
            printf("%d ",score[loster[i]][j]);
        printf("\n");
    }
    printf("所有课程平均分为:%.1f\n",sum*1.0/(n*m));
	return 0;
}

5.19 有n个国家名,要求按字母先后顺序排列,并按顺序输出。

#include <stdio.h>
#include <string.h>
void sort(char cs[5][20])
{
    int i,j,p;
    char st[20];  // 临时存储字符串
    for(i = 0;i < 5;i++)
    {
        p = i;
        strcpy(st,cs[i]);  //strcpy:将字符串2复制到字符数组1中
        // 找出最大一个的位置
        for(j = i + 1;j < 5;j++)
        {
            if(strcmp(cs[j],st) < 0)  // strcmp:比较字符串
            {
                p = j;  // p记录最小值的位置
                strcpy(st,cs[j]);
            }
        }
        if( p != i)
        {
            strcpy(st,cs[i]);
            strcpy(cs[i],cs[p]);
            strcpy(cs[p],st);
        }
        puts(cs[i]);
    }
}

int main()
{
    char cs[5][20];
    int i;
    printf("输入五个国家的名字:\n");
    for(i = 0;i < 5;i++)
    {
        gets(cs[i]);  //当作一维数组
    }
    printf("\n");
    sort(cs);
    return 0;
}

二、注意

2.1 折半查找

#include<stdio.h>
#include<stdlib.h>
int main(){
	int arr[19] = {2,5,6,7,8,13,15,17,19,21,23,25,26,27,28,35,41,52,63};
	int left = 0, mid, right = 18, x;
	printf("输入要查找的数:");
	scanf("%d", &x);
	while(left <= right){
		mid = (left + right) / 2;
		if(x == arr[mid]){
			printf("该元素的的下标为%d\n", mid);
			exit(0);
		}
		else if(x > arr[mid])
			left = mid + 1;
		else 
			right = mid - 1;
	}
	printf("没有找到该元素!\n");
	
	return 0;
}

2.2 冒泡排序

#include<stdio.h>
int main(){
	int arr[10] = {32,5,6,10,8,13,25,17,9,12};
	int i = 0, j = 0, temp;
	printf("排序前:");
	for(i = 0; i < 10; i++){
		printf("%d ", arr[i]);
	}
	printf("\n");
	for(i = 0; i < 9; i++){
		for(j = 0; j < 9 - i; j++){
			if(arr[j] > arr[j + 1]){
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	printf("排序后:");
	for(i = 0; i < 10; i++){
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

2.3

(1)
char *p;
scanf("%s", p); p未事先分配内存,野指针 

(2)
void func2(char (&p)[10])
{
    printf("%d ", sizeof(p));
}//p是装10个char类型数据的数组的引用,其结果类似于char p[10];10

printf("%d ", sizeof(char &));//1

(3)
sizeof(int)不是函数,值在编译时确定

(4)
&a[0]+1表示元素a[0]的地址加1
&a[0]++包含有对&a[0]的赋值运算,本身是非法的

(5)
int x =5;
const int * const p = &x; //* p =1;×
const int &q=x;  //q++; × &q赋值初始化常量也会报错 这题本身就不成立
int const *next=&x; //next++;√
const int *j=&x; //(*j)++;×

(6)
int a=5, b=3, t;
int &ra = a;
int &rb = b;
t = ra;
ra = rb;
rb = t;//a和b的值被交换, 输出 a = 3, b = 5
对于&a而言,如果前面有类型符(如 int &a),它必然是对引用的声明。 
引用就是变量的别名,对引用的操作就是对变量本身的操作,因此这个程序就是把变量a和b的值互换。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值