C Primer Plus第十二章编程练习

第十二章编程练习

第一题要求我们不使用全局变量,修改程序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;
}

程序的运行结果如下

在这里插入图片描述

以上就是第十二章的编程练习的全部内容了。通过这些,可以更好地理解变量在程序运行时的活动范围,去设计风格更好地程序。接下来,就是第十三章的内容了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值