《C Primer Plus》第12章复习题与编程练习

《C Primer Plus》第12章复习题与编程练习

复习题

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中daisy对main()和petal()可见,文件2中以extern声明的daisy才对stem()、root()可见
文件1中main()中的lily仅对main()函数可见
文件2中的lily,rose对文件2中的stem()和root()可见,其中stem()中声明的rose只对stem()可见
2)
文件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.
定义一个名为plink的内部链接的存储变量
定义一个函数名为value_ct的函数,该函数第一个参数为int型的数组,且在函数执行过程中该数组内容不可改变,第二参数和第三个参数都是int型变量,该函数返回一个int型的值
b.
否,形参的值改变并不改变实参的值

编程练习

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

代码:

#include <stdio.h>
#include <stdlib.h>
void critic(int *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");

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

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

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

代码:

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

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

代码:

// pe12-2a.h
#ifndef DRAFT_PE12_2A_H
#define DRAFT_PE12_2A_H

#include <stdio.h>

void show_info(int mode);

#endif
// 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);
    }
}

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

代码:

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

void func()
{
    static int num = 0;
    printf("this function has ran %d times.\n", ++num);
}

int main(void)
{
    int n = 0;

    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        func();
    }

    system("pause");
    return 0;
}

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

代码:

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

int cmpfunc(const void *a, const void *b)
{
    return (*(int *)b - *(int *)a);
}

int main()
{
    int value[100];

    for (int i = 0; i < 100; i++)
    {
        value[i] = rand() % 10 + 1;
    }
    qsort(value, 100, sizeof(int), cmpfunc);
    for (int i = 0; i < 100; i++)
    {
        printf("%d ", value[i]);
    }
    
    system("pause");
    return 0;
}

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);
        // srand(time(0));
        int *x = (int *)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);
    }

    system("pause");
    return 0;
}

当把随机种子设置为srand(i)时,每次生成的数字出现的次数不同;

在这里插入图片描述

当把随机种子设置为srand(time(0))时,每次生成的数字出现的次数相同;

在这里插入图片描述

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

代码:

// diceroll.h
#ifndef DRAFT_DICEROLL_H
#define DRAFT_DICEROLL_H

extern int roll_count;
int roll_n_dice(int dice, int sides);

#endif
// diceroll.c
#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;
}
// main.c
#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");

    system("pause");
    return 0;
}

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

// pe12-8.c
#include <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 elem, int val)
{
    int *p = (int *)malloc(elem * sizeof(int));
    for (int i = 0; i < elem; i++)
    {
        p[i] = val;
    }
    return p;
}

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

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 %d words now:\n", n);
    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 + 1) * sizeof(char));
        for (int j = 0; j < n; j++)
        {
            str[j] = b[j];
        }
        str[n] = '\0';
        a[i] = str;
    }
    printf("Here are your words:\n");
    for (int i = 0; i < n; i++)
    {
        printf("%s\n", a[i]);
    }

    system("pause");
    return 0;
}

运行结果:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

UestcXiye

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

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

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

打赏作者

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

抵扣说明:

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

余额充值