c primer plus第12章课后题答案(个人详解版)

12.1

实参是取地址符,形参使用指针接收

#include <stdio.h>

void critic(int *units);

int main(void)
{
	int units;

	printf("How many pounds to a firkin of butter?\n");
	scanf("%d", &units);

	while (units != 56)
	{
		//调用该函数,再次输入
		critic(&units);
		printf("You must have looked it up!\n");
	}

	return 0;
}

void critic(int *units)
{
	printf("No luck, my friend. Try again.\n");
	scanf("%d", &units);
	return;
}

12.2

版本一
pe12-2a.h

//
void set_mode(int n);
void get_info(void);
void show_info(void);

pe12-2a.cpp

#include <stdio.h>

static int mode;
static double range; // 范围
static double fuel; //燃油

void set_mode(int n)
{
	if (n > 1)
	{
		printf("现在的输入是无效的方式指定,上一次的模式是--%s\n", 
			mode == 0 ? "0(metric)" : "1(US)");
		
	}
	else
	{
		mode = n;

	}

	return;
}

void get_info(void)
{
	if (0 == mode)
	{
		printf("输入行驶距离,单位为公里:\n");		

	}
	else if(mode == 1)//1
	{
		printf("输入旅行距离,单位为英里:\n");
		
	}
	scanf("%lf", &range);


	if (0 == mode)
	{
		printf("输入燃料消耗(以升为单位):\n");
		//putchar('\n');
	}
	else if (mode == 1)
	{
		printf("输入燃料消耗(加仑):\n");
		//putchar('\n');
	}
	scanf("%lf", &fuel);


	return;

}

void show_info(void)
{
	if (0 == mode)
	{
		printf("燃料消耗是 %.2lf 升/100公里.\n",
			(fuel / (range / 100)));
		putchar('\n');
	}

	else if (mode == 1)
	{
		printf("燃料消耗是 %.1lf, 一英里数.\n",
			range / fuel);
		putchar('\n');
	}
	return;
}

pe12-2b.cpp

#include <stdio.h>
#include "pe12-2a.h"

int main(void)
{
	int mode;
	printf("Enter 0 for metric mode, 1 for US mode:\n");	
	scanf("%d", &mode);
	putchar('\n');

	while (mode >= 0)
	{
		set_mode(mode);
		get_info();
		show_info();

		printf("Enter 0 for metric mode, 1 for US mode");
		printf(" (-1 to quit): ");
		scanf("%d", &mode);
		putchar('\n');

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

get_info()第二种方法

在这里插入图片描述

	if (0 == mode)
	{
		printf("输入行驶距离,单位为公里:\n");
		while (!scanf("%lf", &range))
		{
			while (getchar() != '\n')
				continue;
			puts("请输入数字.");
		}
		while (!scanf("%lf", &fuel))
		{
			while (getchar() != '\n')
				continue;
			puts("请输入数字.");
		}

	}
	else
	{
		printf("输入旅行距离,单位为英里:\n");
		while (!scanf("%lf", &range))
		{
			while (getchar() != '\n')
				continue;
			puts("请输入数字.");
		}
		while (!scanf("%lf", &fuel))
		{
			while (getchar() != '\n')
				continue;
			puts("请输入数字.");
		}

	}

结论分析:

在这里插入图片描述
23333

12.3

在pe12-2a.h中,为什么三个函数的形参类型不同:
1.值传递(只传送值,实参不做改变)
2.地址传递(传送地址,实参被改变)

.
set_mode()中要获取我们要从键盘上输入mode,每次不同,实参的值会改变和get_info()获取到的距离、燃油这两个变量的值也会在该函数中发生变化,对应实参的值也会变
.
.
.
C语言_函数_地址和指针:值传递和地址传递的区别
.
pe12-2a.h

void set_mode(int *mode, int *n);
void get_info(int mode, double *range, double *fuel);
void show_info(int mode, double range, double fuel);

pe12-2a.cpp

#include <stdio.h>
#include "pe12-2a.h"
//static int mode;
//static double range; // 范围
//static double fuel; //燃油

void set_mode(int *mode,int *n)
{
	puts("打印-set_mode()已获取到输入的mode值---");
	if (*mode > 1)
	{
		printf("现在的输入是无效的方式指定,上一次的模式是--》%s .\n", 
			*n == 0 ? "0(metric)" : "1(US)");
		puts("打印-此时是无效输入---");
	}
	else
	{
		*n = *mode;
		puts("打印-此时开始赋值操作---");
	}

	return;
}

void get_info(int temp, double *range, double *fuel)
{
	puts("打印-调用get_info()实现---");
	if (0 == temp)
	{
		printf("输入行驶距离,单位为公里:\n");
		while (!scanf("%lf", range))
		{
			while (getchar() != '\n')
				continue;
			puts("请输入数字.");
			 //假,进入,真跳出
		}
		printf("输入燃油:\n");
		while (!scanf("%lf", fuel))
		{
			while (getchar() != '\n')
				continue;
			puts("请输入数字.");
		}

	}
	else
	{
		printf("输入旅行距离,单位为英里:\n");
		while (!scanf("%lf", &range))
		{
			while (getchar() != '\n')
				continue;
			puts("请输入数字.");
		}
		printf("输入燃油:\n");
		while (!scanf("%lf", &fuel))
		{
			while (getchar() != '\n')
				continue;
			puts("请输入数字.");
		}

	}


	return;

}

void show_info(int temp, double range, double fuel)
{
	puts("打印-调用show_info()实现---");
	if (0 == temp)
	{
		printf("燃料消耗是 %.2lf 升/100公里.\n",
			(fuel / (range / 100)));
		putchar('\n');
	}

	else if (temp == 1)
	{
		printf("燃料消耗是 %.1lf, 一英里数.\n",
			range / fuel);
		putchar('\n');
	}
	return;
}

pe12-2b.cpp

#include <stdio.h>
#include "pe12-2a.h"

int main(void)
{
	int mode, temp;
	double range, fuel;

	printf("Enter 0 for metric mode, 1 for US mode:\n");	
	scanf("%d", &mode);
	temp = mode;
	putchar('\n');

	while (mode >= 0)
	{
		puts("打印--主函数while循环--");
		printf("-------------------------\n");
		puts("打印--开始set_mode--");
		set_mode(&mode, &temp);

		puts("打印--开始get_info--");
		get_info(temp, &range, &fuel);

		puts("打印--开始show_info--");
		show_info(temp, range, fuel);

		printf("Enter 0 for metric mode, 1 for US mode");
		printf(" (-1 to quit): ");
		scanf("%d", &mode);
		puts("打印--新输入--");
		putchar('\n');

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

在这里插入图片描述
.

12.4

  变量count是具有内部链接的静态变量 :具有静态存储期文件作用域内部链接三种属性,这样在主函数和调用函数的实现中都可见。
  ++count,++在前,先计算后赋值。
.

#include<stdio.h>

static int count = 0;


int counter(void);
int main(void)
{
	int i;
	int j = 0;

	printf("请输入一个正整数:");
	scanf("%d", &i);
	for (j; j < i; j++)
	{

		printf("counter = %d\n", counter());
	}

	printf("函数总共调用了%d次\n", count);

	return 0;

}

int counter(void)
{

	return ++count;
}

在这里插入图片描述
.

12.5

rand() % 10取余获取到的数都是0-9,所以我们需要为其+1,得到1-10的随机数。

这里的i从1开始,会在最上面单独显示1个数,导致最后一行缺少一个数; 如果i从0开始,而不动对10取余的i,会导致队后一行的最后一个数为负数

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define LEN 100
void show_array(int *a, int n);
void sort(int a[], int n);

int main(void)
{
	int i;
	int a[LEN];

	srand((unsigned int)time(0));
	 //提供随机数种子~

	for (i = 0; i < LEN; i++)
	{
		a[i] = rand() % 10 + 1;
		 //调用随机数种子,产生 1~10 之间的随机数
	}

	printf("最初的%d个数是:\n", LEN);
	puts("排序前的数组:");
	show_array(a,LEN);
	puts("----------------------\n");

	puts("排序后的数组:");
	sort(a,LEN);
	show_array(a, LEN);

	return 0;
}

void show_array(int *a, int n)//int a[]也可以
{
	int i;
	for (i = 1; i < n; i++)
	{
		printf("%-3d ", a[i]);
		
		if (i % 10 == 0)
		{
			//每10个换一行
			putchar('\n');
		}
	}
	putchar('\n');

	return;
}

void sort(int a[], int n)
{
	 //冒泡排序
	int i, j;
	int temp = 0;

	for (i = 0; i < n - 1; i++)
	{
		for (j = i+ 1; j < n; j++)
		{
			if (a[i] < a[j])
			{
				temp = a[j];
				a[j] = a[i];
				a[i] = temp;
			}

		}

	}


	return;
}

在这里插入图片描述

修改

在这里插入图片描述

12.6


#include <stdio.h>
#define N 10
#define LEN 1000


int myrand(void);
void mysrand(unsigned int seeds);

static unsigned long int next = 1;//种子

int main(void)
{
	int i, temp, a[N + 1];
	unsigned int seeds;

	for (seeds = 1; seeds <= N; seeds++)
	{
		printf("第%d次生成随机数:\n", seeds);
		mysrand(seeds);

		for (i = 0; i < N + 1; i++)
		{
			//↑将所有元素下标对应的次数,每循环一次清零一次
			a[i] = 0;
			
		}

		for (i = 0; i < LEN; i++)
		{
			temp = myrand() % 10 + 1;
			 //产生1 ~ 1000的随机数
			a[temp]++;
			 //将产生的随机数作为数组下标,在一次循环中统计该下标出现的次数
		}

		for (i = 1; i < N + 1; i++)
		{			
			printf("%d出现了%d次\n", i, a[i]);
				//i作为数组元素1~10出现 ;a[i] 作为数组下标出现
		}
		printf("随机出现的总数 :%d个\n\n", LEN);
	}


	return 0;
}

int myrand(void)
{
	//↑rand函数的实现;
	next = next * 1103515245 + 12345;
	return (unsigned int)(next / 65536) % 32768;

}

void mysrand(unsigned int seed)
{
	//↑srand函数的实现;
	next = seed;
	return;
}

在这里插入图片描述
在这里插入图片描述

12.7

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

int main(void)
{
    int dice, count;
    int roll;//面数统计
    int sides;
    int set, sets;

    srand((unsigned int) time(0));

    printf("输入掷色子后想产生的数量,\nEnter q停止:");
    while (scanf("%d", &sets) == 1)
    {
        puts("有多少面和多少个筛子?");
        puts("选择两个正数:");
        if(scanf("%d  %d", &sides, &dice) != 2)
        {
            puts("没有整数,终止输入回路");
            break;
        }
        printf("这里有%d次情况产生,有 %d面 %d个筛子-投掷结果:", sets, sides, dice );
        putchar('\n');
        for(set = 0; set < sets; set++)
        {
            for(roll = 0, count = 0; count < dice; count++)
            {
                roll += rollem(sides);

            }
            printf("%-5d", roll);

            if(0 == (set +1) % 8)
            {
                putchar('\n');
            }
        }
        printf("\nHow many sets? Enter q to stop: ");
    }
    puts("GOOD FORTUNE TO YOU!\n");
    return 0;
}

int rollem(int sides)
{
    //产生随机数(随时间变化)
    return rand() % sides + 1;
}

在这里插入图片描述

12.8

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

int *make_array(int elem, int val);
void show_array(const int ar[], int n);

int main(void)
{
	int *pa;
	int size;
	int value;

	printf("Enter the number of elements: ");
	while (scanf("%d", &size) == 1 && size > 0)
	{
		printf("Enter the initialization value: ");
		scanf("%d", &value);

		pa = make_array(size, value);//数组大小、给定的值
		if (pa)
		{
			show_array(pa, size);//相当于传递进去数组的首地址以及数组大小
			free(pa);
		}
		printf("Enter the number of elements (<1 to quit): ");
	}
	printf("Done.\n");

	return 0;
}


int *make_array(int elem, int val)
{
	int i;
	int *pt;
	pt = (int *)malloc(elem * sizeof(int));//在堆区创建elem大小的int类型值块,让pt指向这个区域

	if (NULL == pt)
	{
		printf("Memory allocation failed!\n");
		exit(EXIT_FAILURE);
	}
	printf("Output %d numbers:\n", val);
	for (i = 0; i < elem; i++)
	{
		pt[i] = val;
	}
	return pt;
}

void show_array(const int ar[], int n)
{
	int i;

	for (i = 0; i < n; i++)
	{
		printf("%d ", ar[i]);
		if (0 == (i + 1) % 8)//i从0开始,所以i需要+1再对8取余
		{
			putchar('\n');
		}
	}
	putchar('\n');
	return;
}

12.9

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LEN 100

int main(void)
{
	char **pt;
	char temp[LEN];
	int i, n, length;

	printf("How many words do you wish to enter? ");
	scanf("%d", &n);

	pt = (char**)malloc(n * sizeof(char *));
	//指向指针的指针


	if (pt == NULL)
	{

		printf("Memory allocation failed!\n");
		exit(EXIT_FAILURE);
	}
	printf("Enter %d words now:", n);


	//每循环一次,对temp中的数据进行一次拷贝
	for (i = 0; i < n; i++)
	{
		scanf("%99s", temp);
		length = strlen(temp) + 1;
		//↑+1便于保存空字符'\0';

		pt[i] = (char *)malloc(length * sizeof(char));
		//数组当中包含的元素都是指向 char类型 的指针,pt 是 指向指针的指针
		//↑使用malloc分配足够的存储空间来存储单词;
		if (pt[i] == NULL)
		{
			printf("Memory allocation failed!\n");
			exit(EXIT_FAILURE);
		}
		else
			strcpy(pt[i], temp);
		//这里空间够用,上诉为 pt[i] 创建的堆区空间大小即为 temp 数组对应大小的空间
	}

	printf("Here are your words:\n");
	for (i = 0; i < n; i++)
	{
		puts(pt[i]);
		free(pt[i]);
		pt[i] = NULL;
	}

	free(pt);
	pt = NULL;
	//↑指针仍然指向malloc分配的存储空间;
   //↑因此令指针指向NULL后防止内存滥用;
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

扳手的海角

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

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

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

打赏作者

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

抵扣说明:

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

余额充值