谭浩强【C语言程序设计】第六章习题详解


目录

​编辑

1.用筛选法求100 之内的素数。

2. 用选择法对10个整数排序。

3. 求一个3×3的整型矩阵对角线元素之和。

4.有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中。

5.将一个数组中的值按逆序重新存放。例如,原来顺序为 8,6,5,4,1。要求改为1,4,5、6、8。

6. 输出以下的杨辉三角形(要求输出10行)。

​编辑

7.输出“魔方阵”。所谓魔方阵是指这样的方阵,它的每一行、每一列和对角线之和均相等。例如,三阶魔方阵为

​编辑

要求输出1~n²的自然数构成的魔方阵。

8.找出一个二维数组中的鞍点,即该位置上的元素在该行上最大、在该列上最小。也可能没有鞍点。

9.有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出“无此数”。

10.有一篇文章,共有3行文字,每行有 80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数。

11. 输出以下图案:

​编辑

12. 有一行电文,已按下面规律译成密码:A→Z          a→zB→Y          b→yC→X          c→x⋮                  ⋮即第1个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。要求编程序将密码译回原文,并输出密码和原文。

​编辑

13. 编一程序,将两个字符串连接起来,不要用 strcat 函数。

14.编一个程序,将两个字符串 s1和 s2 比较,若s1>s2,输出一个正数;若s1 =s2,输出0;若s1,输出一个负数。不要用>

15.编写一个程序,将字符数组s2 中的全部字符复制到字符数组s1中。不用strcpy函数。复制时, '\0'也要复制过去。'\0'后面的字符不复制。


1.用筛选法求100 之内的素数。

素数:约数为1和该数本身的数字称为素数,即质数。

筛选法:又称筛法,先把N个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。因为希腊人是把数字写在涂蜡的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛”,简称“筛法”。(另一种解释是当时的数写在纸草上,每要划去一个数,就把这个数挖去,寻求质数的工作完毕后,这许多小洞就像一个筛子。)


#include <stdio.h>

int main()
{
	int i = 0;
	int arr[100];
	//向arr数组中填充1~100的数据
	for (i = 0; i < 100; i++)
	{
		arr[i] = i + 1;
	}
	//1不是素数,将1划掉,用0进行填充
	arr[0] = 0;

	for (i = 1; i < 100; i++)
	{
		if (0 == arr[i])
			continue;
		//现在需要使用a[i]去模其之后所有的数据
		for (int j = i + 1; j < 100; j++)
		{
			if (0 != arr[j] && arr[j] % arr[i] == 0)
			{
				arr[j] = 0;
			}
		}
	}

	//输出所有的素数
	for (i = 0; i < 100; i++)
	{
		if (0 != arr[i])
		{
			printf("%d ", arr[i]);
		}
	}
	printf("\n");
	return 0;
}

2. 用选择法对10个整数排序。

#include <stdio.h>

int main()
{
	int i, j, tmp;
	int maxPos;//用来标记最大元素所在的位置
	int arr[10] = { 0 };

	//输入数据
	printf("请输入10个整数:");
	for (i = 0; i < 10; i++)
	{
		scanf("%d", &arr[i]);
	}
	int size = sizeof(arr) / sizeof(arr[0]);

	//将排序前数组中的元素输出
	printf("排序前:");
	for (i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	for (i = 0; i < size - 1; i++)//控制选择总的趟数
	{
		maxPos = i;
		for (j = i + 1; j < size; j++)
		{
			if (arr[j] < arr[maxPos])
			{
				maxPos = j;
			}
		}

		tmp = arr[maxPos];
		arr[maxPos] = arr[i];
		arr[i] = tmp;
	}

	//输出排好序的数组
	printf("排序后:");
	for (i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	return 0;
}

3. 求一个3×3的整型矩阵对角线元素之和。

#include <stdio.h>

int main()
{
	int i, j;
	int sumLR = 0, sumRL = 0;
	int arr[3][3] = { 0 };
	//接收矩阵中的数据
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}
	
	//求左上角到右下角对角线元素之和
	//行下标与列下标是相等的
	for (i = 0; i < 3; i++)
	{
		sumLR += arr[i][i];
	}

	//求右上角到左下角对角线元素之和
	for (i = 0, j = 2; i < 3; i++, j--)
	{
		sumRL += arr[i][j];
	}

	printf("左上角到右下角对角线元素之和:%d\n", sumLR);
	printf("右上角到左下角对角线元素之和:%d\n", sumRL);

	return 0;
}

4.有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中。

#include <stdio.h>

int main()
{
	int key = 0;
	int end = 8;//数组中最后一个元素的下标
	int arr[10] = { 0,1,2,3,5,6,7,8,9 };
	printf("请输入要插入的元素:");
	scanf("%d", &key);

	printf("原数组中的元素:");
	for (int i = 0; i < 9; i++)
	{
		printf("%d ", arr[i]);
	}

	//1.找待插入元素在数组中的位置,从后往前进行查找
	//注意:如果待插入元素比数组中任何一个元素都小
	//      end最终来到-1的位置,如果继续比较,数组将越界而导致代码崩溃
	while (end > 0 && key < arr[end])
	{
		arr[end + 1] = arr[end];
		end--;
	}

	//插入元素
	arr[end + 1] = key;

	printf("\n新数组中的元素:");
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

5.将一个数组中的值按逆序重新存放。例如,原来顺序为 8,6,5,4,1。要求改为1,4,5、6、8。

1.给两个变量分别比较数组中第一个元素与最后一个元素的位置

        begin:标记第一个元素

        end:标记最后一个元素

2.将begin与end位置的元素进行交换

        begin--;

        end++;


#include <stdio.h>

int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int begin = 0;
	int end = sz - 1;
	int temp = 0;
	int i = 0;

	printf("逆序之前数组的元素序列为:");
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	//从左侧找一个数据,然后从右侧找一个数据,交换
	while (begin < end)
	{
		int temp = arr[end];
		arr[end] = arr[begin];
		arr[begin] = temp;

		begin++;
		end--;
	}

	printf("逆序之后数组的元素序列为:");
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	return 0;
}

6. 输出以下的杨辉三角形(要求输出10行)。

通过观察,我们可以发现以下规律:

1,第0列中的所有数据都是1。

2,对角线上的所有元素都是1,并且行下表与列下标是相等的。

3,其它元素:arr[i][j] = arr[i - 1][j] + arr[i -1][j - 1]。


#include <stdio.h>

int main()
{
	//保存杨辉三角中的数据
	int arr[10][10];
	int i, j;
	for (i = 0; i < 10; i++)
	{
		//给杨辉三角中的每一行进行赋值
		for (j = 0; j <= i; j++)
		{
			//第0行与对角线上的数据都是1
			if (0 == j || i == j)
			{
				arr[i][j] = 1;
			}
			else
			{
				//其它位置
				arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
			}
		}
	}
	//打印
	for (i = 0; i < 10; i++)
	{
		for (j = 0; j <= i; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

7.输出“魔方阵”。所谓魔方阵是指这样的方阵,它的每一行、每一列和对角线之和均相等。例如,三阶魔方阵为


要求输出1~n²的自然数构成的魔方阵。

魔方阵分为:

  • 奇魔方阵,即n为奇数
  • 偶魔方阵,即n = 4*m,其中m为1,2,3,4......
  • 单偶魔方阵,即n = 4*m+2,其中m为1,2,3,4......

本题我们只分析奇魔方阵,对于偶魔方阵和单偶魔方阵大家如果感兴趣可以去网上了解一下。


#include <stdio.h>

int main()
{
	int arr[100][100] = { 0 };
	int n;//表示魔方阵的阶数
	int i, j;
	int row = 0, col = 0;//表示当前元素存放的位置
	int prevRow, preCol;//前一个元素所在的行与列
	while (1)
	{
		printf("请输入魔方阵的阶数,阶数为3~100之内的奇数:");
		scanf("%d", &n);
		if (0 != n % 2 && (n >= 3 && n < 100))
		{
			break;
		}
	}

	//放置1:在第0行最中间的位置
	col = n / 2;
	arr[row][col] = 1;

	//对于剩余的 n^2-1个元素,按照以下规则来存放
	for (i = 2; i <= n * n; i++)
	{
		//下一个元素存放在当前元素上一行下一列
		row--;
		col++;

		if (row < 0)
		{
			row = n - 1;
		}
		if (col >= n)
		{
			col = 0;
		}
		if (0 != arr[row][col])
		{
			//row,col该位置已经有元素 --- 前一个元素当前列的下一行
			row = prevRow + 1;
			col = preCol;
		}
		arr[row][col] = i;
		prevRow = row;
		preCol = col;
	}
	
	//输出魔方阵
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
		{
			printf("%3d", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

8.找出一个二维数组中的鞍点,即该位置上的元素在该行上最大、在该列上最小。也可能没有鞍点。

二维数组不考虑数据重复的情况,如果鞍点存在,该数据一定是唯一的,当然,二维数组中也可能不存在鞍点。

  1. 找该行上最大的元素 --->max,并记录该元素所在的列号pos
  2. 确认该元素是否为该列上最小的元素。如果是,则说明鞍点已经找到了,直接打印鞍点位置即可;如果否,则在下一行找最大的元素,并确认是否为该列上最小的元素。

#include <stdio.h>
#define M 3
#define N 4

int main()
{
	int arr[M][N];
	int i, j;
	int pos = 0, max;
	int flag = 0;
	printf("请输入%d行%d列的二维数组:\n", M, N);
	for (i = 0; i < M; i++)
	{
		for (j = 0; j < N; j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}

	//找鞍点
	for (i = 0; i < M; i++)
	{
		//找该行最大的元素,并记录列号
		max = arr[i][0];
		for (j = 1; j < N; j++)
		{
			if (arr[i][j] > max)
			{
				max = arr[i][j];
				pos = j;
			}
		}
		//确认该元素是否为该列上最小的元素
		for (j = 0; j < M; j++)
		{
			if (arr[j][pos] < max)
			{
				break;
			}
		}
		//如果pos列没有发现比max小的元素,说明max是pos列最小的元素
		if (j == M)
		{
			printf("鞍点为%d行%d列:%d\n", i, pos, arr[i][pos]);
			flag = 1;
			break;
		}
	}
	if (0 == flag)
	{
		printf("没有鞍点\n");
	}

	return 0;
}

9.有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出“无此数”。

折半查找又叫二分查找,查找的前提是数组中的元素必须有序,假设区间使用[left, right)标记,待查找元素为key,具体查找的方式如下:当区间[left, right)有效时循环进行以下操作:

  1. 找到[left, right)区间中间位置。
  2. 如果key等于中间位置元素,则找到,返回该元素在数组中的下标。
  3. 如果key小于中间位置元素,则在数组的右半侧继续二分查找。
  4. 如果key大于中间位置元素,则在数组的左半侧继续二分查找。
  5. 如果循环结束还没有找到,则不存在该元素。

#include <stdio.h>

int main()
{
	int arr[] = { 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int left, right;
	int mid;
	int key;

	//区间采用左闭右开
	left = 0;
	right = sz;
	printf("请输入要查找的数据:");
	scanf("%d", &key);

	while (left < right)
	{
		//找中间位置
		mid = (left + right) / 2;

		//与中间位置的数据进行比较
		//1,如果相等,表示找到了
		if (key == arr[mid])
		{
			printf("找到了,该元素的下标为:%d\n", mid);
			break;
		}
		//2,如果小于中间位置元素,则在右半部分查找
		else if (key < arr[mid])
		{
			left = mid + 1;
		}
		//3,如果大于中间位置元素,则在左半部分查找
		else
		{
			right = mid;
		}
	}
	//循环结束,没有找到,则不存在该元素
	if (left == right)
	{
		printf("无此数\n");
	}

	return 0;
}

10.有一篇文章,共有3行文字,每行有 80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数。


#include <stdio.h>

int main()
{
	char arr[3][80] = { 0 };
	int i = 0, j = 0;
	int upper = 0, low = 0, digit = 0, space = 0, other = 0;
	//1,先接受3行文本
	for (i = 0; i < 3; i++)
	{
		gets(arr[i]);
	}

	//2,统计
	for (i = 0; i < 3; i++)
	{
		//只需在该行中统计到\0的位置即可 --- \0为字符串的结尾标记
		for (j = 0; arr[i][j] != '\0'; j++)
		{
			//大写字母
			if (arr[i][j] >= 'A' && arr[i][j] <= 'Z')
			{
				upper++;
			}
			//小写字母
			else if (arr[i][j] >= 'a' && arr[i][j] <= 'z')
			{
				low++;
			}
			//数字
			else if (arr[i][j] >= '0' && arr[i][j] <= '9')
			{
				digit++;
			}
			//空格
			else if (arr[i][j] == ' ')
			{
				space++;
			}
			//其它字符
			else
			{
				other++;
			}
		}
	}

	printf("大写字母:%d个\n", upper);
	printf("小写字母:%d个\n", low);
	printf("数字:%d个\n", digit);
	printf("空格:%d个\n", space);
	printf("其它字符:%d个\n", other);

	return 0;
}

11. 输出以下图案:

#include <stdio.h>

int main()
{
	int i, j, k;
	for (i = 0; i < 5; i++)
	{
		//打印空格
		for (j = 0; j < i * 2; j++)
		{
			printf(" ");
		}
		//打印*
		for (k = 0; k < 5; k++)
		{
			printf("* ");
		}
		printf("\n");
	}
	return 0;
}

12. 有一行电文,已按下面规律译成密码:
A→Z          a→z
B→Y          b→y
C→X          c→x
⋮                  ⋮
即第1个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。要求编程序将密码译回原文,并输出密码和原文。


#include <stdio.h>

int main()
{
	char sz[100] = { 0 };//假设暗文长度为100个字符
	int i;

	//获取暗文
	printf("请输入密码:");
	gets(sz);

	//解码:只对字符进行解码
	for (i = 0; sz[i] != '\0'; i++)
	{
		if (sz[i] >= 'A' && sz[i] <= 'Z')
		{
			sz[i] = 'A' + 26 - (sz[i] - 'A') - 1;
		}
		if (sz[i] >= 'a' && sz[i] <= 'z')
		{
			sz[i] = 'a' + 26 - (sz[i] - 'a') - 1;
		}
	}
	printf("该密码译成原文后为:%s\n", sz);
	return 0;
}

13. 编一程序,将两个字符串连接起来,不要用 strcat 函数。

  • 拼接原理:将s2中的每个字符逐个拷贝到s1的末尾。
  • 注意:s1中必须要有足够的空间来容纳s2中的元素。
    #include <stdio.h>
    
    int main()
    {
    	int i = 0, j = 0;
    	char dst[100] = { 0 };
    	char src[50] = { 0 };
    
    	printf("请输入目标字符串:");
    	gets(dst);
    
    	printf("请输入源字符串:");
    	gets(src);
    
    	//1.找到目标字符串的末尾
    	while (dst[i] != '\0')
    	{
    		i++;
    	}
    	//2.将源字符串中的每个字符逐个拷贝到目标字符串的末尾
    	while (src[j] != '\0')
    	{
    		dst[i] = src[j];
    		i++;
    		j++;
    	}
    	//注意:最后还需拷贝 '\0'
    	dst[i] = '\0';
    
    	printf("连接后的字符串为:%s\n", dst);
    	return 0;
    }

14.编一个程序,将两个字符串 s1和 s2 比较,若s1>s2,输出一个正数;若s1 =s2,输出0;若s1<s2,输出一个负数。不要用 strcmp函数。两个字符串用 gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相应字符的 ASCII码的差值。例如,"A"与"C"相比,由于'''A''<''C'',,应输出负数,同时由于'A'与'C'的 ASII码差值为 2,因此应输出“-2”。同理: "And"和"Aid"比较,根据第2个字符比较结果,"n"比"i"大5,因此应输出“5”。

#include <stdio.h>

int main()
{
	char s1[50] = { 0 };
	char s2[50] = { 0 };
	int i = 0;
	int ret;

	printf("请输入s1:");
	gets(s1);

	printf("请输入s2:");
	gets(s2);

	do
	{
		ret = s1[i] - s2[i];
		if (0 != ret)
		{
			break;
		}
		i++;
	} while ('\0' != s1[i] && '\0' != s2[i]);

	printf("%d\n", ret);

	return 0;
}

15.编写一个程序,将字符数组s2 中的全部字符复制到字符数组s1中。不用strcpy函数。复制时, '\0'也要复制过去。'\0'后面的字符不复制。

#include <stdio.h>

int main()
{
	char s1[100] = { 0 };
	char s2[50] = { 0 };
	int i = 0;

	printf("请输入要拷贝的字符串:");
	gets(s2);

	//1.先将s2[i]的元素拷贝到s1[i]
	//2.s1[i]中的字符作为判断条件
	//3.i++
	//while (s1[i] = s2[i++]);

	//拷贝方式:将s2中的每个字符逐个拷贝到s1中
	while ('\0' != s2[i])
	{
		s1[i] = s2[i];
		i++;
	}
	s1[i] = '\0';

	printf("拷贝后的结果为:%s\n", s1);

	return 0;
}

  • 64
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 41
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南风与鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值