C Primer Plus第十二章编程练习

news2025/4/17 18:00:50

第十二章编程练习

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

程序的运行结果如下

在这里插入图片描述

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2040887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

node卸载与安装

1.直接使用卸载程序卸载 2.安装新的Node 官网下载并执行下一步直到完成 3.Idea配置不同版本的node file->settings->Languages & Frameworks->Node.js and NPM->增加带选项->选择指定版本

ubuntu下使用docker、socket、yolov5进行图像处理数据交互记录

ubuntu下使用docker、socket、yolov5进行图像处理数据交互记录 概述&#xff1a;主要实现了在宿主机上通过8000端口传递一张图像给docker镜像&#xff0c;然后镜像中处理后&#xff0c;通过8001端口回传处理后的图像给宿主机。 第一章、构建镜像 一、dockerfile文件 1.拉取…

jQuery:配置与选择器

一&#xff0c;jQuery的配置 jQuery下载 这里以compressed为例&#xff0c;根据喜好也可以选择uncompressed版本。 进入jQuery代码中&#xff0c;右键另存为&#xff0c;保存到自己项目中&#xff1a; 导入jQuery <!DOCTYPE html> <html lang"en"><…

WO Mic 手机变身免费麦克风

目录 一、主要特点 1.支持多种连接方式 2.应用广泛 3.低延迟 4.简易配置 5.自动连接 6.音频格式 二、软件下载 三、软件安装 四、系统连接 五、测试 直播的时候,上课的时候,会议的时候……突然发现没有麦克风或者电脑麦克风有故障,这可怎么办呢?今天给大家介绍一…

ONNX深入研究(1):AI模型优化与加速方法

得益于现有的硬件和加速器&#xff0c;深度学习在 2010 年代初开始兴起&#xff0c;在这种支持下&#xff0c;研究人员和工程师提出了更复杂、更大的模型。然而&#xff0c;内存消耗和执行时间等限制仍然是一个挑战。由于计算资源的限制&#xff0c;这些挑战在工程和商业领域变…

UE5学习笔记11-为拿取武器添加动画

一、一点说明 动画实例通过扩展为所有机器上的每个字符都存在动画蓝图&#xff0c;动画实例只能访问该计算机上的变量。 二、思路 我在武器组件中有一个武器类的指针&#xff0c;判断当前指针是否为空去判断当前角色是否装备武器 三、实现 1.在角色C类中添加是否装备武器的函…

OpenCV--图片操作

一.图片旋转 图片旋转是图像处理中的一种基本操作&#xff0c;用于将图像按照指定的角度进行旋转。旋转操作在图像编辑、计算机视觉和图形学等领域中非常常见&#xff0c;通常用来调整图像的方向或在图像识别中进行数据增强。 旋转的基本原理 图片旋转涉及到将每个像素从原始…

(贪心) LeetCode 376. 摆动序列

原题链接 一. 题目描述 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如&#xff0c; [1, 7, 4, 9, 2,…

电脑技巧:电脑系统盘文件清理指南

目录 一、可以安全删除的文件 1.1. 临时文件 1.2. 系统缓存文件 1.3. 回收站 1.4. 安装包缓存 1.5. 系统还原点 1.6. 已下载的更新文件 1.7. 浏览器缓存 1.8. Thumbs.db 文件 1.9. Windows日志文件 1.10. Windows.old 文件夹 二、系统文件清理注意点 三、系统文件…

推荐一款Python开源移动应用安全测试分析工具!!!

今天给大家推荐一个安全测试相关的开源项目&#xff1a;nccgroup/house 1、介绍 它是一个由 NCC Group 开发的&#xff0c;一个基于Frida和Python编写的动态运行时移动应用分析工具包&#xff0c;提供了基于 Frida 的 Web GUI 界面&#xff0c;旨在简化动态函数挂钩的过程&am…

Linux---04---Vim编辑器

一、vi/vim编辑器介绍 vi 是 visual interface 的简称&#xff0c;是Linux系统提供的一个文本编辑工具&#xff0c;可以对文件内容进行编辑&#xff0c;类似于Windows中的记事本。 vim 是 vi 的加强版本&#xff0c;兼容 vi 的所有指令&#xff0c;不仅能编辑文本&#xff0c…

Using locally deployed llm with langchain‘s openai llm wrapper

题意&#xff1a;使用本地部署的LLM与Langchain的OpenAI LLM封装器 问题背景&#xff1a; I have deployed llm model locally which follows openai api schema. As its endpoint follows openai schema, I dont want to write separate inference client. 我已经本地部署了…

Mybatis框架介绍

Mybatis入门 MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;Plain Old Jav…

IT管控体系建设(集团企业),附网传埃森哲案例

&#xff08;一&#xff09;集团IT企业IT管控组织结构设计 1.集团分管领导 职能&#xff1a;最高级别的管理&#xff0c;负责对整个集团的信息化管控进行监督和决策。 2.CIO/管理部主任 职能&#xff1a;负责整体的IT战略和方向&#xff0c;直接向集团分管领导汇报。负责协…

一分钟了解:Java 冒泡排序算法

1. 冒泡排序算法介绍 冒泡排序是最简单的排序算法&#xff0c;如果相邻元素的顺序错误&#xff0c;则通过反复交换相邻元素来工作。Java 中的冒泡排序不是对数组进行排序的最佳方法&#xff0c;但却是最基本的实现之一。在本文中&#xff0c;我们将学习如何用 Java 编写冒泡排…

「Pytorch」解析 nn.Embedding 词嵌入 及反推输入

在Pytorch里面有三种编码方式&#xff0c;Embedding 就是其中之一&#xff0c;不同于 one_hot 需要用同长度的张量存 Embedding将单词映射为稠密向量&#xff0c;并且指定 embedding_dim维度。通过 Embedding层 转换的数据并不是经过词典映射的&#xff0c;而是原始数据。Embed…

VirtualBox扩容VDI虚拟磁盘

环境 虚拟机软件&#xff1a;VirtualBox虚拟机&#xff1a;Ubuntu 18.04.1 第一步&#xff1a;调整虚磁盘大小 方法1&#xff1a;使用VirtualBox管理器直接修改 关闭虚拟机&#xff0c;点击VirtualBox管理器菜单管理>虚拟介质管理&#xff0c;重新设大小 方法2&#x…

【Linux基础】对Linux权限的理解与管理

目录 &#x1f680;前言一&#xff0c;有关用户二&#xff0c;Linux权限管理1. 文件访问者的分类(人)2. 文件类型和访问权限(事物属性)2.1 文件类型2.2 文件/目录的基本权限 三&#xff0c;文件权限值的表示方法3.1 字符表示方法3.2 八进制数值表示方法 四&#xff0c;文件访问…

服务器是什么?怎么选择适合自己的服务器?

在这个数字化的世界中&#xff0c;我们每天都在与各种网站打交道&#xff0c;浏览新闻、购物、看视频等。你是否曾经好奇过&#xff0c;这些网站是如何运行的&#xff1f;它们又是如何实现随时随地可访问的呢&#xff1f; 在这背后&#xff0c;有一个神秘的角色在默默地支撑着…

数据结构与算法 - 贪心算法

一、贪心例子 贪心算法或贪婪算法的核心思想是&#xff1a; 1. 将寻找最优解的问题分为若干个步骤 2. 每一步骤都采用贪心原则&#xff0c;选取当前最优解 3. 因为没有考虑所有可能&#xff0c;局部最优的堆叠不一定让最终解最优 贪心算法是一种在每一步选择中都采取在当前…