C Primer Plus 第十二章 课后答案

目录

 

复习题

1.哪些类别的变量可以成为它所在函数的局部变量?

2.哪些类别的变量在它所在程序的运行期一直存在?

3.哪些类别的变量可以被多个文件使用?哪些类别的变量仅限于在一个文件中使用?

4.块作用域变量具有什么链接属性?

         5.extern关键字有什么用途?

6.考虑下面两行代码,就输出的结果而言有何异同:

int * p1 = (int *)malloc(100 * sizeof(int));

int * p1 = (int *)calloc(100, sizeof(int));

7.下面的变量对哪些函数可见?程序是否有误?

8.下面程序会打印什么

9.假设文件的开始处有如下声明:

static int plink;

int value_ct(const int arr[], int value, int n);

a.以上声明表明了程序员的什么意图?

b.用const int value和const int n分别替换int value和int n,是否对主调程序的值加强保护。

编程练习

1.不使用全局变量,重写程序清单12.4

2.在美国,通常以英里/加仑来计算油耗;在欧洲,以升/100 公里来计算。下面是程序的一部分,提示用户选择计算模式(美制或公制),然后接收数据并计算油耗

如果用户输入了不正确的模式,程序向用户给出提示消息并使用上一次输入的正确模式。请提供pe12-2a.h头文件和pe12-2a.c源文件。源代码文件应定义3个具有文件作用域、内部链接的变量。一个表示模式、一个表示距离、一个表示消耗的燃料。get_info()函数根据用户输入的模式提示用户输入相应数据,并将其储存到文件作用域变量中。show_info()函数根据设置的模式计算并显示油耗。可以假设用户输入的都是数值数据

3.重新设计编程练习2,要求只使用自动变量。该程序提供的用户界面不变,即提示用户输入模式等。但是,函数调用要作相应变化

4.在一个循环中编写并测试一个函数,该函数返回它被调用的次数

5.编写一个程序,生成100个1~10范围内的随机数,并以降序排列(可以把第11章的排序算法稍加改动,便可用于整数排序,这里仅对整数排序)

6.编写一个程序,生成1000个1~10范围内的随机数。不用保存或打印这些数字,仅打印每个数出现的次数。用 10 个不同的种子值运行,生成的数字出现的次数是否相同?可以使用本章自定义的函数或ANSI C的rand()和srand()函数,它们的格式相同。这是一个测试特定随机数生成器随机性的方法

7.编写一个程序,按照程序清单12.13输出示例后面讨论的内容,修改该程序。使其输出类似:

Enter the number of sets; enter q to stop : 18

How many sides and how many dice? 6 3

Here are 18 sets of 3 6-sided throws.

12 10 6 9 8 14 8 15 9 14 12 17 11 7 10 13 8 14

How many sets? Enter q to stop: q

8.下面是程序的一部分:

提供make_array()和show_array()函数的定义,完成该程序。make_array()函数接受两个参数,第1个参数是int类型数组的元素个数,第2个参数是要赋给每个元素的值。该函数调用malloc()创建一个大小合适的数组,将其每个元素设置为指定的值,并返回一个指向该数组的指针。show_array()函数显示数组的内容,一行显示8个数

9.编写一个符合以下描述的函数。首先,询问用户需要输入多少个单词。然后,接收用户输入的单词,并显示出来,使用malloc()并回答第1个问题(即要输入多少个单词),创建一个动态数组,该数组内含相应的指向char的指针(注意,由于数组的每个元素都是指向char的指针,所以用于储存malloc()返回值的指针应该是一个指向指针的指针,且它所指向的指针指向char)。在读取字符串时,该程序应该把单词读入一个临时的char数组,使用malloc()分配足够的存储空间来储存单词,并把地址存入该指针数组(该数组中每个元素都是指向 char 的指针)。然后,从临时数组中把单词拷贝到动态分配的存储空间中。因此,有一个字符指针数组,每个指针都指向一个对象,该对象的大小正好能容纳被储存的特定单词。下面是该程序的一个运行示例:

How many words do you wish to enter? 5

Enter 5 words now: I enjoyed doing this exerise

Here are your words:

I

enjoyed

doing

this

exercise


复习题

1.哪些类别的变量可以成为它所在函数的局部变量?

  1. 自动存储类别
  2. 寄存器存储类别
  3. 静态、无链接存储类别

2.哪些类别的变量在它所在程序的运行期一直存在?

  1. 静态、无链接存储类别
  2. 静态、内部链接存储类别
  3. 静态、外部链接存储类别

3.哪些类别的变量可以被多个文件使用?哪些类别的变量仅限于在一个文件中使用?

1)静态、外部链接存储内容

2)静态、内部链接存储内容

4.块作用域变量具有什么链接属性?

无链接

5.extern关键字有什么用途?

用于声明,表名该变量或函数已经在别处定义了

6.考虑下面两行代码,就输出的结果而言有何异同:

int * p1 = (int *)malloc(100 * sizeof(int));

int * p1 = (int *)calloc(100, sizeof(int));

前者在分配时内存中存储元素的值是未定义的,后者中的每一个元素都设置为0

7.下面的变量对哪些函数可见?程序是否有误?

/* 文件 1 */ 
int daisy;
int main(void) 
{ 
    int lily; 
    ...; 
} 
int petal() 
{ 
    extern int daisy, lily; 
    ...; 
}
/* 文件 2 */ 
extern int daisy; 
static int lily; 
int rose; 
int stem() 
{ 
    int rose; 
    ...;
} 
void root() 
{
    ...;
}

1)

  1. 文件1中daisy对main()和petal()可见,文件2中以extern声明的daisy才对stem()、root()可见//12.1.7  【附录A中的答案给的是petal()中也要以extern声明,但书上12.1.7说是可选的声明不是必须的声明】
  2. 文件1中main()中的lily仅对main()函数可见
  3. 文件2中的lily,rose对文件2中的stem()和root()可见,其中stem()中声明的rose只对stem()可见

2)

  1. 文件1中lily的引用是错误的,不存在变量名为lily的外部链接变量

8.下面程序会打印什么

#include <stdio.h>
char color = 'B';
void first(void);
void second(void);
int main(void)
{
    extern char color;
    printf("color in main() is %c\n", color);
    first();
    printf("color in main() is %c\n", color);
    second();
    printf("color in main() is %c\n", color);
    return 0;
}
void first(void)
{
    char color;
    color = 'R';
    printf("color in first() is %c\n", color);
}

void second(void) 
{
    color = 'G';
    printf("color in second() is %c\n", color);
}
 

color in main() is B

color in first() is R

color in main() is B

color in second() is G

color in main() is G

9.假设文件的开始处有如下声明:

static int plink;

int value_ct(const int arr[], int value, int n);

a.以上声明表明了程序员的什么意图?

b.用const int value和const int n分别替换int value和int n,是否对主调程序的值加强保护。

a.

  1. 定义一个名为plink的内部链接的存储变量       
  2. 定义一个函数名为value_ct的函数,该函数第一个参数为int型的数组,且在函数执行过程中该数组内容不可改变,第二参数和第三个参数都是int型变量,该函数返回一个int型的值

b. 否,形参的值改变并不改变实参的值

编程练习

1.不使用全局变量,重写程序清单12.4

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

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

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;
}

2.在美国,通常以英里/加仑来计算油耗;在欧洲,以升/100 公里来计算。下面是程序的一部分,提示用户选择计算模式(美制或公制),然后接收数据并计算油耗

如果用户输入了不正确的模式,程序向用户给出提示消息并使用上一次输入的正确模式。请提供pe12-2a.h头文件和pe12-2a.c源文件。源代码文件应定义3个具有文件作用域、内部链接的变量。一个表示模式、一个表示距离、一个表示消耗的燃料。get_info()函数根据用户输入的模式提示用户输入相应数据,并将其储存到文件作用域变量中。show_info()函数根据设置的模式计算并显示油耗。可以假设用户输入的都是数值数据

//pe12-2a.c
#include "pe12-2a.h"

void set_mode(int n)
{
    mode = n;
}

void get_info()
{
    printf("Enter distance traveled in kilometers:");
    scanf("%lf", &km);
    printf("Enter fuel consumed in liters:");
    scanf("%lf", &fc);
}

void show_info()
{
    if(mode)
    {
        printf("Fuel consumption is %.1lf miles per gallon.\n", km / fc);
    }
    else
    {
        printf("Fuel consumption is %.2lf liters per 100 km.\n", fc / km);
    }
}
//pe12-2a.h
#ifndef DRAFT_PE12_2A_H
#define DRAFT_PE12_2A_H

#include <stdio.h>

static int mode;
static double km, fc;

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


#endif

3.重新设计编程练习2,要求只使用自动变量。该程序提供的用户界面不变,即提示用户输入模式等。但是,函数调用要作相应变化

//pe12-2a.c
#include "pe12-2a.h"

void show_info(int mode)
{
    double km, fc;
    printf("Enter distance traveled in kilometers:");
    scanf("%lf", &km);
    printf("Enter fuel consumed in liters:");
    scanf("%lf", &fc);
    if(mode)
    {
        printf("Fuel consumption is %.1lf miles per gallon.\n", km / fc);
    }
    else
    {
        printf("Fuel consumption is %.2lf liters per 100 km.\n", fc / km);
    }
}
//pe12-2a.h
#ifndef DRAFT_PE12_2A_H
#define DRAFT_PE12_2A_H

#include <stdio.h>

void show_info(int mode);

#endif

4.在一个循环中编写并测试一个函数,该函数返回它被调用的次数

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

void func()
{
    static num = 0;
    printf("%d\n", ++num);
}

int main(void)
{
    int n = 0;
    scanf("%d", &n);
    while(n--)
    {
        func();
    }
    return 0;
}

5.编写一个程序,生成100个1~10范围内的随机数,并以降序排列(可以把第11章的排序算法稍加改动,便可用于整数排序,这里仅对整数排序)

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

void qqsort(int a[], int c, int d)
{
    int s = c;
    int e = d;
    if(s < e)
    {
        int t = a[s];
        while (s < e) {
            while (s < e && a[e] <= t) {
                e--;
            }
            a[s] = a[e];
            while (s < e && a[s] >= t) {
                s++;
            }
            a[e] = a[s];
        }
        a[s] = t;
        qqsort(a, c, s - 1);
        qqsort(a, s + 1, d);
    }
}

int main()
{
    srand((unsigned int)time(0));
    int a[101];
    for(int i = 0; i < 100; i++)
    {
        a[i] = rand() % 11 + 1;
    }
    qqsort(a, 0, 99);
    for(int i = 0; i < 100; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}

6.编写一个程序,生成1000个1~10范围内的随机数。不用保存或打印这些数字,仅打印每个数出现的次数。用 10 个不同的种子值运行,生成的数字出现的次数是否相同?可以使用本章自定义的函数或ANSI C的rand()和srand()函数,它们的格式相同。这是一个测试特定随机数生成器随机性的方法

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

int main()
{
    int n;
    for (int i = 0; i < 10; ++i)
    {
        n = 1000;
        srand(i);//这里把i改成time(0)就每次结果都一样- -?
        int *x = calloc(11, sizeof(int));
        while(n--)
        {
            x[rand() % 11 + 1]++;
        }
        for (int j = 1; j < 11; ++j) {
            printf("%d ", x[j]);
        }
        putchar('\n');
        free(x);
    }

}

7.编写一个程序,按照程序清单12.13输出示例后面讨论的内容,修改该程序。使其输出类似:

Enter the number of sets; enter q to stop : 18

How many sides and how many dice? 6 3

Here are 18 sets of 3 6-sided throws.

12 10 6 9 8 14 8 15 9 14 12 17 11 7 10 13 8 14

How many sets? Enter q to stop: q

//main.h
#include <stdio.h>
#include <stdlib.h>    /* 为库函数 srand() 提供原型 */
#include <time.h>     /* 为 time() 提供原型      */
#include "diceroll.h"   /* 为roll_n_dice()提供原型,为roll_count变量提供声明 */
int main(void)
{
    int dice, roll;
    int sides;
    int set;
    srand((unsigned int) time(0)); /* 随机种子 */
    printf("Enter the number of sets; enter q to stop :");
    if(scanf("%d", &set) != 1)
    {
        return 0;
    }
    printf("How many sides and how many dice?");
    while (scanf("%d %d", &sides, &dice) == 2 && sides > 0 && dice > 0)
    {
        printf("Here are %d sets of 3 6-sided throws.\n", set);
        for (int i = 0; i < set; ++i)
        {
            roll = roll_n_dice(dice, sides);
            printf("%d ", roll);
        }
        putchar('\n');
    }
    printf("The rollem() function was called %d times.\n", roll_count);     /* 使用外部变量 */
    printf("GOOD FORTUNE TO YOU!\n");
    return 0;
}
//diceroll
#include "diceroll.h"
#include <stdio.h>
#include <stdlib.h>      /* 提供库函数 rand()的原型 */
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;
}
//diceroll.h
#ifndef DRAFT_DICEROLL_H
#define DRAFT_DICEROLL_H

//diceroll.h
extern int roll_count;
int roll_n_dice(int dice, int sides);

#endif //DRAFT_DICEROLL_H

8.下面是程序的一部分:

// pe12-8.c #include 
#incude <stdio.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;
}

提供make_array()和show_array()函数的定义,完成该程序。make_array()函数接受两个参数,第1个参数是int类型数组的元素个数,第2个参数是要赋给每个元素的值。该函数调用malloc()创建一个大小合适的数组,将其每个元素设置为指定的值,并返回一个指向该数组的指针。show_array()函数显示数组的内容,一行显示8个数

int* make_array(int a, int b)
{
    int *p = (int*)malloc(a * sizeof(int));
    for (int i = 0; i < a; ++i) {
        p[i] = b;
    }
    return p;
}

void show_array(int *a, int b)
{
    for (int i = 0; i < b; ++i) {
        printf("%d ", a[i]);
        if((i + 1) % 8 == 0)
        {
            putchar('\n');
        }
    }
}

9.编写一个符合以下描述的函数。首先,询问用户需要输入多少个单词。然后,接收用户输入的单词,并显示出来,使用malloc()并回答第1个问题(即要输入多少个单词),创建一个动态数组,该数组内含相应的指向char的指针(注意,由于数组的每个元素都是指向char的指针,所以用于储存malloc()返回值的指针应该是一个指向指针的指针,且它所指向的指针指向char)。在读取字符串时,该程序应该把单词读入一个临时的char数组,使用malloc()分配足够的存储空间来储存单词,并把地址存入该指针数组(该数组中每个元素都是指向 char 的指针)。然后,从临时数组中把单词拷贝到动态分配的存储空间中。因此,有一个字符指针数组,每个指针都指向一个对象,该对象的大小正好能容纳被储存的特定单词。下面是该程序的一个运行示例:

How many words do you wish to enter? 5

Enter 5 words now: I enjoyed doing this exerise

Here are your words:

I

enjoyed

doing

this

exercise

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


int main(void)
{
    int n;
    printf("How many words do you wish to enter?");
    scanf("%d", &n);
    printf("Enter 5 words now: ");
    char **a = (char**)malloc(n * sizeof(char*));
    for (int i = 0; i < n; ++i) {
        char b[100];
        scanf("%s", b);
        int n = strlen(b);
        char* str = (char*)malloc(n * sizeof(char));
        for (int j = 0; j < n; ++j) {
            str[j] = b[j];
        }
        a[i] = str;
    }
    for (int k = 0; k < n; ++k) {
        puts(a[k]);
    }
    return 0;
}

 

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值