第十二章编程练习
第一题要求我们不使用全局变量,修改程序12.4,那我们就用指针作为参数去传递变量的地址,去修改变量的值,完整程序代码以及运行结果如下:
#include<stdio.h>
//int units = 0;
void critic(int * i);
int main(){
//extern int units;
int units;
int * ptr = &units;
printf("How many pounds to a firkin of butter?\n");
scanf("%d", &units);
while (units != 56){
critic(ptr);
}
printf("You must have looked it up!\n");
return 0;
}
void critic(int * i){
printf("No luck, my friend. Try again.\n");
scanf("%d", i);
}
接着,我们来看一下第二题,题目有些长,我们先看一下题目要求
第二题的内容有点多,但是也就是看着比较唬人,它给了我们一个c文件,规定了几个参数以及输出的格式,要我们去补充其他的文件。首先,pe12-2a.h这个头文件我们要去写,接着,另外几个函数的具体实现我们要写到pe12-2a.c文件中,因为函数要在pe12-2b.c文件中使用,所以我们将函数原型放到头文件中。
//pe12-2a.h
static int mode = 0;
static double distance;
static double fuel;
void set_mode(int m);
void get_info(void);
void show_info(void);
接着,我们去实现那几个函数的内容,我是按照他的输出例子去做的格式。
#include<stdio.h>
#include "pe12-2a.h"
extern int mode;
extern double distance;
extern double fuel;
void set_mode(int m){
if (m > 1){
mode = 1;
printf("Invalid mode specified.Mode 1(US) used.\n");
}else{
mode = m;
}
}
void get_info(void){
if (mode == 0){
printf("Enter distance traveled in kilometers:");
scanf("%lf",&distance);
printf("Enter fuel consumed in liters:");
scanf("%lf",&fuel);
}else if (mode == 1){
printf("Enter distance traveled in miles:");
scanf("%lf",&distance);
printf("Enter fuel consumed in gallons:");
scanf("%lf",&fuel);
}
}
void show_info(void){
if (mode == 0){
printf("Fuel consumption is %0.2lf liters per 100 km.\n",(fuel/distance*100));
}else if (mode == 1){
printf("Fuel consumption is %0.2lf miles per gallon.\n",(distance/fuel));
}
}
最后,把pe12-2b.c文件中的内容放到一个文件中。
#include<stdio.h>
#include "pe12-2a.h"
int main(void){
int mode;
printf("Enter 0 for metric mode, 1 for US mode: ");
scanf("%d", &mode);
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);
}
printf("Done.\n");
return 0;
}
在控制终端将三个文件一起编译为一个可执行应用程序,然后执行,获得最终的结果,程序运行结果如下
第三题要求我们只使用自动变量修改上面的程序,创建几个自动变量,然后在函数之间传递他们的值,然后根据各种不同的情况去输出不同的文字,三个修改之后的文件内容以及运行结果如下:
//pe12-2a.h
//static int mode = 0;
//static double distance;
//static double fuel;
int set_mode(int m);
double get_info(int mode);
void show_info(int mode, double number);
//pe12-2a.c
#include<stdio.h>
#include "pe12-2a.h"
//extern int mode;
//extern double distance;
//extern double fuel;
int set_mode(int m){
int mode;
if (m > 1){
mode = 1;
printf("Invalid mode specified.Mode 1(US) used.\n");
}else{
mode = m;
}
return mode;
}
double get_info(int mode){
double distance;
double fuel;
double r;
if (mode == 0){
printf("Enter distance traveled in kilometers:");
scanf("%lf",&distance);
printf("Enter fuel consumed in liters:");
scanf("%lf",&fuel);
r = (fuel/distance*100);
}else if (mode == 1){
printf("Enter distance traveled in miles:");
scanf("%lf",&distance);
printf("Enter fuel consumed in gallons:");
scanf("%lf",&fuel);
r = (distance/fuel);
}
return r;
}
void show_info(int mode, double number){
if (mode == 0){
printf("Fuel consumption is %0.2lf liters per 100 km.\n",number);
}else if (mode == 1){
printf("Fuel consumption is %0.2lf miles per gallon.\n",number);
}
}
//pe12-2b.c
#include<stdio.h>
#include "pe12-2a.h"
int main(void){
int mode;
double number;
printf("Enter 0 for metric mode, 1 for US mode: ");
scanf("%d", &mode);
while (mode >= 0){
mode = set_mode(mode);
number = get_info(mode);
show_info(mode, number);
printf("Enter 0 for metric mode, 1 for US mode");
printf("(-1 to quit):");
scanf("%d",&mode);
}
printf("Done.\n");
return 0;
}
好的,接下来来看一下第四题,让我们写一个循环,用函数去测试调用的次数,完整程序代码以及运行结果如下:
#include<stdio.h>
void ceshi(void);
static int number = 0;
int main(void){
int n;
printf("输入正数进入循环,负数退出:\n");
while (scanf("%d",&n)==1 && n>0){
ceshi();
printf("测试函数被调用了%d次\n",number);
}
printf("Done!!!\n");
return 0;
}
void ceshi(void){
number++;
}
接下来,我们来看一下第五题,生成一百个一到十以内的随机数,且按照降序排列,完整程序代码以及运行结果如下:
#include<stdio.h>
#define SIZE 100
static unsigned long int next = 1;
int rand(void);
int main(void){
int arr[SIZE];
for (int i = 0; i < SIZE; i++){
arr[i] = rand() % 10 + 1;
}
int n;
for (int i = 0; i < SIZE; i++){
for (int j = i+1; j < SIZE; j++){
if (arr[i]<arr[j]){
n = arr[i];
arr[i] = arr[j];
arr[j] = n;
}
}
}
for (int i = 0; i < SIZE; i++){
printf("%d ",arr[i]);
if (i%10 ==9){
printf("\n");
}
}
printf("Done!!!\n");
return 0;
}
int rand(void){
next = next * 1103515245 + 12345;
return (unsigned int) (next / 65536) % 32768;
}
下面看一下第六题,生成一千个随机数,记录每个数字出现的次数,用不同的种子去实验,去更换静态变量next的值即可更换种子,完整程序代码以及运行结果如下
#include<stdio.h>
#define SIZE 1000
static unsigned long int next = 1;
int rand(void);
int main(void){
int n;
int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0, n7 = 0, n8 = 0, n9 = 0, n10 = 0;
for (int i = 0; i < SIZE; i++){
n = rand() % 10 + 1;
switch (n){
case 1:
n1++;
break;
case 2:
n2++;
break;
case 3:
n3++;
break;
case 4:
n4++;
break;
case 5:
n5++;
break;
case 6:
n6++;
break;
case 7:
n7++;
break;
case 8:
n8++;
break;
case 9:
n9++;
break;
case 10:
n10++;
break;
default:
break;
}
}
printf("数字-------出现的次数\n");
printf("1--------%d\n",n1);
printf("2--------%d\n",n2);
printf("3--------%d\n",n3);
printf("4--------%d\n",n4);
printf("5--------%d\n",n5);
printf("6--------%d\n",n6);
printf("7--------%d\n",n7);
printf("8--------%d\n",n8);
printf("9--------%d\n",n9);
printf("10--------%d\n",n10);
printf("Done!!!\n");
return 0;
}
int rand(void){
next = next * 1103515245 + 12345;
return (unsigned int) (next / 65536) % 32768;
}
种子为1
种子为2
显然,更换种子之后,每个数字出现的频率不同了,他让用十个去实验,这里我暂时就用这俩吧,自己感兴趣的话可以多换几次种子值。下面我们来看第七题,让我们去修改程序清单12.13后面讨论的内容,我们首先先将12.13在电脑上运行一遍,然后着手对其进行修改,完整程序代码以及运行结果如下:
//diceroll.h
extern int roll_count;
int roll_n_dice(int dice, int sides);
//diceroll.c
#include<stdio.h>
#include<stdlib.h>
#include "diceroll.h"
int roll_count = 0;
static int rollem(int sides){
int roll;
roll = rand() % sides + 1;
++roll_count;
return roll;
}
int roll_n_dice(int dice, int sides){
int d;
int total = 0;
if(sides < 2){
printf("Need at least 2 sides.\n");
return -2;
}
if (dice < 1){
printf("Need at least 1 die.\n");
return -1;
}
for ( d = 0; d < dice; d++){
total += rollem(sides);
}
return total;
}
//manydice.c
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include "diceroll.h"
int main(void){
int dice, roll;
int sides;
int status;
int number;
srand((unsigned int) time(0));
printf("Enter the number of sets; enter q to stop.\n");
while (scanf("%d", &number) == 1 && number > 0){
printf("How many sides and how many dice?\n");
if ((status = scanf("%d %d", &sides, &dice)) != 2){
if (status == EOF){
break;
}else{
printf("You should have entered an integer.");
printf(" Let's begin again.\n");
while (getchar() != '\n'){
continue;
}
printf("How many sides? Enter 0 to stop.\n");
continue;
}
}
printf("Here are %d sets of %d %d-side throws.\n",number, dice, sides);
for (int i = 1; i <= number; i++){
roll = roll_n_dice(dice, sides);
printf("%d ",roll);
if (i%10 == 0){
printf("\n");
}
}
printf("\n");
printf("How many sets? Enter q to stop.\n");
}
printf("The rollem() function was called %d times.\n",roll_count);
printf("GOOD FORTUNE TO YOU!\n");
return 0;
}
紧接着,来看一下第八题的要求
乍一看,题目要求很长,其实就是让我们去补充两个函数,完整程序代码以及运行结果如下:
#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 * a;
a = (int *)malloc(elem * sizeof(int));
for (int i = 0; i < elem; i++){
*(a + i) = val;
}
return a;
}
void show_array(const int ar [], int n){
for (int i = 0; i < n; i++){
printf("%d ",ar[i]);
if ((i+1)%8 == 0){
printf("\n");
}
}
printf("\n");
}
接下来,我们来看一下最后一个问题
看上去比较复杂,分析一下哈,首先这道题关键的点在于要创建根据用户输入单词,动态去使用存储的数组以存放数据,其中还要求使用指向指针的指针,好
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//头文件需要用这几个,暂时想到这几个
int main(void){
//主函数
int number;//获取单词数
printf("How many words do you wish to enter? \n");
while (scanf("%d",&number) !=1 && number <= 0){
//校验数据合法性,不合法的话重新获取值
printf("Please enter a number and the number must be > 0\n");
printf("How many words do you wish to enter? \n");
}
//创建存放char类型指针的数组,char类型指针存储的是每一个单词的位置
char ** ptr = (char **) malloc(number * sizeof(char *));
printf("Enter %d words now:\n",number);
//获取单词
for (int i = 0; i < number; i++){
//临时数组
char temp[44];
//利用scanf函数读取到空格会暂停的属性,去断开每个单词
scanf("%s",temp);
//计算单词的长度,创建合适的存储位置,将这个地址放到数组中
*(ptr + i) = (char *) malloc(strlen(temp) * sizeof(char));
//将临时数组中的内容放到新创建的位置中
strcpy(*(ptr + i),temp);
}
//展示单词
printf("Here are your words:\n");
for (int i = 0; i < number; i++){
printf("%s\n",*(ptr + i));
}
//释放每个单词所占的内存
for (int i = 0; i < number; i++){
free(*(ptr + i));
}
//释放指针数组所占的内存
free(ptr);
return 0;
}
程序的运行结果如下
以上就是第十二章的编程练习的全部内容了。通过这些,可以更好地理解变量在程序运行时的活动范围,去设计风格更好地程序。接下来,就是第十三章的内容了。