《C语言程序设计教程》第三版 习题六

目录

一、习题

6.3 从键盘输入3个整数,要求设3个指针变量p1、p2、p3,使p1指向3个数中的最大者,p2指向次大者, p3指向最小者,然后按由大到小的顺序输出这3个数。

6.7 有一个数列,含有20个整数,现要求编写一个函数,能够对从指定位置开始的几个数按相反顺序重新排列,并在main函数中输出新的数列。例如,原数列为1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,若要求对从第5个数开始的10个数进行逆序处理,则得到的新数列为1,2,3,4,14,13,12,11,10,9,8,7,6,5,15,16,17,18。

6.8 有n个人围成一圈,顺序排号,从第1个人开始报数,从1报到5,凡是报到5的人退出圈子,问最后留下的是原来第几序号的人?要求如下。(1)用函数实现报数并退出。(2)n的值由 main函数输入并通过实参传送给该函数,最后结果由 main函数输出。(3)要求使用指针。

6.10 有一个整型二维数组,大小为m×n,要求找出其中最大值所在的行和列以及该最大值。请编写一个函数max,要求如下。(1)以数组名和数组大小为该函数的形参。(2)数组元素的值在main函数中输入,结果在函数max中输出。

6.12 输入3行字符(每行60个字符以内),要求统计出其中共有多少大写字母、小写字母、空格及标点符号。

6.14 建立一个动态二维数组,用来存储1~10的1~4次幂。

二、注意

2.1

2.2

2.3

2.4

2.5


一、习题

6.3 从键盘输入3个整数,要求设3个指针变量p1、p2、p3,使p1指向3个数中的最大者,p2指向次大者, p3指向最小者,然后按由大到小的顺序输出这3个数。

#include<stdio.h>
int main(){
	int a, b, c;
	int *p1, *p2, *p3;
	scanf("%d %d %d", &a, &b, &c);
	if(a>b&&b>c){
		p1=&a;
		p2=&b;
		p3=&c;
	}
	if(a>c&&c>b){
		p1=&a;
		p2=&c;
		p3=&b;
	}
	if(b>a&&a>c){
		p1=&b;
		p2=&a;
		p3=&c;
	}
	if(b>c&&c>a){
		p1=&b;
		p2=&c;
		p3=&a;
	}
	if(c>b&&b>a){
		p1=&c;
		p2=&b;
		p3=&a;
	}
	if(c>a&&a>b){
		p1=&c;
		p2=&a;
		p3=&b;
	}

	printf("%d %d %d\n", *p1, *p2, *p3);
	return 0;
}

6.7 有一个数列,含有20个整数,现要求编写一个函数,能够对从指定位置开始的几个数按相反顺序重新排列,并在main函数中输出新的数列。例如,原数列为1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,若要求对从第5个数开始的10个数进行逆序处理,则得到的新数列为1,2,3,4,14,13,12,11,10,9,8,7,6,5,15,16,17,18。

#include<stdio.h>
void resort(int number[], int wh, int cnt){
	int *p1, *p2, temp;
	p1 = &number[wh - 1];
	p2 = &number[wh + cnt - 2];
	for(; p1 < p2; p1++, p2--){
		temp = *p1;
		*p1 = *p2;
		*p2 = temp;
	}
}

int main(){
	int number[20]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
	int wh, cnt, i;
	printf("old array as follow:\n");
	for(i=0;i<20;i++)
		printf("%d ",number[i]);
	printf("\n");
	printf("where and count:");
	scanf("%d %d", &wh, &cnt);
	resort(number,wh,cnt);
	printf("\nresorted array as follow:\n");
	for(i=0;i<20;i++)
		printf("%d ",number[i]);
	printf("\n");
}

6.8 有n个人围成一圈,顺序排号,从第1个人开始报数,从1报到5,凡是报到5的人退出圈子,问最后留下的是原来第几序号的人?要求如下。
(1)用函数实现报数并退出。
(2)n的值由 main函数输入并通过实参传送给该函数,最后结果由 main函数输出。
(3)要求使用指针。

#include <stdio.h>
void sort(int num[], int n){
	int *p, j, i, m, k;
	p = num;//开始给这些人编号
	for (j = 0; j < n; j++){
		*(p + j) = j + 1;
	}
	i = 0;//i用于计数,即让指针后移
	m = 0;//m记录退出圈子的人数
	k = 0;//k报数1,2,3,4,5
	while(m < n - 1){//当退出的人数不大于总人数时,即留下的人数至少是一个人
		if (*(p + i) != 0){//如果这个人的头上编号不是0就开始报数加1,这里采用的方法是报数为3的人头上编号重置为0
			k++;
		}
		if (k == 5){    
			k = 0;    //报数清零,即下一个人从1开始报数
			*(p + i) = 0;//将报数为5的人编号重置为0
			m++;    //退出人数加1
		}
		i++;      //指针后移
		if (i == n){//如果到了队尾,就要使指针重新指向对头//并且它只能放在i++后面,因为只有i++了才有可能i==n
			i = 0;
		}
	}
}

int main(){
	int num[50], n, *p, j, loop, i, m, k;
	printf("请输入这一圈人的数量:\n");
	scanf("%d", &n);
	sort(num, n);
	printf("现在剩下的人是:");
	for (loop = 0; loop < n; loop++){
		if (num[loop] != 0){
			printf("%2d号\n",num[loop]);
		}
	}
	return 0;
}

6.10 有一个整型二维数组,大小为m×n,要求找出其中最大值所在的行和列以及该最大值。请编写一个函数max,要求如下。
(1)以数组名和数组大小为该函数的形参。
(2)数组元素的值在main函数中输入,结果在函数max中输出。

#include<stdio.h>
#include<stdlib.h>
int max, maxi, maxj;
void find(int a[][4]){
	int i, j;
	max = a[0][0];
	for(i=0; i<3; i++){
		for(j=0; j<4; j++){
			if(max < a[i][j]){
				max = a[i][j];
				maxi = i + 1;
				maxj = j + 1;
			}
		}
	}
}

int main(){
	int i, j;
	int a[3][4];
	
	for(i=0; i<3; i++)
		for(j=0; j<4; j++)
			scanf("%d", &a[i][j]);
	find(a);
	printf("最大值为:%d, 行为:%d, 列为:%d\n", max, maxi, maxj);
}

6.12 输入3行字符(每行60个字符以内),要求统计出其中共有多少大写字母、小写字母、空格及标点符号。

#include <stdio.h>
#include<string.h>
int big = 0, small = 0, blank = 0, symbol = 0;
void StringBracket(char *str){
	int i,len;
	len = strlen(str);
	for(i = 0; i < len; i++){
		if(str[i] >= 'A' && str[i] <= 'Z'){
			big++;
		}else if(str[i] >= 'a' && str[i] <= 'z'){
			small++;
		}else if(str[i] == ' '){
			blank++;
		}else{
			symbol++;
		}
	}
}
int main(){
	int i;
	char a[100];
	
	for(i = 0; i < 3; i++){
		gets(a);
		StringBracket(a);
	}
	printf("大写字母:%d\n小写字母:%d\n空格:%d\n符号:%d\n", big, small, blank, symbol);
	return 0;
}

6.14 建立一个动态二维数组,用来存储1~10的1~4次幂。

#include<stdio.h>
#include<malloc.h>
#include<math.h>
int main()
{
	//4行10列的数组
	int i, j;
	int **p = (int **)malloc(sizeof(int *) * 4);//行
	for (i = 0; i < 4; ++i)
	{
		p[i] = (int *)malloc(sizeof(int) * 10);//列
	}
	for (i = 1; i <= 4; ++i)
	{
		for (j = 1; j <= 10; ++j)
		{
			printf("%-5d ", (int)pow((double)j, (double)i));
		}
		printf("\n");
	}
	for (i = 0; i < 4; ++i){
		free(p[i]);
		p[i] = NULL;
	}
	free(p);
	p = NULL;
    return 0;
}

二、注意

2.1

#include<stdio.h>
int main(){
	//no.1
	int a1[5]={1,3,5,7,9};
	int *p=a1;
	int **k=&p;
	printf("%d ", *(p++));//1
	printf("%d ", **k);//3

	//no.2
	int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
	int *pa[3];
	int **pp;
	pa[0]=a[0];
	pa[1]=a[0]+1;
	pa[2]=a[0]+2;
	pp=pa;
	printf("%d\n", pp[1][2]); //4

	//no.3
	char *c[]={"enter","new","point","first"};
	char **pc[]={c+3,c+2,c+1,c};//"first","point","new","enter"
	char ***ppc=pc;
	printf("%s\n", **++ppc);//point
	printf("%s\n", *--*++ppc+3);//er
	printf("%s\n", *ppc[-2]+3);//st
	printf("%s\n", ppc[-1][-1]+1);//ew
	return 0;
}

2.2

#include "stdio.h"
#include "string.h"
void fun(char *s){ 
    char t[7];
    s=t;
    strcpy(s, "example");
}
 
int  main(){ 
    char *s;   
    fun(s);   
    printf("%s",s);
    return 0;
}

C.程序编译时出现错误×
D.程序运行时出现错误√

  1.main函数里的s没有初始化就在fun函数里使用s,编译器会报警告,运行时会报错(局部变量未初始化)。
  2.就算s初始化了,在fun函数里,局部变量t的大小为7,而strcpy函数会复制example末尾的\0 
  所以example+'\0'一共8个字节空间,会溢出,程序会崩溃。 
  3.就算局部变量t的大小足够大,在fun函数运行结束后,局部变量t的内存空间会被释放掉,此时s成为野指针;返回main函数后,也不会输出example。

编译错误可以理解成编译器能检查出来的错误,运行错误理解成逻辑错误,需要用户自己纠错
对于栈中内存如果没有初始化,则会出现“烫烫烫烫烫烫”。对于堆中内存如果没有初始化,则会出现“屯屯屯屯屯”

2.3

float a[3]={1.5,2.5,3.5},*pa=a;*(pa++)*=3;
则*pa = ?

  *(pa++) *= 3 
  1)*pa  *=  3,此时pa指向a[0],a[0] = 4.5 
  2)pa++,此时pa指向a[1],*pa = a[1] = 2.5

2.4

#include<stdio.h>
void foobar(int a, int *b, int **c)
{
    int *p = &a;
    *p = 101;
    *c = b;
    b = p;
}
 
int main()
{
    int a = 1;
    int b = 2;
    int c = 3;
    int *p = &c;
    foobar(a, &b, &p); //a是按值传递,因此在函数中的修改不会引起主函数中的变化。
    printf("a=%d, b=%d, c=%d, *p=%d\n", a, b, c, *p);
    return (0);
}
1.函数中b传递的是主函数中b的指针,语句b = p ,其中p指向的是函数foobar内局部变量a的地址,让传递过去的指针换了指向的数据,原来指向的数据(主函数中的b)不会有影响。
  如果这里是*b = *p那么主函数中的b也要相应变化。
2.函数中的c传递的是双重指针,*c = b,也就是让主函数中的p指针指向了主函数中的b的地址
3.在函数foobar中对指针的变化没有影响到主函数,只是让双重指针更换了指向而已

2.5

#include <stdio.h>
int inc(int a) { return (++a); }
int multi(int *a, int *b, int *c) { return (*c = *a * *b); }
typedef int (*FUNC1)(int in);
typedef int (*FUNC2)(int *, int *, int *);
void show(FUNC2 fun, int arg1, int *arg2) {
    FUNC1 p = &inc;
    int temp = p(arg1);
    fun(&temp, &arg1, arg2);
    printf("%d\n", *arg2);
}
int main() {
    int a;
    show(multi, 10, &a);
    return 0;
}
  typedef int(*FUNC1)(int in); 是函数指针定义
  show(multi,10,&a); FUNC2类型函数指针fun 指向函数multi的首地址
  FUNC1 p=&inc; FUNC1类型函数指针p 指向函数inc的首地址
  int temp=p(arg1);   此时调用函数inc,参数为10,返回值为11 
  fun(&temp,&arg1,arg2); 调用函数multi,参数为(11,10,arg2) arg2为指针变量负责带回返回值
  printf("%d\n",*arg2); 输出 110

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值