《C Primer Plus》第 9 章复习题和编程练习

目录

一、复习题

1. 实际参数和形式参数的区别是什么?

答:实际参数是主调函数传给被调函数的具体的值,而形式参数是被调函数的私有变量。

2. 根据下面各函数的描述,分别编写它们的 ANSIC 函数头。注意,只需写出函数头,不用写函数体。
a. donut() 接受一个 int 类型的参数,打印若干(参数指定数目)个 0
b. gear() 接受两个 int 类型的参数,返回 int 类型的值
c. guess() 不接受参数,返回一个 int 类型的值
d. stuff_it() 接受一个 double 类型的值和 double 类型的变量的地址,把第一个值存储在指定位置

答:
a. void donut(int n);
b. int gear(int i1, int i2);
c. int guess();
d. void stuff_it(double d, double *pd);

3. 根据下面各函数的描述,分别编写它们的 ANSIC 函数头。注意,只需写出函数头,不用写函数体。
a. n_to_char() 接受一个 int 类型的参数,返回一个 char 类型的值
b. digit() 接受一个 double 类型的参数和一个 int 类型的参数,返回一个 int 类型的值
c. which() 接受两个可存储 double 类型变量的地址,返回一个 double 类型的地址
d. random() 不接受参数,返回一个 int 类型的值

答:
a. char n_to_char(int i);
b. int digit(double d, int i);
c. double* which(double *pd1, double *pd2);
d. int random();

4. 设计一个函数,返回两个整数之和。

答:
程序设计分析: 函数声明、函数调用和函数体。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
int sum(int i1, int i2);

int main()
{
	// 操作
	printf("%d", sum(1, 2));
	return 0;
}

// 函数定义
int sum(int i1, int i2)
{
	return i1 + i2;
}

5. 如果把复习题 4 改成返回两个 double 类型的值之和,应如何修改?

答:
程序设计分析: 分别修改函数声明、函数定义,函数调用的时候使用 double值。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
double sum(double d1, double d2);

int main()
{
	// 操作
	printf("%d", sum(1.1, 2.2));
	return 0;
}

// 函数定义
double sum(double d1, double d2)
{
	return d1 + d2;
}

6. 设计一个名为 alter() 的函数,接受两个 int 类型的变量 x 和 y,把它们的值分别改成两个变量之和和两个变量之差。

答:
程序设计分析: 通过函数调用修改主调函数的值,需要传地址。所以 alter() 函数接受两个指向 int 的指针。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
void alter(int *x, int *y);

int main()
{
	int x = 1, y = 2;

	alter(&x, &y);

	printf("x = %d, y = %d", x, y);

	return 0;
}

// 函数定义
void alter(int *x, int *y)
{
	int temp = *x - *y;
	*x = *x + *y;
	*y = temp;
}

7. 下面的函数定义是否正确?

c 复制代码
void salami()
{
	int num, count;
	for (count = 1; count <= num; num++)
		printf("O salami mio!\n");
}

答:错误,该函数中没有对变量 num 进行初始化,其值是不确定的,导致程序无法正常运行。

8. 编写一个函数,返回 3 个整数中的最大值。

答:
程序设计分析: 先假定一个数是最大值,然后剩下两个数依次比较选出最大值。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
int max_3i(int a, int b, int c);

int main()
{
	printf("%d", max_3i(101, 111, 110));

	return 0;
}

// 函数定义
int max_3i(int a, int b, int c)
{
	int max = a;

	if (b > max)
		max = b;
	if (c > max)
		max = c;

	return max;
}

二、编程练习

1. 设计一个函数 min(x, y),返回两个 double 值中的较小值。在一个简单的驱动程序中测试该函数。

答:
程序设计分析: 该函数返回 double 值,需要两个 double 参数

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
double min(double a, double b);

int main()
{
	double a = 1.1;
	double b = 1.2;

	printf("较小的值为:%lf\n", min(a, b));

	return 0;
}

// 函数定义
double min(double a, double b)
{
	return a > b ? b : a;
}

2. 设计一个函数 chline(ch, i, j),打印指定字符 j 行 i 列,在一个简单的驱动程序中测试该程序。

答:
程序设计分析: 该函数没有返回值,需要一个 char、两个 int 参数。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
void chline(char ch, int row, int col);

int main()
{
	chline('*', 3, 4);

	return 0;
}

// 函数定义 
void chline(char ch, int row, int col)
{
	int i;
	for (i = 0; i < row; ++i)
	{
		int j;
		for (j = 0; j < col; ++j)
		{
			putchar(ch);
		}
		// 下一行
		putchar('\n');
	}
}

3. 编写一个函数,接受 3 个参数 ------ 一个字符和两个整数。字符参数是待打印的字符,第 1 个整数指定 1 行中打印字符的次数,第 2 个整数指定打印指定字符的行数。同时,编写一个调用该函数的程序。

答:
程序设计分析: 该函数没有返回值,接受一个 char 和 两个 int 类型的参数。实际上就是上一题把行和列换了一下。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
void chline(char ch, int col, int row);

int main()
{
	chline('*', 3, 4);

	return 0;
}

// 函数定义 
void chline(char ch, int col, int row)
{
	int i;
	for (i = 0; i < row; ++i)
	{
		int j;
		for (j = 0; j < col; ++j)
		{
			putchar(ch);
		}
		// 下一行
		putchar('\n');
	}
}

4. 两数的调和平均数这样计算:先求两数的倒数,然后计算两个倒数的平均值,最后计算结果的倒数。编写一个函数,接受两个 double 类型的参数,返回这两个参数的调和平均数。

答:
程序设计分析: 该函数接受两个 double 参数,返回一个 double 值。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
double harmonic(double a, double b);

int main()
{
	printf("%lf", harmonic(10.0, 5.0));

	return 0;
}

// 函数定义
double harmonic(double a, double b)
{
	return 2 * a * b / (a + b);
}

5. 编写并测试一个函数 larger_of(), 该函数把两个 double 类型变量的值替换为较大的值,例如,larger_of(x, y) 会把 x 和 y 中较大的值重新赋值给两个变量。

答:
程序设计分析: 该函数返回类型为 void,接受两个指向 double 的指针

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
void larger_of(double* d1, double* d2);

int main()
{
	double d1 = 1.88, d2 = 1.89;
	larger_of(&d1, &d2);

	printf("d1 = %lf, d2 = %lf\n", d1, d2);

	return 0;
}

// 函数定义
void larger_of(double* d1, double* d2)
{
	*d1 = *d1 > *d2 ? *d1 : *d2;
	*d2 = *d1;
}

6. 编写并测试一个函数,该函数以 3 个 double 变量的地址作为参数,把最小值放入第 1 个变量中,中间值放入第 2 个变量中,最大值放入第 3 个变量中。

答:
程序设计分析: 该函数的返回类型为 void,接受 3 个 double 类型的变量。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
void sort(double *a, double *b, double *c);
void swap(double* d1, double* d2);

int main()
{
	double a = 1.4, b = 1.3, c = 1.2;

	sort(&a, &b, &c);

	printf("a = %.1lf\nb = %.1lf\nc = %.1lf\n", a, b, c);

	return 0;
}

// 函数定义
void sort(double* a, double* b, double* c)
{
	if (*a > *b)
		swap(a, b);
	
	if (*a > *c)
		swap(a, c);

	if (*b > *c)
		swap(b, c);
}

void swap(double* d1, double* d2)
{
	double temp = 0;
	temp = *d1;
	*d1 = *d2;
	*d2 = temp;
}

7. 编写一个函数,从标准输入中读取字符,知道遇到文件结尾。程序要报告每个字符是否是字母,如果是报告该字母在字母表中的位置,例如,c 和 C在字母表中的位置都是 3。再编写一个函数,以一个字符作为参数。如果该字符是一个字母则返回一个数值位置;否则返回 -1。

答:
程序设计分析: 第一个函数的返回类型为 void,不需要参数。第二个函数的返回类型为 int,接受一个 char 类型的变量。

代码如下:

c 复制代码
#include <stdio.h>
#include <ctype.h>

// 函数声明
void get_char_pos();
int position(char ch);

int main()
{
	get_char_pos();

	return 0;
}

// 函数定义
void get_char_pos()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)
	{
		if (position(ch) != -1)
			printf("%c: %d\n", ch, position(ch));
	}
}

int position(char ch)
{
	if (isupper(ch))
		return ch - 'A' + 1;
	else if (islower(ch))
		return ch - 'a' + 1;
	else
		return -1;
}

8. 在程序清单 6.20 中,power() 函数返回一个 double 类型的正整数次幂。改进该函数,使他能够计算负幂。另外,函数要处理特殊情况:0 的任何次幂都是 0,任何数的 0 次幂都是 1(函数应该报告 0 的 0 次幂未定义,因此把该值视为 1)。使用一个循环,并在程序中测试该函数。

答:
程序设计分析: 该函数返回类型为 double 值,接受一个 int 类型和 double 类型的参数。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
double power(int n, double d);

int main()
{
	// 所需变量
	int n = 0;
	double d = 0;

	// 进入循环
	printf("请输入指数和底数(中间用空格隔开):");
	while (scanf("%d %lf", &n, &d) == 2)
	{
		printf("结果为:%lf\n", power(n, d));
		printf("下一组:");
	}

	return 0;
}

// 函数定义
double power(int n, double d)
{
	double result = 1;

	if (0 == n && 0 == d)
	{
		printf("0 的 0 次幂未定义,值为 1\n");
		return 1;
	}
	else if (0 == n)
		return 1;
	else if (0 == d)
		return 0;
	else if (n > 0)
	{
		int i;
		for (i = n; i > 0; --i)
			result *= d;

		return result;
	}
	else
	{
		int i;
		for (i = n; i < 0; ++i)
			result *= d;

		return 1.0 / result;
	}
}

9. 使用递归函数重做编程练习 8。

答:
程序设计分析: 和编程练习 8 差不多,只是函数使用了递归,需要注意退出递归的条件,正次幂好递归,负次幂就化成正次幂就好了。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
double power(int n, double d);

int main()
{
	// 所需变量
	int n = 0;
	double d = 0;

	// 进入循环
	printf("请输入指数和底数(中间用空格隔开):");
	while (scanf("%d %lf", &n, &d) == 2)
	{
		printf("结果为:%lf\n", power(n, d));
		printf("下一组:");
	}

	return 0;
}

// 函数定义
double power(int n, double d)
{
	if (0 == n && 0 == d)
	{
		printf("0 的 0 次幂未定义,值为 1\n");
		return 1;
	}
	else if (0 == n)
		return 1;
	else if (0 == d)
		return 0;
	else if (n > 0)
	{
		return d * power(n - 1, d);
	}
	else
	{
		return 1.0 / power(-n, d);
	}
}

10. 为了让程序清单 9.8 中的 to_binary() 函数更通用,编写一个 to_base_n() 函数,该函数接受两个参数,且第 2 个参数介于 2 ~ 10 ,然后以第 2 个参数中指定的进制打印第一个数的数值。例如,to_base_n(129, 8)显示的结果 201,也就是 129 的八进制数。在一个完整的程序中测试该函数。

答:
程序设计分析: 和书本上二进制转换是一个道理,只不过除以 2 和对 2 取余换了而已。该函数没有返回值,接受两个 int 类型的参数。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
void to_base_n(int num, int n);

int main()
{
	int num = 0, n = 0;

	printf("请输入需要转换的数字和进制数:");
	while (scanf("%d %d", &num, &n) == 2)
	{
		printf("转换结果为:");
		to_base_n(num, n);
		printf("\n请输入下一组:");
	}

	return 0;
}

// 函数定义
void to_base_n(int num, int n)
{
	int left = num % n;
	num /= n;

	if (num)
		to_base_n(num, n);

	printf("%d", left);

}

11. 编写并测试 Fibonacci() 函数,该函数用循环代替递归计算斐波那契数。

答:
程序设计分析: 斐波那契数列,前面两个数为 1,后面的数均为前面两个数之和,所以循环需要 3 个变量,记录当前两个和下一个数。

代码如下:

c 复制代码
#include <stdio.h>

// 函数声明
int Fibonacci(int n);

int main()
{
	int n = 0;

	printf("你需要第几位斐波那契数:");
	scanf("%d", &n);
	printf("%d", Fibonacci(n));

	return 0;
}

// 函数定义
int Fibonacci(int n)
{
	if (n < 3)
		return 1;

	n -= 2;
	int a = 1, b = 1, c = 0;
	int i;
	for (i = n; i > 0; --i)
	{
		c = a + b;
		a = b;
		b = c;
	}

	return c;
	
}
相关推荐
拾木2003 分钟前
常见的限流算法
java·开发语言
处处清欢8 分钟前
MaintenanceController
java·开发语言
牵牛老人14 分钟前
Qt技巧(三)编辑框嵌入按钮,系统位数判断,判断某对象是否属于某种类,控件取句柄,支持4K,巧用QEventLoop,QWidget的窗体样式
开发语言·qt
Niu_brave19 分钟前
Python基础知识学习(2)
开发语言·python·学习
神仙别闹34 分钟前
基于C#+Mysql实现(界面)企业的设备管理系统
开发语言·mysql·c#
大柏怎么被偷了42 分钟前
【C++算法】位运算
开发语言·c++·算法
程序猿方梓燚43 分钟前
C/C++实现植物大战僵尸(PVZ)(打地鼠版)
c语言·开发语言·c++·算法·游戏
CPP_ZhouXuyang44 分钟前
C语言——模拟实现strcpy
c语言·开发语言·数据结构·算法·程序员创富
Zucker n1 小时前
猫狗识别大模型——基于python语言
开发语言·python
QXH2000001 小时前
数据结构—双向链表
c语言·数据结构·算法·链表