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



1.输入 3个整数,按由小到大的顺序输出。

#include <stdio.h>

int main()
{
	int num1, num2, num3;
	printf("请输入3个整数:>");
	scanf("%d%d%d", &num1, &num2, &num3);

	int* pmin = &num1;
	int* pmid = &num2;
	int* pmax = &num3;

	if (*pmin > *pmid)
	{
		int* tmp = pmin;
		pmin = pmid;
		pmid = tmp;
	}
	if (*pmin > *pmax)
	{
		int* tmp = pmin;
		pmin = pmax;
		pmax = tmp;
	}
	if (*pmid > *pmax)
	{
		int* tmp = pmid;
		pmid = pmax;
		pmax = tmp;
	}
	printf("由小到大为:%d %d %d\n", *pmin, *pmid, *pmax);

	return 0;
}

2.输入 3个字符串,按由小到大的顺序输出。

#include <stdio.h>
#include <string.h>

int main()
{
	char str1[32], str2[32], str3[32];
	printf("请输入3个字符串:>\n");
	scanf("%s", str1);
	scanf("%s", str2);
	scanf("%s", str3);

	char* pmin = str1;
	char* pmid = str2;
	char* pmax = str3;

	if (strcmp(pmin, pmid) > 0)
	{
		char* tmp = pmin;
		pmin = pmid;
		pmid = tmp;
	}
	if (strcmp(pmin, pmax) > 0)
	{
		char* tmp = pmin;
		pmin = pmax;
		pmax = tmp;
	}
	if (strcmp(pmid, pmax) > 0)
	{
		char* tmp = pmid;
		pmid = pmax;
		pmax = tmp;
	}
	printf("由小到大的顺序为:\n%s\n%s\n%s\n", pmin, pmid, pmax);

	return 0;
}

3.输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。写3个函数: ①输入 10个数;②进行处理;③输出 10 个数。

#include <stdio.h>

void Init(int* arr, int sz)
{
	printf("请输入10个整数:>\n");
	for (int i = 0; i < sz; i++)
	{
		//arr是数组首元素地址,+i就表示数组第i个元素的地址
		scanf("%d", arr + i);
	}
	printf("\n");
}

void Handler(int* arr, int sz)
{
	//将pmin和pmax都初始化为数组的首元素地址
	int* pmin = arr, * pmax = arr;
	for (int i = 0; i < sz; i++)
	{
		if (*pmin > *(arr + i))
		{
			//若arr+i位置的数据比pmin位置的数据小,则把arr+i这个地址赋值给pmin
			pmin = arr + i;
		}
		if (*pmax < *(arr + i))
		{
			//若arr+i位置的数据比pmin位置的数据大,则把arr+i这个地址赋值给pmax
			pmax = arr + i;
		}
	}
	if (pmax == arr)
	{
		pmax = pmin;
	}
	int tmp = *arr; *arr = *pmin; *pmin = tmp;
	tmp = *(arr + sz - 1); *(arr + sz - 1) = *pmax; *pmax = tmp;
}

void Print(int* arr, int sz)
{
	printf("对换后的10个整数为:\n");
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));
	}
	printf("\n");
}

int main()
{
	int arr[10];

	Init(arr, 10);
	Handler(arr, 10);
	Print(arr, 10);

	return 0;
}

4. 有 n个整数,使前面各数顺序向后移 m个位置,最后 m个数变成最前面 m个数,见图 8.43。写一函数实现以上功能,在主函数中输入 n个整数和输出调整后的n个数。

#include <stdio.h>

void reverse(int* arr, int n, int m)
{
	for (int i = 0; i < m; i++)
	{
		int tmp = *(arr + n - 1);
		for (int j = n - 1; j > 0; j--)
		{
			*(arr + j) = *(arr + j - 1);
		}
		*arr = tmp;
	}
}

int main()
{
	int n = 0, m = 0;
	int arr[32];

	printf("请确定需要输入几个数字:");
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", arr + i);
	}

	printf("请输入要向后移动的位数:");
	scanf("%d", &m);
	reverse(arr, n, m);
	for (int i = 0; i < n; i++)
	{
		printf("%d ", *(arr + i));
	}
	
	return 0;
}

5.有 n个人围成一圈,顺序排号。从第1个人开始报数
(从 1到3 报数),凡报到3 的人退出圈子,问最后留下的是原来第几号的那位。

#include <stdio.h>

int main()
{
	int total;//记录总人数
	int arr[128];//记录每个人所报的数
	int digit = 1;//记录当前要喊的数字
	printf("请输入总人数:");
	scanf("%d", &total);
	int remain = total;//记录剩余人数,剩余人数刚开始应等于总人数

	while (remain > 1)//循环至最终只剩一个人
	{
		for (int i = 1; i <= total; i++)
		{
			if (*(arr + i) == 3)//第i个人是3,代表这个人已经被淘汰了
				continue;
			*(arr + i) = digit;
			if (digit == 3)
			{
				digit = 0;//报数报道3则归0,因为下边有++操作
				remain--;//剩余人数-1
			}
			digit++;
		}
	}
	for (int i = 1; i <= total; i++)
	{
		if (*(arr + i) != 3)
			printf("最后留下的是原来的第%d位\n", i);
	}
	return 0;
}

6.写一函数,求一个字符串的长度。在 main函数中输入字符串,并输出其长度。

#include <stdio.h>
#include <assert.h>

int my_strlen(char* str)
{
	assert(str);
	char* ptr = str;
	while (*ptr != '\0')
	{
		ptr++;
	}
	return ptr - str;
}

int main()
{
	char str[128] = { 0 };
	printf("请输入一个字符串:");
	gets(str);

	int ret = my_strlen(str);
	printf("长度为:%d\n", ret);

	return 0;
}

7.有一字符串,包含 n个字符。写一函数,将此字符串中从第 m个字符开始的全部字符复制成为另一个字符串。

#include <stdio.h>

void mystrcpy(char* dst, char* src, int m)
{
	char* ps = src + m - 1;
	char* pd = dst;

	while (*ps != '\0')
	{
		*pd = *ps;
		ps++;
		pd++;
	}
	*pd = '\0';

}

int main()
{
	char src[32];
	printf("请输入一个字符串:");
    //从键盘获取一行数据,最大不超过30字节,放到str指向的空间中
	fgets(src, 30, stdin);

	int m = 0;
	printf("请输入要从第多少个字符开始拷贝:");
	scanf("%d", &m);

	char dst[32];
	mystrcpy(dst, src, m);
	printf("拷贝后的字符串为:%s\n", dst);

	return 0;
}

8.输入一行文字,找出其中大写字母、小写字母、空格、数字以及其他字符各有多少。

#include <stdio.h>
#include <string.h>

int main()
{
	char str[128];
	printf("请输入一行文字:>");
	fgets(str, 125, stdin);//fgets获取一行数据的时候,末尾是有个换行字符\0的
	*(str + strlen(str) - 1) = '\0';

	char* ptr = str;
	int upper = 0, lower = 0, digit = 0, space = 0, other = 0;
	while (*ptr != '\0')
	{
		if (*ptr >= 'A' && *ptr <= 'Z')
		{
			upper++;
		}
		else if (*ptr >= 'a' && *ptr <= 'z')
		{
			lower++;
		}
		else if (*ptr >= '0' && *ptr <= '9')
		{
			digit++;
		}
		else if (*ptr == ' ')
		{
			space++;
		}
		else 
		{
			other++;
		}
		ptr++;
	}
	printf("大写字母:%d\n小写字母:%d\n空格:%d\n数字:%d\n其他字符:%d\n",
		upper, lower, space, digit, other);

	return 0;
}

9.写一函数,将一个3×3的整型矩阵转置。

#include <stdio.h>

void reverse(int(*arr)[3])
{
	for (int i = 0; i < 3; i++)
	{
		for (int j = i; j < 3; j++)
		{
			int tmp = *(*(arr + i) + j);
			*(*(arr + i) + j) = *(*(arr + j) + i);
			*(*(arr + j) + i) = tmp;
		}
	}
}

int main()
{
	int arr[3][3];
	printf("请输入一个3x3的整形矩阵:\n");
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			scanf("%d", *(arr + i) + j);
		}
	}

	reverse(arr);
	printf("将矩阵转置后为:\n");
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d ", *(*(arr + i) + j));
		}
		printf("\n");
	}

	return 0;
}

10.将一个5×5的矩阵中最大的元素放在中心,4个角分别放4 个最小的元素(顺序为从左到右,从上到下依次从小到大存放),写一函数实现之。用 main 函数调用。

#include <stdio.h>

void change(int (*arr)[5], int row, int col)
{
	//1.找最大的元素并放在中间
	int* mid = *(arr + row / 2) + (col / 2);
	int* max = *(arr + 0) + 0;//假设[0, 0]位置就是最大值
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			//如果第i行第j列的元素比当前位置大,则max指向新的最大值位置
			if (*max < *(*(arr + i) + j))
			{
				max = *(arr + i) + j;
			}
		}
	}
	int tmp = *mid; *mid = *max; *max = tmp;
	//2.找出4个最小的数并和4个角落进行交换
	//将4个角的地址保存起来
	int* corner[4] = { *(arr + 0) + 0, *(arr + 0) + col - 1, *(arr + row - 1) + 0, *(arr + row - 1) + col - 1 };
	//找最小值,需要找4次
	for (int i = 0; i < 4; i++)
	{
		int* min = mid;//假设最小值位置为中间值的位置
		for (int m = 0; m < row; m++)
		{
			for (int n = 0; n < col; n++)
			{
				int k;
				for (k = 0; k < i; k++)//找第0个最小数的时候,i是0,意味着没有角落被置换
				{
					if (*(arr + m) + n == *(corner + k))
						break;
				}
				if (k != i)
					continue;
				if (*min > *(*(arr + m) + n))
					min = *(arr + m) + n;
			}
		}
		int tmp = *min; *min = **(corner + i); **(corner + i) = tmp;
	}
}

int main()
{
	int arr[5][5];
	printf("请输入一个5x5的整形矩阵:\n");
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			scanf("%d", *(arr + i) + j);
		}
	}

	change(arr, 5, 5);
	printf("--------------------------\n");
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%2d ", *(*(arr + i) + j));
		}
		printf("\n");
	}
	return 0;
}

11.在主函数中输入10个等长的字符串。用另一函数对它们排序。然后在主函数输出这10个已排好序的字符串。

#include <stdio.h>
#include <string.h>

void str_sort(char (*arr)[32], int row)
{
	for (int i = 0; i < 10 - 1; i++)
	{
		for (int j = 0; j < 10 - 1 - i; j++)
		{
			if (strcmp(*(arr + j), *(arr + j + 1)) > 0)
			{
				char tmp[32];
				strcpy(tmp, *(arr + j));
				strcpy(*(arr + j), *(arr + j + 1));
				strcpy(*(arr + j + 1), tmp);
			}
		}
	}
}

int main()
{
	char arr[10][32];
	printf("请输入10个字符串:\n");
	for (int i = 0; i < 10; i++)
	{
		scanf("%s", arr + i);
	}
	str_sort(arr, 10);
	printf("------------------\n");
	for (int i = 0; i < 10; i++)
	{
		printf("%s\n", *(arr + i));
	}
	return 0;
}

12.用指针数组处理上一题目,字符串不等长。

#include <stdio.h>
#include <string.h>

void str_sort(char** str, int row)
{
	for (int i = 0; i < 10 - 1; i++)
	{
		for (int j = 0; j < 10 - 1 - i; j++)
		{
			if (strcmp(*(str + j), *(str + j + 1)))
			{
				char* tmp = *(str + j);
				*(str + j) = *(str + j + 1);
				*(str + j + 1) = tmp;
			}
		}
	}
}

int main()
{
	char arr[10][32];
	char* parr[10] = { 0 };
	printf("请输入10个字符串:\n");
	for (int i = 0; i < 10; i++)
	{
		*(parr + i) = *(arr + i);
		scanf("%s", *(parr + i));
	}
	str_sort(parr, 10);
	printf("---------------\n");
	for (int i = 0; i < 10; i++)
	{
		printf("%s\n", *(arr + i));
	}
	printf("---------------\n");
	for (int i = 0; i < 10; i++)
	{
		printf("%s\n", *(parr + i));
	}
	return 0;
}

13.写一个用矩形法求定积分的通用函数,分别求
∫sinxdx, ∫cosxdx, ∫e^xdx
说明: sin, cos, exp函数已在系统的数学函数库中,程序开头要用# include<math. h>。

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

double integral(double num1, double num2, int count, double (*handler)(double))
{
	double dx = (num2 - num1) / count;
	double res = 0;
	for (int i = 0; i < count; i++)
	{
		double dh = handler(num1 + dx * i);
		res += dx * dh;
	}
	return res;
}

int main()
{
	printf("请输入积分区间[num1, num2]:");
	double num1, num2;
	scanf("%lf%lf", &num1, &num2);
	printf("请输入分割数量:");
	int count;
	scanf("%d", &count);
	printf("请输入被积分函数<1-sin, 2-cos, 3-exp>:");
	int choice;
	scanf("%d", &choice);

	double (*var[4])(double) = { NULL, sin, cos, exp };
	double res = integral(num1, num2, count, var[choice]);
	printf("定积分结果:%lf\n", res);
	return 0;
}

14. 将 n个数按输入时顺序的逆序排列,用函数实现。

#include <stdio.h>

void reverse(int* arr, int sz)
{
	int* left = arr;
	int* right = arr + sz - 1;
	while (left < right)
	{
		int tmp = *left;
		*left = *right;
		*right = tmp;

		left++;
		right--;
	}
}

int main()
{
	int arr[128];
	int n;
	printf("请输入数据的个数:>");
	scanf("%d", &n);
	printf("请输入数据:>");
	for (int i = 0; i < n; i++)
	{
		scanf("%d", arr + i);
	}
	reverse(arr, n);
	printf("逆序排列后为:");
	for (int i = 0; i < n; i++)
	{
		printf("%d ", *(arr + i));
	}
	return 0;
}

15.有一个班4 个学生,5门课程。①求第1门课程的平均分;②找出有两门以上课程不及格的学生,输出他们的学号和全部课程成绩及平均成绩;③找出平均成绩在 90分以上或全部课程成绩在85分以上的学生。分别编3个函数实现以上3个要求。

#include <stdio.h>

float course_avg(float(*arr)[5], int row, int col)
{
	float sum = 0;
	for (int i = 0; i < row; i++)
	{
		sum += *(*(arr + i) + 0);
	}
	return (sum / row);
}

float stu_avg(float* score, int sz)
{
	float sum = 0;
	for (int i = 0; i < sz; i++)
	{
		sum += *(score + i);
	}
	return (sum / sz);
}

void fail(float(*arr)[5], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		int fail_count = 0;
		for (int j = 0; j < col; j++)
		{
			if (*(*(arr +i) + j) < 60)
			{
				fail_count++;
			}
		}
		if (fail_count > 2)
		{
			printf("%d号学生有两门课以上成绩不及格。\n", i);
			printf("这个学生的平均成绩是:%.2f\n", stu_avg(*(arr + i), col));
		}
	}
}

void print_stu_score(float* score, int sz)
{
	printf("此学生的所有成绩如下:");
	for (int i = 0; i < sz; i++)
	{
		printf("%.2f ", *(score + i));
	}
	printf("\n");
}

void excellent(float(*arr)[5], int row, int col)
{
	for (int i = 0; i < row; i++)
	{
		int course_count = 0;
		float sum = 0; 
		for (int j = 0; j < col; j++)
		{
			if (*(*(arr + i) + j) > 85)
			{
				course_count++;
			}
			sum += *(*(arr + i) + j);
		}
		if ((sum / col) > 90 || course_count == col)
		{
			printf("%d号学生是好学生!\n", i);
			print_stu_score(*(arr + i), col);
		}
	}
}

int main()
{
	float score[4][5] = {
		{32, 48, 56, 36, 75},
		{98, 70, 99, 100, 97},
		{87, 88, 89, 86, 87},
		{68, 69, 75, 78, 80}
	};

	float cour_avg_score = course_avg(score, 4, 5);
	printf("第1门课的平均分:%.2f\n", cour_avg_score);
	fail(score, 4, 5);
	excellent(score, 4, 5);

	return 0;
}

16.输入一个字符串,内有数字和非数字字符,例如:
A123×456 17960?302tab5876
将其中连续的数字作为一个整数,依次存放到一数组 a中。例如,123 放在 a[0],456 放在a[1]⋯⋯统计共有多少个整数,并输出这些数。

#include <stdio.h>

int main()
{
	char str[1024] = { 0 };
	fgets(str, 1023, stdin);

	char res[128][32];
	int row = 0, col = 0;
	char* ptr = str;
	while (*ptr != '\0')
	{
		if (*ptr >= '0' && *ptr <= '9')
		{
			while (*ptr >= '0' && *ptr != '\0' && *ptr <= '9')
			{
				*(*(res + row) + col) = *ptr;
				col++;
				ptr++;
			}
			*(*(res + row) + col) = '\0';
			row++;
			col = 0;
			if (*ptr == '\0')
				break;
		}
		ptr++;
	}
	printf("共找到%d个数字\n", row);
	for (int i = 0; i < row; i++)
	{
		printf("%s\n", *(res + i));
	}
	return 0;
}

17.写一函数,实现两个字符串的比较。即自己写一个 strcmp函数,函数原型为
int strcmp(char *p1, char *p2);
设 p1指向字符串 s1, p2指向字符串 s2。要求当s1=s2 时,返回值为0;若sl≠s2,返回它们二者第1个不同字符的 ASCII码差值(如"BOY"与"BAD",第2个字母不同,O 与 A 之差为79-65=14)。如果s1>s2,则输出正值;如果s1<s2,则输出负值。

#include <stdio.h>
int my_strcmp(char* p1, char* p2)
{
	while (*p1 != '\0' && *p2 != '\0' && *p1 == *p2)
	{
		p1++;
		p2++;
	}
	return *p1 - *p2;
}

int main()
{
	char str1[128];
	char str2[128];
	printf("请输入要比较的两个字符串:>\n");
	scanf("%s%s", str1, str2);

	int ret = my_strcmp(str1, str2);
	printf("%d\n", ret);

	return 0;
}

18.编一程序,输入月份号,输出该月的英文月名。例如,输入 3,则输出"March", 要求用指针数组处理。

#include <stdio.h>

int main()
{
	char* month[13] = {
		NULL,
		"January",
		"February",
		"March",
		"April",
		"May",
		"June",
		"July",
		"August",
		"September",
		"October",
		"November",
		"December"
	};
	int input;
	printf("请输入月份:>");
	scanf("%d", &input);
	if (input < 1 || input > 12)
	{
		printf("输入有误!\n");
		return -1;
	}
	printf("%s\n", *(month + input));

	return 0;
}

19.(1) 编写一个函数 new,对 n个字符开辟连续的存储空间,此函数应返回一个指针(地址),指向字符串开始的空间。new(n)表示分配 n个字节的内存空间。

(2)写一函数free,将前面用 new 函数占用的空间释放。free(p)表示将 p(地址)指向的单元以后的内存段释放。

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

char* my_news(int n)
{
	char* p = (char*)malloc(n);
	return p;
}

void my_free(char* p)
{
	free(p);
	p = NULL;
}

int main()
{
	char* data = my_news(32);
	strcpy(data, "hello world!");
	printf("%s\n", data);

	my_free(data);
	printf("%s\n", data);

	return 0;
}

20.用指向指针的指针的方法对5个字符串排序并输出。

#include <stdio.h>
#include <string.h>

void str_sort(char** ppstr, int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (strcmp(*(ppstr + j), *(ppstr + j + 1)) > 0)
			{
				char tmp[32];
				strcpy(tmp, *(ppstr + j));
				strcpy(*(ppstr + j), *(ppstr + j + 1));
				strcpy(*(ppstr + j + 1),tmp);
			}
		}
	}
}

int main()
{
	char str[5][32];
	printf("请输入5个字符串:>\n");
	for (int i = 0; i < 5; i++)
	{
		scanf("%s", str + i);
	}
	char* pstr[5];
	for (int i = 0; i < 5; i++)
	{
		pstr[i] = *(str + i) + 0;
	}
	str_sort(pstr, 5);
	printf("排序后为:\n");
	for (int i = 0; i < 5; i++)
	{
		printf("%s ", *(str + i));
	}
	return 0;
}

21.用指向指针的指针的方法对n个整数排序并输出。要求将排序单独写成一个函数。n个整数在主函数中输入,最后在主函数中输出。

#include <stdio.h>

void int_sort(int** pparr, int sz)
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (**(pparr + j) > **(pparr + j + 1))
			{
				int tmp = **(pparr + j);
				**(pparr + j) = **(pparr + j + 1);
				**(pparr + j + 1) = tmp;
			}
		}
	}
}

int main()
{
	int arr[128] = { 0 };
	int n;
	printf("请确定需要输入的数字个数:>");
	scanf("%d", &n);
	printf("请输入数字:>");
	for (int i = 0; i < n; i++)
	{
		scanf("%d", arr + i);
	}

	int* parr[128];
	for (int i = 0; i < n; i++)
	{
		parr[i] = arr + i;
	}
	int_sort(parr, n);
	printf("排序后为:");
	for (int i = 0; i < n; i++)
	{
		printf("%d ", *(arr + i));
	}
	return 0;
}

  • 52
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 30
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

南风与鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值