• 沒有找到結果。

练习参考答案

在文檔中 第 8 章 指针 (頁 22-27)

8.3 练习与习题答案

8.3.1 练习参考答案

8-1 如果有定义:int m, n = 5, *p = &m; 与 m = n 等价的语句是 B 。 A.m = *p; B. *p = *&n; C. m = &n; D. m = **p;

8-2 调用函数求两个数的和与差:计算输入的两个数的和与差,要求自定义一个函数 sum_diff(float op1, float op2, float *psum, float *pdiff),其中 op1 和 op2 是输入的两个数,

*psum 和*pdiff 是计算得出的和与差。

解答:

#include <stdio.h>

int main (void) {

float op1, op2, sum, diff;

void sum_diff(float op1, float op2, float *psum, float *pdiff);

printf(“input op1 and op2: “);

scanf(“%f%f”, &op1, &op2);

sum_diff(op1, op2, &sum, &diff);

printf(“%f+%f=%f; %f-%f=%f \n”,op1,op2,sum,op1,op2,diff);

return 0;

}

void sum_diff(float op1, float op2, float *psum, float *pdiff) {

*psum = op1 + op2;

*pdiff = op1 – op2;

}

8-3 两个相同类型的指针变量能不能相加?为什么?

解答:不能。因为指针变量是一种特殊的变量,指针变量的值存放的是所指向变量的地址,

两个地址相加并不能保证结果为一个有效的地址值,因而在 C 语言中指针变量相加是非法

的。

8-4 根据表 8.2 所示,这组数据的冒泡排序其实循环到第 6 遍(即 n-2)时就已经排好序了,

说明有时候并不一定需要n-1 次循环。请思考如何改进冒泡排序算法并编程实现(提示:当

发现一遍循环后没有数据发生交换,说明已经排好序了)。

解答:设置一个标志变量flag,进入一轮循环前设置为 0,在循环中有发生数据交换就改写

flag 值为 1。当该轮循环结束后检查 flag 值,如果变为 1 说明发生了数据交换,还没有排好

序,如果为0 说明没有发生交换,已经排好序。

#include <stdio.h>

void bubble (int a[ ], int n);

int main(void) {

int n, a[8];

int i;

printf("Enter n (n<=8): ");

scanf("%d", &n);

printf("Enter a[%d] : ",n);

for (i=0; i<n;i++) scanf("%d",&a[i]);

bubble(a,n);

printf("After sorted, a[%d] = ", n);

for (i=0; i<n; i++) printf("%3d",a[i]);

return 0;

}

void bubble (int a[ ], int n) /* n 是数组 a 中待排序元素的数量 */

{

int i, j, t, flag;

for( i = 1; i < n; i++ ) { /* 外部循环 */

flag=0;

for (j = 0; j < n-i; j++ ) /* 内部循环 */

if (a[j] > a[j+1]){ /* 比较两个元素的大小 */

t=a[j]; a[j]=a[j+1]; a[j+1]=t; /* 如果前一个元素大,则交换 */

flag=1; /* 发生交换,flag 置为 1 */

}

if (flag==0) /* 如果一轮循环没有发生数据交换,排序结束*/

break;

} }

8-5 重做例 8-5,要求使用选择排序算法。

解答:

#include <stdio.h>

void bubble (int a[ ], int n);

int main(void) {

int n, a[8];

int i;

printf("Enter n (n<=8): ");

scanf("%d", &n);

printf("Enter a[%d] : ",n);

for (i=0; i<n;i++) scanf("%d",&a[i]);

bubble(a,n);

printf("After sorted, a[%d] = ", n);

for (i=0; i<n; i++) printf("%3d",a[i]);

return 0;

}

void bubble (int a[ ], int n) /* n 是数组 a 中待排序元素的数量 */

{

int i, j, t, index;

for( i = 0; i < n-1; i++ ) { /* 外部循环 */

index=i;

for (j = i+1; j < n; j++ ) /* 内部循环 */

if (a[j] < a[index]) index = j;

t=a[i]; a[i]=a[index]; a[index]=t;

} }

8-6 在使用 scanf()函数时,输入参数列表需要使用取地址操作符&,但当参数为字符数组名 时并没有使用,为什么?如果在字符数组名前加上取地址操作符&,会发生什么?

解答:

因为字符数组名的值是一个特殊的固定地址,可以看作是常量指针,因此不需要再使用 取地址符来获取该数组的地址。

如果在字符数组名str 前加上取地址操作符&,那么对其取地址&str 可以看做是这个数 组的第一个元素的地址,由于数组地址和数组第一个元素的地址相同,所以&str 表示地址值

和str 表示的地址值是相等的。对 scanf()的变长参数列表的话,编译器只负责参数传递,怎

么解释后边的几个地址的含义, 是由前边的字符串确定的。所以使用 scanf(“%s”,str)和 scanf(“%s”,&str)都能通过编译且正常执行。

8-7 C 语言不允许用赋值表达式直接对数组赋值,为什么?

解答:

数组名可以看作是常量指针,因为不可以对一个常量进行赋值,所以不允许用赋值表达 式直接对数组进行赋值。

8-8 输入一个字符串,把该字符串的前 3 个字母移到最后,输出变换后的字符串。比如输入

“abcdef”,输出为“defabc”。

解答:

#include <stdio.h>

#include <string.h>

#define MAXS 10 void Shift( char s[] );

void GetString( char s[] );

int main() {

char s[MAXS];

GetString(s);

Shift(s);

printf("%s\n", s);

return 0;

}

void Shift( char s[] ) {

char str[4];

int i;

for (i=0;i<3;i++)

str[i]=s[i];

str[i]='\0';

for(i=3; s[i]!='\0';i++) s[i-3]=s[i];

s[i-3]= '\0';

strcat(s,str);

}

void GetString( char s[] ) { gets(s);

}

8-9 使用动态内存分配的方法实现例 8-5 的冒泡排序。

解答:

#include <stdio.h>

#include <stdlib.h>

void bubble (int a[ ], int n);

int main(void) {

int n, *p;

int i;

printf("input n : ");

scanf("%d", &n);

/*为数组 p 动态分配 n 个整数类型大小的空间 */

if ((p=(int *)calloc(n, sizeof(int))) == NULL) { printf("Not able to allocate memory. \n");

exit(1);

}

printf("input %d integers : ",n);

for (i=0; i<n;i++) scanf("%d",p+i);

bubble(p,n);

printf("After sorted : ");

for (i=0; i<n; i++)

printf("%3d",*(p+i));

free(p);

return 0;

}

void bubble (int a[ ], int n) /* n 是数组 a 中待排序元素的数量 */

{

int i, j, t;

for( i = 1; i < n; i++ ) /* 外部循环 */

for (j = 0; j < n-i; j++ ) /* 内部循环 */

if (a[j] > a[j+1]) /* 比较两个元素的大小 */

t=a[j]; a[j]=a[j+1]; a[j+1]=t; /* 如果前一个元素大,则交换 */

}

在文檔中 第 8 章 指针 (頁 22-27)

相關文件