你也可以上程序咖(https://meta.chengxuka.com)试伙,打開(kāi)大學(xué)幕題板塊析校,不但有答案,講解滥比,還可以在線(xiàn)答題牙咏。
本章習(xí)題均要求用指針?lè)椒ㄌ幚怼?/p>
題目1:輸入3個(gè)整數(shù)臼隔,按由小到大的順序輸出。
解:
答案代碼:
#include <stdio.h>
int main()
{
void swap(int *p1, int *p2);
int n1, n2, n3;
int *p1, *p2, *p3;
printf("input three integer n1,n2,n3:");
scanf("%d,%d,%d", &n1, &n2, &n3);
p1 = &n1;
p2 = &n2;
p3 = &n3;
if (n1 > n2)
swap(p1, p2);
if (n1 > n3)
swap(p1, p3);
if (n2 > n3)
swap(p2, p3);
printf("Now,the order is:%d,%d,%d\n", n1, n2, n3);
return 0;
}
void swap(int *p1, int *p2)
{
int p;
p = *p1;
*p1 = *p2;
*p2 = p;
}
運(yùn)行結(jié)果:
題目2:輸入3個(gè)字符串妄壶,按由小到大的順序輸出摔握。
解:
#include <stdio.h>
#include <string.h>
int main()
{
void swap(char *, char *);
char str1[20], str2[31], str3[20];
printf("input three line:\n");
gets(str1);
gets(str2);
gets(str3);
if (strcmp(str1, str2) > 0)
swap(str1, str2);
if (strcmp(str1, str3) > 0)
swap(str1, str3);
if (strcmp(str2, str3) > 0)
swap(str2, str3);
printf("Now,the order is:\n");
printf("%s\n%s\n%s\n", str1, str2, str3);
return 0;
}
void swap(char *p1, char *p2)
{
char p[20];
strcpy(p, p1);
strcpy(p1, p2);
strcpy(p2, p);
}
運(yùn)行結(jié)果:
輸入3行文字,程序把它們按字母由小到大的順序輸出丁寄。
題目3:輸入10個(gè)整數(shù)氨淌,將其中最小的數(shù)與第一個(gè)數(shù)對(duì)換,把最大的數(shù)與最后一個(gè)數(shù)對(duì)換伊磺。寫(xiě)3 個(gè)函數(shù):
①輸入 10個(gè)數(shù);
②進(jìn)行處理;
③輸出 10 個(gè)數(shù)盛正。
解:
#include <stdio.h>
int main()
{
void input(int *);
void max_min_value(int *);
void output(int *);
int number[10];
input(number); //調(diào)用輸入10 個(gè)數(shù)的函數(shù)
max_min_value(number); //調(diào)用交換函數(shù)
output(number); //調(diào)用輸出函數(shù)
return 0;
}
//輸入10 個(gè)數(shù)的函數(shù)
void input(int *number)
{
int i;
printf("input 10 numbers:");
for (i = 0; i < 10; i++)
scanf("%d", &number[i]);
}
// 交換函數(shù)
void max_min_value(int *number)
{
int *max, *min, *p, temp;
max = min = number; //開(kāi)始時(shí)使 max和 min都指向第1個(gè)數(shù)
for (p = number + 1; p < number + 10; p++)
if (*p > *max)
max = p; //若 p指向的數(shù)大于max指向的數(shù),就使 max指向p指向的大數(shù)
else if (*p < *min)
min = p; //若 p指向的數(shù)小于min指向的數(shù)屑埋,就使 min指向p指向的小數(shù)
temp = number[0]; //將最小數(shù)與第1個(gè)數(shù) number[0]交換
number[0] = *min;
*min = temp;
if (max == number)
max = min; //如果 max和 number相等豪筝,表示第1個(gè)數(shù)是最大數(shù),則使 max指向當(dāng)前的最大數(shù)
temp = number[9]; //將最大數(shù)與最后一個(gè)數(shù)交換
number[9] = *max;
*max = temp;
}
//輸出函數(shù)
void output(int *number)
{
int *p;
printf("Now, they are: ");
for (p = number; p < number + 10; p++)
printf("%d ", *p);
printf("\n");
}
分析:關(guān)鍵在 max_min_value 函數(shù)摘能,請(qǐng)認(rèn)真分析此函數(shù)续崖。形參 number 是指針,局部變量 max团搞,min和 p都定義為指針變量严望,max 用來(lái)指向當(dāng)前最大的數(shù),min 用來(lái)指向當(dāng)前最小的數(shù)逻恐。
number 是第 1 個(gè)數(shù) number[0] 的地址像吻,開(kāi)始時(shí)執(zhí)行 max=min=number 的作用就是使 max 和 min 都指向第 1 個(gè)數(shù) number[0] 。以后使 p 先后指向10個(gè)數(shù)中的第 2~10 個(gè)數(shù)复隆。如果發(fā)現(xiàn)第 2 個(gè)數(shù)比第 1 個(gè)數(shù) number[0] 大拨匆,就使 max 指向這個(gè)大的數(shù),而 min 仍指向第 1 個(gè)數(shù)昏名。如果第 2 個(gè)數(shù)比第. 1個(gè)數(shù) number[0] 小涮雷,就使 min 指向這個(gè)小的數(shù),而 max 仍指向第 1個(gè)數(shù)。然后使 p 移動(dòng)到指向第 3 個(gè)數(shù),處理方法同前堂鲤。直到 p 指向第 10 個(gè)數(shù)碑诉,并比較完畢為止。此時(shí) max. 指向 10個(gè)數(shù)中的最大者,min 指向 10 個(gè)數(shù)中的最小者。假如原來(lái) 10 個(gè)數(shù)是:
32 24 56 78 1 98 36 44 29 6
在經(jīng)過(guò)比較和對(duì)換后,max和 min的指向?yàn)?/p>
32 24 56 78 1 98 36 44 29 6
↑ ↑
min max
此時(shí)蜓竹,將最小數(shù) 1 與第 1 個(gè)數(shù)(即 number[0] )32 交換,將最大數(shù) 98 與最后一個(gè)數(shù) 6 交換。因此應(yīng)執(zhí)行以下兩行:
temp = number[0]; number[0] = *min;*min = temp;//將最小數(shù)與第1個(gè)數(shù) number[0]交換
temp = number[9]; number[9] = *max;*max = temp;//將最大數(shù)與最后一個(gè)數(shù)交換
最后將已改變的數(shù)組輸出俱济。
運(yùn)行結(jié)果:
但是嘶是,有一個(gè)特殊的情況應(yīng)當(dāng)考慮:如果原來(lái) 10 個(gè)數(shù)中第 1 個(gè)數(shù) number[0] 最大,如:
98 24 56 78 1 32 36 44 29 6
在經(jīng)過(guò)比較和對(duì)換后蛛碌,max 和 min 的指向?yàn)?/p>
98 24 56 78 1 32 36 44 29 6
↑ ↑
max min
在執(zhí)行完上面第1行"temp=number[0] ;number[0]=*min;*min=temp;"
后聂喇,最小數(shù) 1 與第 1個(gè)數(shù) number[0] 對(duì)換,這個(gè)最大數(shù)就被調(diào)到后面去了(與最小的數(shù)對(duì)調(diào))蔚携。
1 24 56 78 98 32 36 44 29 6
↑ ↑
max min
請(qǐng)注意:數(shù)組元素的值改變了希太,但是 max 和 min 的指向未變,max 仍指向 number[0]酝蜒。此時(shí)如果接著執(zhí)行下一行:temp= number[9];number[9]=* max;* max= temp;
就會(huì)出問(wèn)題誊辉,因?yàn)榇藭r(shí) max 并不指向最大數(shù),而指向的是第1個(gè)數(shù)亡脑,結(jié)果是將第 1個(gè)數(shù)(最小的數(shù)已調(diào)到此處)與最后一個(gè)數(shù) number[9] 對(duì)調(diào)堕澄。結(jié)果變成:
6 24 56 78 98 32 36 44 29 1
顯然就不對(duì)了。
為此远豺,在以上兩行中間加上一行:
if(max== number)max = min;
由于經(jīng)過(guò)執(zhí)行"temp= number[0]; number[0]=* min;* min=temp;"
后奈偏,10 個(gè)數(shù)的排列為
1 24 56 78 98 32 36 44 29 6
↑ ↑
max min
max指向第 1 個(gè)數(shù),if 語(yǔ)句判別出 max 和 number 相等(即 max 和 number 都指向 number[0] )躯护,而實(shí)際上 max 此時(shí)指向的已非最大數(shù)了,就執(zhí)行"max=min"丽涩,使 max 也指向 min 當(dāng)前的指向棺滞。而 min 原來(lái)是指向最小數(shù)的,剛才與 number[0] 交換矢渊,而 number[0] 原來(lái)是最大數(shù)继准,所以現(xiàn)在 min 指向的是最大數(shù)。執(zhí)行 max=min 后 max也指向這個(gè)最大數(shù)矮男。
1 24 56 78 98 32 36 44 29 6
↑
max,min
然后執(zhí)行下面的語(yǔ)句:
temp = number[9]; number[9]=*max;* max= temp;
這就沒(méi)問(wèn)題了移必,實(shí)現(xiàn)了把最大數(shù)與最后一個(gè)數(shù)交換。
運(yùn)行結(jié)果:
讀者可以將上面的"if(max==number)max=min;" 刪去毡鉴,再運(yùn)行程序崔泵,輸入以上數(shù)據(jù),分析一下結(jié)果猪瞬。
也可以采用另一種方法:先找出 10 個(gè)數(shù)中的最小數(shù)憎瘸,把它和第 1 個(gè)數(shù)交換,然后再重新找 10 個(gè)數(shù)中的最大數(shù)陈瘦,把它和最后一個(gè)數(shù)交換幌甘。這樣就可以避免出現(xiàn)以上的問(wèn)題。重寫(xiě)void max_min_value 函數(shù)如下:
//交換函數(shù)
void max_min_value(int *number)
{
int *max, *min, *p, temp;
max = min = number; //開(kāi)始時(shí)使max和min都指向第1個(gè)數(shù)
for (p = number + 1; p < number + 10; p++)
if (*p < *min) //若p指向的數(shù)小于min指向的數(shù),就使min指向p指向的小數(shù)
min = p;
temp = number[0]; //將最小數(shù)與第1個(gè)數(shù) number[0] 交換
number[0] = *min;
*min = temp;
for (p = number + 1; p < number + 10; p++)
if (*p > *max) //若p指向的數(shù)大于max指向的數(shù)锅风,就使max指向p指向的大數(shù)
max = p;
temp = number[9]; //將最大數(shù)與最后一個(gè)數(shù)交換
number[9] = *max;
*max = temp;
}
這種思路容易理解酥诽。
這道題有些技巧,請(qǐng)讀者仔細(xì)分析皱埠,學(xué)會(huì)分析程序運(yùn)行時(shí)出現(xiàn)的各種情況肮帐,并善于根據(jù)情況予以妥善處理。
題目4:有n個(gè)整數(shù)漱逸,使前面各數(shù)順序向后移 m 個(gè)位置泪姨,最后 m 個(gè)數(shù)變成最前面 m 個(gè)數(shù),見(jiàn)圖 8.43饰抒。寫(xiě)一函數(shù)實(shí)現(xiàn)以上功能肮砾,謎在主函數(shù)中輸入 n個(gè)整數(shù)和輸出調(diào)整后的n個(gè)數(shù)。
解:
答案代碼:
#include <stdio.h>
int main()
{
void move(int[20], int, int);
int number[20], n, m, i;
printf("how many numbers?"); //問(wèn)共有多少個(gè)數(shù)
scanf("%d", &n);
printf("input %d numbers:\n", n);
for (i = 0; i < n; i++)
scanf("%d", &number[i]); //輸入n 個(gè)數(shù)
printf("how many place you want move?"); //問(wèn)后移多少個(gè)位置
scanf("%d", &m);
move(number, n, m); //調(diào)用move 函數(shù)
printf("Now,they are:\n");
for (i = 0; i < n; i++)
printf("%d ", number[i]);
printf("\n");
return 0;
}
//循環(huán)后移一次的函數(shù)
void move(int array[20], int n, int m)
{
int *p, array_end;
array_end = *(array + n - 1);
for (p = array + n - 1; p > array; p--)
*p = *(p - 1);
*array = array_end;
m--;
if (m > 0) //遞歸調(diào)用袋坑,當(dāng)循環(huán)次數(shù)m減至為0時(shí)仗处,停止調(diào)用
move(array, n, m);
}
運(yùn)行結(jié)果:
題目5:有 n 個(gè)人圍成一圈,順序排號(hào)枣宫。從第 1 個(gè)人開(kāi)始報(bào)數(shù)婆誓。(從1到3報(bào)數(shù)),凡報(bào)到3 的 人退出圈子也颤,問(wèn)最后留下的是原來(lái)第幾號(hào)的那位洋幻。
解:N-S圖如圖8.2所示。
答案代碼:
#include <stdio.h>
int main()
{
int i, k, m, n, num[50], *p;
printf("\ninput number of person: n=");
scanf("%d", &n);
p = num;
for (i = 0; i < n; i++)
*(p + i) = i + 1; //以1至 n 為序給每個(gè)人編號(hào)
i = 0; // i為每次循環(huán)時(shí)計(jì)數(shù)變量
k = 0; // k 為按1翅娶,2文留,3報(bào)數(shù)時(shí)的計(jì)數(shù)變量
m = 0; // m為退出人數(shù)
while (m < n - 1) //當(dāng)退出人數(shù)比 n-1少時(shí)(即未退出人數(shù)大于1時(shí))執(zhí)行循環(huán)體
{
if (*(p + i) != 0)
k++;
if (k == 3)
{
*(p + i) = 0; //對(duì)退出的人的編號(hào)置為0
k = 0;
m++;
}
i++;
if (i == n) //報(bào)數(shù)到尾后,i 恢復(fù)為0了
i = 0;
}
while (*p == 0)
p++;
printf("The last one is NO.%d\n", *p);
return 0;
}
運(yùn)行結(jié)果:
題目6:寫(xiě)一函數(shù)竭沫,求一個(gè)字符串的長(zhǎng)度燥翅。在 main 函數(shù)中輸入字符串,并輸出其長(zhǎng)度蜕提。
解:
答案代碼:
#include <stdio.h>
int main()
{
int length(char *p);
int len;
char str[20];
printf("input string: ");
scanf("%s", str);
len = length(str);
printf("The length of string is %d.\n", len);
return 0;
}
//求字符串長(zhǎng)度函數(shù)
int length(char *p)
{
int n;
n = 0;
while (*p != '\0')
{
n++;
p++;
}
return (n);
}
運(yùn)行結(jié)果:
題目7:有一字符串森书,包含 n 個(gè)字符。寫(xiě)一函數(shù)谎势,將此字符串中從第 m 個(gè)字符開(kāi)始的全部字符復(fù)制成為另一個(gè)字符串凛膏。
解:
答案代碼:
#include <stdio.h>
#include <string.h>
int main()
{
void copystr(char *, char *, int);
int m;
char str1[20], str2[20];
printf("input string:");
gets(str1);
printf("which character that begin to copy?");
scanf("%d", &m);
if (strlen(str1) < m)
printf("input error!");
else
{
copystr(str1, str2, m);
printf("result:%s\n", str2);
}
return 0;
}
void copystr(char *p1, char *p2, int m) //字符串部分復(fù)制函數(shù)
{
int n;
n = 0;
while (n < m - 1)
{
n++;
p1++;
}
while (*p1 != '\0')
{
*p2 = *p1;
p1++;
p2++;
}
*p2 = '\0';
}
運(yùn)行結(jié)果:
題目8:輸入一行文字,找出其中大寫(xiě)字母它浅、小寫(xiě)字母译柏、空格、數(shù)字以及其他字符各有多少姐霍。
解:
答案代碼:
#include <stdio.h>
int main()
{
int upper = 0, lower = 0, digit = 0, space = 0, other = 0, i = 0;
char *p, s[20];
printf("input string: ");
while ((s[i] = getchar()) != '\n')
i++;
p = &s[0];
while (*p != '\n')
{
if (('A' <= *p) && (*p <= 'Z'))
++upper;
else if (('a' <= *p) && (*p <= 'z'))
++lower;
else if (*p == ' ')
++space;
else if ((*p <= '9') && (*p >= '0'))
++digit;
else
++other;
p++;
}
printf("upper case:%d lower case:%d", upper, lower);
printf(" space:%d digit:%d other:%d\n", space, digit, other);
return 0;
}
運(yùn)行結(jié)果:
題目9:寫(xiě)一函數(shù)鄙麦,將一個(gè) 3×3 的整型矩陣轉(zhuǎn)置典唇。
解:
答案代碼:
#include <stdio.h>
int main()
{
void move(int *pointer);
int a[3][3], *p, i;
printf("input matrix:\n");
for (i = 0; i < 3; i++)
scanf("%d %d %d", &a[i][0], &a[i][1], &a[i][2]);
p = &a[0][0];
move(p);
printf("Now,matrix:\n");
for (i = 0; i < 3; i++)
printf("%d %d %d\n", a[i][0], a[i][1], a[i][2]);
return 0;
}
void move(int *pointer)
{
int i, j, t;
for (i = 0; i < 3; i++)
for (j = i; j < 3; j++)
{
t = *(pointer + 3 * i + j);
*(pointer + 3 * i + j) = *(pointer + 3 * j + i);
*(pointer + 3 * j + i) = t;
}
}
運(yùn)行結(jié)果:
說(shuō)明: a 是二維數(shù)組,p 和形參 pointer 是指向整型數(shù)據(jù)的指針變量胯府,p 指向數(shù)組 0 行 0 列元素 a[0][0]
介衔。在調(diào)用 move 函數(shù)時(shí),將實(shí)參p的值&a[0][0]
傳遞給形參 pointer骂因,在 move 函數(shù)中將 a[i][j]
與 a[j][i]
的值互換炎咖。由于 a 數(shù)組的大小是 3×3,而數(shù)組元素是按行排列的寒波,因此 a[i][j]
在 a 數(shù)組中是第(3×i+j)個(gè)元素乘盼,例如,a[2][1]
是數(shù)組中第(3×2+1)個(gè)元素俄烁,即第 7 個(gè)元素(序號(hào)從 0 算起)绸栅。a[i][j]
的地址是(pointer十3*i+j
,同理页屠,a[i][j]
的地址是(pointer十3*j+i)
粹胯。將*(pointer+3*i+j)
和*(pointer+3*j+i)
互換,就是將a[i][j]
和 a[j][i]
互換辰企。
題目10:將一個(gè) 5×5 的矩陣中最大的元素放在中心风纠,4 個(gè)角分別放 4 個(gè)最小的元素(順序?yàn)閺淖蟮接遥瑥纳系较乱来螐男〉酱蟠娣牛├蚊常瑢?xiě)一函數(shù)實(shí)現(xiàn)之竹观。用 main 函數(shù)調(diào)用。
解:
答案代碼(1):
#include <stdio.h>
int main()
{
void change(int *p);
int a[5][5], *p, i, j;
printf("input matrix:\n"); //提示輸入二維數(shù)組各元素
for (i = 0; i < 5; i++)
for (j = 0; j < 5; j++)
scanf("%d", &a[i][j]);
p = &a[0][0]; //使p指向0行0列元素
change(p); //調(diào)用change 函數(shù)潜索,實(shí)現(xiàn)交換
printf("Now,matrix:\n");
for (i = 0; i < 5; i++) //輸出已交換的二維數(shù)組
{
for (j = 0; j < 5; j++)
printf("%d ", a[i][j]);
printf("\n");
}
return 0;
}
//交換函數(shù)
void change(int *p)
{
int i, j, temp;
int *pmax, *pmin;
pmax = p;
pmin = p;
for (i = 0; i < 5; i++) //找最大值和最小值的地址栈幸,并賦給 pmax,pmin
for (j = i; j < 5; j++)
{
if (*pmax < *(p + 5 * i + j))
pmax = p + 5 * i + j;
if (*pmin > *(p + 5 * i + j))
pmin = p + 5 * i + j;
}
temp = *(p + 12); //將最大值換給中心元素
*(p + 12) = *pmax;
*pmax = temp;
temp = *p; //將最小值換給左上角元素
*p = *pmin;
*pmin = temp;
pmin = p + 1;
for (i = 0; i < 5; i++) //找第二最小值的地址并賦給 pmin
for (j = 0; j < 5; j++)
if (((p + 5 * i + j) != p) && (*pmin > *(p + 5 * i + j)))
pmin = p + 5 * i + j;
temp = *pmin; //將第二最小值換給右上角元素
*pmin = *(p + 4);
*(p + 4) = temp;
pmin = p + 1;
for (i = 0; i < 5; i++) //找第三最小值的地址并賦給 pmin
for (j = 0; j < 5; j++)
if (((p + 5 * i + j) != (p + 4)) && ((p + 5 * i + j) != p) && (*pmin > *(p + 5 * i + j)))
pmin = p + 5 * i + j;
temp = *pmin; //將第三最小值換給左下角元素
*pmin = *(p + 20);
*(p + 20) = temp;
pmin = p + 1; //找第四最小值的地址并賦給 pmin
for (i = 0; i < 5; i++)
for (j = 0; j < 5; j++)
if (((p + 5 * i + j) != p) && ((p + 5 * i + j) != (p + 4)) && ((p + 5 * i + j) != (p + 20)) && (*pmin > *(p + 5 * i + j)))
pmin = p + 5 * i + j;
temp = *pmin; //將第四最小值換給右下角元素
*pmin = *(p + 24);
*(p + 24) = temp;
}
運(yùn)行結(jié)果:
說(shuō)明:程序中用 change 函數(shù)來(lái)實(shí)現(xiàn)題目所要求的元素值的交換帮辟,分為以下幾個(gè)步驟:
①找出全部元素中的最大值和最小值,將最大值與中心元素互換玩焰,將最小值與左上角元素互換由驹。中心元素的地址為p+12(該元素是數(shù)組中的第 12 個(gè)元素——序號(hào)從 0 算起)。
②找出全部元素中的次小值昔园。由于最小值已找到并放在 a[0][0]
中蔓榄,因此,在這一輪的比較中應(yīng)不包括a[0][0]
默刚,在其余 24 個(gè)元素中值最小的就是全部元素中的次小值甥郑。在雙重 for 循環(huán)中應(yīng)排除 a[0][0]
參加比較。在 if 語(yǔ)句中荤西,只有滿(mǎn)足條件 ((p+5*i+j)!=p)
才進(jìn)行比較澜搅。不難理解伍俘, (p+5*i+j)
就是 &a[i][j]
,p 的值是 &a[0][0]
勉躺。((p+5*i+j)!=p)
意味著在 i 和 j 的當(dāng)前值條件下 &a[i][j]
不等于 &a[0][0]
才滿(mǎn)足條件癌瘾,這樣就排除了 a[0][0]
。因此執(zhí)行雙重 for 循環(huán)后得到次小值饵溅,并將它與右上角元素互換妨退,右上角元素的地址為 p+4。
③找出全部元素中第 3 個(gè)最小值蜕企。此時(shí) a[0][0]
和 a[0][4]
(即左上角和右上角元素)不應(yīng)參加比較咬荷。可以看到∶在 if 語(yǔ)句中規(guī)定轻掩,只有滿(mǎn)足條件 ((p+5*i+j)!=p)&&((p+5*i+j)!=(p+4))
才進(jìn)行比較幸乒。((p+5*i+j)!=p)
的作用是排除 a[0][0]
,((p+5*i+j)!=(p+4))
的作用是排除 a[0][4]
放典。(p+5*i+j)
是 &a[i][j]
逝变,(p+4) 是 &a[0][4]
,即右上角元素的地址奋构。滿(mǎn)足 ((p+5*i+j)!=(p+4))
條件意味著排除了 a[0][4]
壳影。執(zhí)行雙重 for 循環(huán)后得到除了 a[0][0]
和 a[0][4]
外的最小值,也就是全部元素中第 3 個(gè)最小值弥臼,將它與左下角元素互換宴咧,左下角元素的地址為 p+20。
④找出全部元素中第 4 個(gè)最小值径缅。此時(shí) a[0][0]
掺栅,a[0][4]
和 a[4][0]
(即左上角、右上角和左下角元素)不應(yīng)參加比較纳猪,在 if 語(yǔ)句中規(guī)定氧卧,只有滿(mǎn)足條件 ((p+5*i+j)!=p)&&((p+5*i+j)!=(p+4))&&((p+5*i+j)!=(p+20))
才進(jìn)行比較。((p+5*i+j)!=p)
和((p+5*i+j)!=(p+4))
的作用前已說(shuō)明氏堤,((p+5*i+j)!=(p+20))
的作用是排除 a[4][0]
沙绝,理由與前面介紹的類(lèi)似。執(zhí)行雙重 for 循環(huán)后得到除了 a[0][0]
鼠锈,a[0][4]
和 a[4][0]
以外的最小值闪檬,也就是全部元素中第 4 個(gè)最小值,將它與右下角元素互換购笆,左下角元素的地址為 p+24粗悯。
上面所說(shuō)的元素地址是指以元素為單位的地址,p+24 表示從指針 p 當(dāng)前位置向前移動(dòng) 24 個(gè)元素的位置同欠。如果用字節(jié)地址表示样傍,上面右下角元素的字節(jié)地址應(yīng)為 p+4*24横缔,其中4 是整型數(shù)據(jù)所占的字節(jié)數(shù)。
(2)可以改寫(xiě)上面的 if 語(yǔ)句铭乾,change 函數(shù)可以改寫(xiě)如下∶
//交換函數(shù)
void change(int *p)
{
int i, j, temp;
int *pmax, *pmin;
pmax = p;
pmin = p;
for (i = 0; i < 5; i++) //找最大值和最小值的地址剪廉,并賦給 pmax,pmin
for (j = i; j < 5; j++)
{
if (*pmax < *(p + 5 * i + j))
pmax = p + 5 * i + j;
if (*pmin > *(p + 5 * i + j))
pmin = p + 5 * i + j;
}
temp = *(p + 12); //將最大值與中心元素互換
*(p + 12) = *pmax;
*pmax = temp;
temp = *p; //將最小值與左上角元素互換
*p = *pmin;
*pmin = temp;
pmin = p + 1;
//將 a[0][1]的地址賦給 pmin炕檩,從該位置開(kāi)始找最小的元素
for (i = 0; i < 5; i++) //找第二最小值的地址并賦給 pmin
for (j = 0; j < 5; j++)
{
if (i == 0 && j == 0)
continue;
if (*pmin > *(p + 5 * i + j))
pmin = p + 5 * i + j;
}
temp = *pmin; //將第二最小值與右上角元素互換
*pmin = *(p + 4);
*(p + 4) = temp;
pmin = p + 1;
for (i = 0; i < 5; i++) //找第三最小值的地址并賦給 pmin
for (j = 0; j < 5; j++)
{
if ((i == 0 && j == 0) || (i == 0 && j == 4))
continue;
if (*pmin > *(p + 5 * i + j))
pmin = p + 5 * i + j;
}
temp = *pmin; //將第三最小值與左下角元素互換
*pmin = *(p + 20);
*(p + 20) = temp;
pmin = p + 1; //找第四最小值的地址并賦給 pmin
for (i = 0; i < 5; i++)
for (j = 0; j < 5; j++)
{
if ((i == 0 && j == 0) || (i == 0 && j == 4) || (i == 4 && j == 0))
continue;
if (*pmin > *(p + 5 * i + j))
pmin = p + 5 * i + j;
}
temp = *pmin; //將第四最小值與右下角元素互換
*pmin = *(p + 24);
*(p + 24) = temp;
}
這種寫(xiě)法可能更容易為一般讀者所理解斗蒋。
題目11:在主函數(shù)中輸入 10 個(gè)等長(zhǎng)的字符串。用另一函數(shù)對(duì)它們排序笛质。然后在主函數(shù)輸出這 10 個(gè)已排好序的字符串泉沾。
解∶
(1)用字符型二維數(shù)組
答案代碼:
#include <stdio.h>
#include <string.h>
int main()
{
void sort(char s[][6]);
int i;
char str[10][6]; // p 是指向由 6個(gè)元素組成的一維數(shù)組的指針
printf("input 10 strings:\n");
for (i = 0; i < 10; i++)
scanf("%s", str[i]);
sort(str);
printf("Now,the sequence is:\n");
for (i = 0; i < 10; i++)
printf("%s\n", str[i]);
return 0;
}
void sort(char s[10][6]) //形參s是指向由6個(gè)元素組成的一維數(shù)組的指針
{
int i, j;
char *p, temp[10];
p = temp;
for (i = 0; i < 9; i++)
for (j = 0; j < 9 - i; j++)
if (strcmp(s[j], s[j + 1]) > 0)
{
//以下3行是將s[i]指向的一維數(shù)組的內(nèi)容與s[j+1]指向的一維數(shù)組的內(nèi)容互換
strcpy(p, s[j]);
strcpy(s[j], s[+j + 1]);
strcpy(s[j + 1], p);
}
}
運(yùn)行結(jié)果:
(2) 用指向一維數(shù)組的指針作函數(shù)參數(shù)
#include <stdio.h>
#include <string.h>
int main()
{
void
sort(char(*p)[6]);
int i;
char str[10][6];
char(*p)[6];
printf("input 10 strings:\n");
for (i = 0; i < 10; i++)
scanf("%s", str[i]);
p = str;
sort(p);
printf("Now, the sequence is:\n");
for (i = 0; i < 10; i++)
printf("%s\n", str[i]);
return 0;
}
void sort(char (*s)[6])
{
int i, j;
char temp[6], *t = temp;
for (i = 0; i < 9; i++)
for (j = 0; j < 9 - i; j++)
if (strcmp(s[j], s[j + 1]) > 0)
{
strcpy(t, s[j]);
strcpy(s[j], s[+j + 1]);
strcpy(s[j + 1], t);
}
}
運(yùn)行結(jié)果同(1)。
題目12:用指針數(shù)組處理上一題目妇押,字符串不等長(zhǎng)跷究。
解:
答案代碼:
#include <stdio.h>
#include <string.h>
int main()
{
void sort(char *[]);
int i;
char *p[10], str[10][20];
for (i = 0; i < 10; i++)
p[i] = str[i]; //將第i個(gè)字符串的首地址賦予指針數(shù)組 p的第i個(gè)元素
printf("input 10 strings:\n");
for (i = 0; i < 10; i++)
scanf("%s", p[i]);
sort(p);
printf("Now,the sequence is:\n");
for (i = 0; i < 10; i++)
printf("%s\n", p[i]);
return 0;
}
void sort(char *s[])
{
int i, j;
char *temp;
for (i = 0; i < 9; i++)
for (j = 0; j < 9 - i; j++)
if (strcmp(*(s + j), *(s + j + 1)) > 0)
{
temp = *(s + j);
*(s + j) = *(s + j + 1);
*(s + j + 1) = temp;
}
}
運(yùn)行結(jié)果:
題目13:寫(xiě)一個(gè)用矩形法求定積分的通用函數(shù),分別求
說(shuō)明:sin敲霍,cos俊马,exp 函數(shù)已在系 統(tǒng)的數(shù)學(xué)函數(shù)庫(kù)中,程序 開(kāi)頭要用 # include <math.h>肩杈。
解:
可以看出柴我,每次需要求定積分的函數(shù)是不一樣的±┤唬可以編寫(xiě)一個(gè)求定積分的通用函數(shù) integral艘儒,它有3個(gè)形參,即下限 a夫偶、上限 b及指向函數(shù)的指針變量 fun界睁。函數(shù)原型可寫(xiě)為
float integral(float a, float b,float(* fun)());
先后調(diào)用integral函數(shù)3次,每次調(diào)用時(shí)把 a兵拢,b翻斟,sin,cos说铃,exp 之一作為實(shí)參杨赤,把上限、下限及有關(guān)函數(shù)的入口地址傳送給形參 fun截汪。在執(zhí)行 integral 函數(shù)過(guò)程中求出定積分的值。根據(jù)以上思路編寫(xiě)出程序:
#include <stdio.h>
#include <math.h>
int main()
{
float integral(float (*)(float), float, float, int); //對(duì) integarl函數(shù)的聲明
float fsin(float); //對(duì) fsin 函數(shù)的聲明
float fcos(float); //對(duì) fcos 函數(shù)的聲明
float fexp(float); //對(duì)fexp 函數(shù)的聲明
float a1, b1, a2, b2, a3, b3, c, (*p)(float);
int n = 20;
printf("input a1,b1:");
scanf("%f,%f", &a1, &b1); //輸入求 sin(x)定積分的下限和上限
printf("input a2,b2:");
scanf("%f,%f", &a2, &b2); //輸入求 cos(x)定積分的下限和上限
printf("input a3,b3:");
scanf("%f,%f", &a3, &b3); //輸入求e的x次方的定積分的下限和上限
p = fsin; //使p指向 fsin 函數(shù)
c = integral(p, a1, b1, n); //求出 sin(x)的定積分
printf("The integral of sin(x)is:%f\n", c);
p = fcos; //使 p指向fcos 函數(shù)
c = integral(p, a2, b2, n); //求出 cos(x)的定積分
printf("The integral of cos(x)is:%f\n", c);
p = fexp; //使p指向 fexp 函數(shù)
c = integral(p, a3, b3, n); //求出e的x次方的定積分
printf("The integral of exp(x)is:%f\n", c);
return 0;
}
//下面是用矩形法求定積分的通用函數(shù)
float integral(float (*p)(float), float a, float b, int n)
{
int i;
float x, h, s;
h = (b - a) / n;
x = a;
s = 0;
for (i = 1; i <= n; i++)
{
x = x + h;
s = s + (*p)(x)*h;
}
return (s);
}
float fsin(float x) //計(jì)算 sin(x)的函數(shù)
{
return sin(x);
}
float fcos(float x) //計(jì)算 cos(x)的函數(shù)
{
return cos(x);
}
float fexp(float x) //計(jì)算e的 x次方的函數(shù)
{
return exp(x);
}
運(yùn)行結(jié)果:
說(shuō)明:sin植捎,cos 和 exp 是系統(tǒng)提供的數(shù)學(xué)函數(shù)衙解,在程序中定義3 個(gè)函數(shù),即 fsin焰枢,fcos 和 fexp蚓峦。分別用來(lái)計(jì)算 sin(x) 舌剂,cos(x) 和exp(x) 的值。在 main 函數(shù)中要對(duì)這 3 個(gè)函數(shù)作聲明暑椰。在 main 函數(shù)定義中 p為指向函數(shù)的指針變量霍转,定義形式是"float(*p)(float)"
,表示 p 指向的函數(shù)有一個(gè)實(shí)型形參一汽,p 指向返回值為實(shí)型的函數(shù)避消。在 main 函數(shù)中有"p=fsin;",表示將 fsin 函數(shù)的入口地址傳賦給 p召夹,在調(diào)用 integral 函數(shù)時(shí)岩喷,用 p 作為實(shí)參,把 fsin 函數(shù)的入口地址傳遞給形參 p(相當(dāng)于 fsin(x) 监憎。fsin(x) 的值就是 sin(x)的值纱意。因此通過(guò)調(diào)用 integral 函數(shù)求出 sin(x) 的定積分。求其余兩個(gè)函數(shù)的定積分的情況與此類(lèi)似鲸阔。
題目14:將 n 個(gè)數(shù)按輸入時(shí)順序的逆序排列偷霉,用函數(shù)實(shí)現(xiàn)。
解:
答案代碼:
#include <stdio.h>
int main()
{
void sort(char *p, int m);
int i, n;
char *p, num[20];
printf("input n:");
scanf("%d", &n);
printf("please input these numbers: \n");
for (i = 0; i < n; i++)
scanf("%d", &num[i]);
p = &num[0];
sort(p, n);
printf("Now,the sequence is:\n");
for (i = 0; i < n; i++)
printf("%d ", num[i]);
printf("\n");
return 0;
}
//將n 個(gè)數(shù)逆序排列函數(shù)
void sort(char *p, int m)
{
int i;
char temp, *p1, *p2;
for (i = 0; i < m / 2; i++)
{
p1 = p + i;
p2 = p + (m - 1 - i);
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
}
運(yùn)行結(jié)果:
題目15:有一個(gè)班 4 個(gè)學(xué)生褐筛,5 門(mén)課程类少。
①求第 1 門(mén)課程的平均分;
②找出有兩門(mén)以上課程不及格的學(xué)生,輸出他們的學(xué)號(hào)和全部課程成績(jī)及平均成績(jī);
③找出平均成績(jī)?cè)?90 分以上或全部課程成績(jī)?cè)?85分以上的學(xué)生死讹。
分別編3個(gè)函數(shù)實(shí)現(xiàn)以上 3個(gè)要求专缠。
解:
答案代碼:
#include <stdio.h>
int main()
{
void avsco(float *, float *); //函數(shù)聲明
void avcour1(char(*)[10], float *); //函數(shù)聲明
void fali2(char course[5][10], int num[], float *pscore, float aver[4]); //函數(shù)聲明
void good(char course[5][10], int num[4], float *pscore, float aver[4]); //函數(shù)聲明
int i, j, *pnum, num[4];
float score[4][5], aver[4], *pscore, *paver;
char course[5][10], (*pcourse)[10];
printf("input course:\n");
pcourse = course;
for (i = 0; i < 5; i++)
scanf("%s", course[i]);
printf("input NO. and scores:\n");
printf("NO.");
for (i = 0; i < 5; i++)
printf(",%s", course[i]);
printf("\n");
pscore = &score[0][0];
pnum = &num[0];
for (i = 0; i < 4; i++)
{
scanf("%d", pnum + i);
for (j = 0; j < 5; j++)
scanf("%f", pscore + 5 * i + j);
}
paver = &aver[0];
printf("\n\n");
avsco(pscore, paver); //求出每個(gè)學(xué)生的平均成績(jī)
avcour1(pcourse, pscore); //求出第 1 門(mén)課的平均成績(jī)
printf("\n\n");
fali2(pcourse, pnum, pscore, paver); //找出兩門(mén)課不及格的學(xué)生
printf("\n\n");
good(pcourse, pnum, pscore, paver); //找出成績(jī)好的學(xué)生
return 0;
}
//求每個(gè)學(xué)生的平均成績(jī)的函數(shù)
void avsco(float *pscore, float *paver)
{
int i, j;
float sum, average;
for (i = 0; i < 4; i++)
{
sum = 0.0;
for (j = 0; j < 5; j++)
sum = sum + (*(pscore + 5 * i + j)); //累計(jì)每個(gè)學(xué)生的各科成績(jī)
average = sum / 5; //計(jì)算平均成績(jī)
*(paver + i) = average;
}
}
//求第1課程的平均成績(jī)的函數(shù)
void avcour1(char (*pcourse)[10], float *pscore)
{
int i;
float sum, average1;
sum = 0.0;
for (i = 0; i < 4; i++)
sum = sum + (*(pscore + 5 * i)); //累計(jì)每個(gè)學(xué)生的得分
average1 = sum / 4; //計(jì)算平均成績(jī)
printf("course 1:%s average score:%7.2f\n", *pcourse, average1);
}
//找兩門(mén)以上課程不及格的學(xué)生的函數(shù)
void fali2(char course[5][10], int num[], float *pscore, float aver[4])
{
int i, j, k, label;
printf(" ======Student who is fail in two courses ======\n");
printf("NO. ");
for (i = 0; i < 5; i++)
printf("%11s", course[i]);
printf(" average\n");
for (i = 0; i < 4; i++)
{
label = 0;
for (j = 0; j < 5; j++)
if (*(pscore + 5 * i + j) < 60.0)
label++;
if (label >= 2)
{
printf("%d", num[i]);
for (k = 0; k < 5; k++)
printf("%11.2f", *(pscore + 5 * i + k));
printf("%11.2f\n ", aver[i]);
}
}
}
//找成績(jī)優(yōu)秀學(xué)生(各門(mén)85分以上或平均 90分以上)的函數(shù)
void good(char course[5][10], int num[4], float *pscore, float aver[4])
{
int i, j, k, n;
printf(" ======Students whose score is good ======\n");
printf("NO. ");
for (i = 0; i < 5; i++)
printf("%11s", course[i]);
printf(" average\n");
for (i = 0; i < 4; i++)
{
n = 0;
for (j = 0; j < 5; j++)
if (*(pscore + 5 * i + j) > 85.0)
n++;
if ((n == 5) || (aver[i] >= 90))
{
printf("%d", num[i]);
for (k = 0; k < 5; k++)
printf("%11.2f", *(pscore + 5 * i + k));
printf("%11.2f\n", aver[i]);
}
}
}
運(yùn)行結(jié)果:
程序中 num 是存放 4 個(gè)學(xué)生學(xué)號(hào)的一維數(shù)組,course 是存放 5 門(mén)課名稱(chēng)的二維字符數(shù)組苟穆,score 是存放 4 個(gè)學(xué)生 5 門(mén)課成績(jī)的二維數(shù)組甲喝,aver 是存放每個(gè)學(xué)生平均成績(jī)的數(shù)組。pnum 是指向 num數(shù)組的指針變量愧旦,pcou 是指向 course 數(shù)組的指針變量世剖,psco 是指向 score 數(shù)組的指針變量,pave是指向 aver 數(shù)組的指針變量笤虫,見(jiàn)圖8.3旁瘫。
函數(shù)的形參用數(shù)組,調(diào)用函數(shù)時(shí)的實(shí)參用指針變量琼蚯。形參也可以不用數(shù)組而用指針變量酬凳,請(qǐng)讀者自己分析。
題目16:輸入一個(gè)字符串遭庶,內(nèi)有數(shù)字和非數(shù)字字符宁仔,例如∶
A123x456 17960?302tab5876
將其中連續(xù)的數(shù)字作為一個(gè)整數(shù),依次存放到一數(shù)組 a 中峦睡。例如翎苫,123放在 a[0]权埠,456放在a[1]……統(tǒng)計(jì)共有多少個(gè)整數(shù),并輸出這些數(shù)煎谍。
解∶
答案代碼:
#include <stdio.h>
int main()
{
char str[50], *pstr;
int i, j, k, m, e10, digit, ndigit, a[10], *pa;
printf("input a string:\n");
gets(str);
pstr = &str[0]; //字符指針 pstr置于數(shù)組 str 首地址
pa = &a[0]; //指針 pa 置于a數(shù)組首地址
ndigit = 0; // ndigit 代表有多少個(gè)整數(shù)
i = 0; //代表字符串中的第幾個(gè)字符
j = 0;
while (*(pstr + i) != '\0')
{
if ((*(pstr + i) >= '0') && (*(pstr + i) <= '9'))
j++;
else
{
if (j > 0)
{
digit = *(pstr + i - 1) - 48; //將個(gè)數(shù)位賦予digit
k = 1;
while (k < j) //將含有兩位以上數(shù)的其他位的數(shù)值累加于digit
{
e10 = 1;
for (m = 1; m <= k; m++)
e10 = e10 * 10; // e10 代表該位數(shù)所應(yīng)乘的因子
digit = digit + (*(pstr + i - 1 - k) - 48) * e10; //將該位數(shù)的數(shù)值\累加于 digit
k++; //位數(shù)k自增
}
*pa = digit; //將數(shù)值賦予數(shù)組 a
ndigit++;
pa++; //指針 pa 指向 a數(shù)組下一元素
j = 0;
}
}
i++;
}
if (j > 0) //以數(shù)字結(jié)尾字符串的最后一個(gè)數(shù)據(jù)
{
digit = *(pstr + i - 1) - 48; //將個(gè)數(shù)位賦予 digit
k = 1;
while (k < j)
{
e10 = 1; //將含有兩位以上數(shù)的其他位的數(shù)值累加于 digit
for (m = 1; m <= k; m++)
e10 = e10 * 10; // e10代表位數(shù)所應(yīng)乘的因子
digit = digit + (*(pstr + i - 1 - k) - 48) * e10; //將該位數(shù)的數(shù)值累加于 digit
k++; //位數(shù)k自增
}
*pa = digit; //將數(shù)值賦予數(shù)組 a
ndigit++;
j = 0;
}
printf("There are %d numbers in this line, they are:\n", ndigit);
j = 0;
pa = &a[0];
for (j = 0; j < ndigit; j++) //輸出打印數(shù)據(jù)
printf("%d ", *(pa + j));
printf("\n");
return 0;
}
運(yùn)行結(jié)果:
題目17:寫(xiě)一函數(shù)攘蔽,實(shí)現(xiàn)兩個(gè)字符串的比較。即自己寫(xiě)一個(gè) strcmp 函數(shù)呐粘,函數(shù)原型為
int strcmp(char * p1,char * p2);
設(shè) p1指向字符串sl满俗,p2指向字符串s2。要求當(dāng)s1=s2時(shí)事哭,返回值為0;若 s1≠s2漫雷,返回它們二者第 1 個(gè)不同字符的 ASCII 碼差值(如"BOY"與"BAD",第 2個(gè)字母不同鳍咱,O與 A 之差為79-65=14)降盹。如果 s1>s2,則輸出正值;如果 s1<s2谤辜,則輸出負(fù)值蓄坏。
解:
答案代碼:
#include <stdio.h>
int main()
{
int m;
char str1[20], str2[20], *p1, *p2;
printf("input two strings:\n");
scanf("%s", str1);
scanf("%s", str2);
p1 = &str1[0];
p2 = &str2[0];
m = strcmp(p1, p2);
printf("result:%d,\n", m);
return 0;
} //兩個(gè)字符串比較函數(shù)
strcmp(char *p1, char *p2)
{
int i;
i = 0;
while (*(p1 + i) == *(p2 + i))
if (*(p1 + i++) == '\0') //相等時(shí)返回結(jié)果0
return (0);
return (*(p1 + i) - *(p2 + i)); /*不等時(shí)返回結(jié)果為第一個(gè)不等字符ASCII碼的差值 */
}
運(yùn)行結(jié)果∶
①:
②:
題目18:編一程序,輸入月份號(hào)丑念,輸出該月的英文月名涡戳。例如,輸入 3脯倚,則輸出"March"渔彰,要求用指針數(shù)組處理。
解:
答案代碼:
#include <stdio.h>
int main()
{
char *month_name[13] = {"illegal month ", " January", " February", " March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
int n;
printf("input month:\n");
scanf("%d", &n);
if ((n <= 12) && (n >= 1))
printf("It is %s.\n", *(month_name + n));
else
printf("It is wrong.\n");
return 0;
}
運(yùn)行結(jié)果∶
①:
②:
③:
題目19:(1)編寫(xiě)一個(gè)函數(shù) new推正,對(duì) n 個(gè)字符開(kāi)辟連續(xù)的存儲(chǔ)空間恍涂,此函數(shù)應(yīng)返回一個(gè)指針(地址),指向字符串開(kāi)始的空間植榕。new(n)表示分配 n 個(gè)字節(jié)的內(nèi)存空間再沧。(2)寫(xiě)一函數(shù) free;將 前面用 new 函數(shù)占用的空間釋放。free(p)表示將 p(地址))指向的單元以后的內(nèi)存段釋放尊残。
解∶
(1)編寫(xiě)函數(shù)new 程序如下∶
#include <stdio.h>
#define NEWSIZE 1000 //指定開(kāi)辟存儲(chǔ)區(qū)的最大容量
char newbuf[NEWSIZE]; //定義字符數(shù)組 newbuf
char *newp = newbuf; //定義指針變量 newp炒瘸,指向可存儲(chǔ)區(qū)的始端
//定義開(kāi)辟存儲(chǔ)區(qū)的函數(shù) new,開(kāi)辟存儲(chǔ)區(qū)后返回指針
char *new (int n)
{
if (newp + n <= newbuf + NEWSIZE) //開(kāi)辟區(qū)未超過(guò) newbuf 數(shù)組的大小
{
newp += n; // newp指向存儲(chǔ)區(qū)的末尾
return (newp - n); //返回一個(gè)指針寝衫,它指向存儲(chǔ)區(qū)的開(kāi)始位置
}
else
return (NULL); //當(dāng)存儲(chǔ)區(qū)不夠分配時(shí)顷扩,返回一個(gè)空指針
}
new 函數(shù)的作用是:分配 n 個(gè)連續(xù)字符的存儲(chǔ)空間。為此慰毅,應(yīng)先開(kāi)辟一個(gè)足夠大的連續(xù)存儲(chǔ)區(qū)屎即,今設(shè)置字符數(shù)組 newbuf[1000],new 函數(shù)將在此范圍內(nèi)進(jìn)行操作。指針變量 newp 開(kāi)始指向存儲(chǔ)區(qū)首字節(jié)技俐。在每當(dāng)請(qǐng)求用 new 函數(shù)開(kāi)辟 n 個(gè)字符的存儲(chǔ)區(qū)時(shí),要先檢查一下 newbuf 數(shù)組是否還有足夠的可用空間统台。若有雕擂,則使指針變量 newp 指向開(kāi)辟區(qū)的末尾(newp=newp十n),見(jiàn)圖8.4中的 newp 贱勃。此時(shí) newp 指向下面的空白(未分配)的區(qū)域的開(kāi)頭井赌,即 newp 的值是下一次可用空間的開(kāi)始地址。如果再一次調(diào)用 new 函數(shù)贵扰,就從 newp 最后所指向的字節(jié)開(kāi)始分配下一個(gè)開(kāi)辟區(qū)仇穗。如果若存儲(chǔ)區(qū)不夠分配,則返回 NULL戚绕,表示開(kāi)辟失敗纹坐。
new返回一個(gè)指向字符型數(shù)據(jù)的指針,指向新開(kāi)辟的區(qū)域的首字節(jié)舞丛。
在主函數(shù)中可以用以下語(yǔ)句:
pt = new(n);
把新開(kāi)辟的區(qū)域首字節(jié)的地址賦給 pt耘子,使指針變量 pt 也指向新開(kāi)辟的區(qū)域的開(kāi)頭。
(2)編寫(xiě)函數(shù) free
free 的作用是使newp 的值恢復(fù)為p球切。
free 函數(shù)如下∶
#include <stdio.h>
#define NEWSIZE 1000
char newbuf[NEWSIZE];
char *newp = newbuf;
//釋放存區(qū)函數(shù)
void free(char *p)
{
if (p >= newbuf && p < newbuf + NEWSIZE)
newp = p;
}
在主函數(shù)中用以下語(yǔ)句指令釋放 pt 指向的存儲(chǔ)區(qū)谷誓。
free(pt);
調(diào)用 free時(shí),實(shí)參 pt 的值傳給形參 p吨凑,因此 p的值也是新開(kāi)辟的區(qū)域首字節(jié)的地址捍歪。用 if 語(yǔ)句檢查 p 是否在已開(kāi)辟區(qū)的范圍內(nèi)(否則不合法,不能釋放未分配的區(qū)域)鸵钝。如果確認(rèn) p 在上述范圍內(nèi)糙臼,就把 p(即 pt)的值賦給 newp,使 newp 重新指向原來(lái)開(kāi)辟區(qū)的開(kāi)頭蒋伦,這樣弓摘,下次再開(kāi)辟新區(qū)域時(shí)就又從 newp 指向的字節(jié)開(kāi)始分配,這就相當(dāng)于釋放了此段空間痕届,使這段空間可再分配作其他用途韧献。
有人可能對(duì) if語(yǔ)句所檢查的條件 "p>=newbuf && p<newbuf + NEWSIZE" 不理解,為什么不直接檢查 "p==newbuf" 呢?他們認(rèn)為 p 應(yīng)當(dāng)指向 newbuf 的開(kāi)頭研叫。這里有個(gè)細(xì)節(jié)要考慮∶當(dāng)?shù)?1 次調(diào)用 new 函數(shù)開(kāi)辟存儲(chǔ)區(qū)時(shí)锤窑,new 函數(shù)的返回值(也是 pt 的值)的確是 newbuf。但是如果接著再開(kāi)辟第 2 個(gè)存儲(chǔ)區(qū)嚷炉,new 函數(shù)的返回值(也是 pt 的值)就不是newbuf了渊啰,而是指針變量 newp的當(dāng)前值,即 newbuf+n了。因此绘证,調(diào)用free 函數(shù)時(shí)隧膏,形參p得到的值也是第 2個(gè)存儲(chǔ)區(qū)的起始地址。要釋放的是第 2個(gè)存儲(chǔ)區(qū)嚷那,而不是第1個(gè)存儲(chǔ)區(qū)胞枕。但p的值必然在"newbuf 到 newbuf+NEWSIZE"的范圍內(nèi)。
上面只是編寫(xiě)了兩個(gè)函數(shù)魏宽,并不是完整的程序腐泻,它沒(méi)有main 函數(shù)。本題是示意性的队询,可以大體了解開(kāi)辟存儲(chǔ)區(qū)的思路派桩。
題目20:用指向指針的指針的方法對(duì) 5個(gè)字符串排序并輸出。
解:
程序如下
#include <stdio.h>
#include <string.h>
#define LINEMAX 20 //定義字符串的最大長(zhǎng)度
int main()
{
void sort(char **p);
int i;
char **p, *pstr[5], str[5][LINEMAX];
for (i = 0; i < 5; i++)
pstr[i] = str[i]; //將第i個(gè)字符串的首地址賦予指針數(shù)組 pstr 的第i個(gè)元素
printf("input 5 strings:\n");
for (i = 0; i < 5; i++)
scanf("%s", pstr[i]);
p = pstr;
sort(p);
printf("\nstrings sorted:\n");
for (i = 0; i < 5; i++)
printf("%s\n", pstr[i]);
return 0;
}
//用冒泡法對(duì)5個(gè)字符串排序函數(shù)
void sort(char **p)
{
int i, j;
char *temp;
for (i = 0; i < 5; i++)
{
for (j = i + 1; j < 5; j++) //比較后交換字符串地址
{
if (strcmp(*(p + i), *(p + j)) > 0)
{
temp = *(p + i);
*(p + i) = *(p + j);
*(p + j) = temp;
}
}
}
}
運(yùn)行結(jié)果:
題目21:用指向指針的指針的方法對(duì) n個(gè)整數(shù)排序并輸出蚌斩。要求將排序單獨(dú)寫(xiě)成一個(gè)函數(shù)铆惑。n 個(gè)整數(shù)在主函數(shù)中輸入,最后在主函數(shù)中輸出凳寺。
解:
答案代碼:
#include <stdio.h>
int main()
{
void sort(int **p, int n);
int i, n, data[20], **p, *pstr[20];
printf("input n:\n");
scanf("%d", &n);
for (i = 0; i < n; i++)
pstr[i] = &data[i]; //將第i個(gè)整數(shù)的地址賦予指針數(shù)組 pstr 的第i個(gè)元素
printf("input %d integer numbers:", n);
for (i = 0; i < n; i++)
scanf("%d", pstr[i]);
p = pstr;
sort(p, n);
printf("Now,the sequence is:\n");
for (i = 0; i < n; i++)
printf("%d ", *pstr[i]);
printf("\n");
return 0;
}
void sort(int **p, int n)
{
int i, j, *temp;
for (i = 0; i < n - 1; i++)
{
for (j = i + 1; j < n; j++)
{
if (**(p + i) > **(p + j)) //比較后交換整數(shù)地址
{
temp = *(p + i);
*(p + i) = *(p + j);
*(p + j) = temp;
}
}
}
}
運(yùn)行結(jié)果:
data數(shù)組用來(lái)存放n個(gè)整數(shù)鸭津,pstr 是指針數(shù)組,每一個(gè)元素指向 data 數(shù)組中的一個(gè)元素肠缨,p 是指向指針的指針逆趋,請(qǐng)參考圖8.5。圖8.5(a)表示的是排序前的情況晒奕,圖8.5(b)表示的是排序后的情況闻书。可以看到脑慧,data 數(shù)組中的數(shù)的順序沒(méi)有變化魄眉,而 pstr 指針數(shù)組中的各元素的值(也就是它們的指向)改變了。