C Primer Plus 第十二章 課後答案
阿新 • • 發佈:2018-12-13
目錄
複習題
1.哪些類別的變數可以成為它所在函式的區域性變數?
- 自動儲存類別
- 暫存器儲存類別
- 靜態、無連結儲存類別
2.哪些類別的變數在它所在程式的執行期一直存在?
- 靜態、無連結儲存類別
- 靜態、內部連結儲存類別
- 靜態、外部連結儲存類別
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()可見//12.1.7 【附錄A中的答案給的是petal()中也要以extern宣告,但書上12.1.7說是可選的宣告不是必須的宣告】
- 檔案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)
{
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;
}