S1E24:指针和二维数组 课后作业

测试题:
0. 如果不上机,你能看出下边代码将打印什么值吗?

#include <stdio.h>

int main()
{
        char matrix[3][5] = {
                'I', 'l', 'o', 'v', 'e',
                'F', 'i', 's', 'h', 'C',
                '.', 'c', 'o', 'm', '!'
        };
        char *p;

        p = &matrix[0][3];

        printf("%c", *p);
        printf("%c", *p++);
        printf("%c", *++p);
        printf("\n");

        return 0;
}

答:*p:v     *p++ :h   *++p:m (错误

答案:vvF

分析:

  • 字符指针 p 指向二维数组 matrix 第一行第四个元素('v')
  • 由于 p 是一个字符指针(其跨度为一个字符),所以 p++ 指向 matrix 第一行第五个元素('e'),但加加运算符(++)作为后缀使用时,是先使用原来的值再进行加一运算,因此 *p++ 仍然打印 'v',随后指针指向 'e'
  • 加加运算符(++)作为前缀使用时,则先让指针(p)指向下一个元素,再间接取出里边的值。由于二维数组实质上是一维数组的线性扩展,所以 ++p 指向的是第二行第一个元素('F')

1. 假如定义了二维数组 int matrix[4][5] = {0};,请问 matrix 和 matrix + 0 的含义一样吗?

答:一样

答案:一样啊,怎么不一样?!

2. 假设有二维数组如下,请问 *(matrix + 1) + 2 的含义是?

char matrix[3][5] = {
        'I', 'l', 'o', 'v', 'e',
        'F', 'i', 's', 'h', 'C',
        '.', 'c', 'o', 'm', '!'
};

答:为    's'   的地址

答:*(matrix + 1) + 2 的含义是一个指向字符变量的指针,其值是二维数组 matrix 第二行第三个元素的地址(即 &matrix[1][2])。

3. 请问 array[x][y][z] 用指针法如何表示?

答:*(*(*(array+x)+y)+z)

答案:*(*(*(array+i)+j)+k)

4. 请问下边代码将打印什么值?

#include <stdio.h>

int main()
{
        char array[2][3][5] = {
                {
                        {'x', 'x', 'x', 'x', 'x'},
                        {'x', 'x', 'o', 'x', 'x'},
                        {'x', 'x', 'x', 'x', 'x'}
                },
                {
                        {'x', 'x', 'x', 'x', 'x'},
                        {'x', 'x', 'o', 'x', 'x'},
                        {'x', 'x', 'x', 'x', 'x'}
                }
        };

        printf("%c%c%c%c\n", *(*(*array + 1) + 2), *(*(*(array + 1) + 1) + 2), ***array, *(**array + 1));

        return 0;
}

答:ooxx

*(*(*array + 1) + 2) = ‘o’     *(*(*(array + 1) + 1) + 2) = 'o'     ***array = 'x'    *(**array + 1)) =  'x'

答案:ooxx(这道简直是送分题嘛!)

5. 如果不上机,你能看出下边代码将打印什么值吗?

#include <stdio.h>

int main()
{
        int array[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        int (*p)[3] = (int (*)[3])&array;

        printf("%d\n", p[2][2]);

        return 0;
}

答:迷惑了,解不出来(错误

答案:9
分析:对于初学者来说,这道题的难度级别很高,但当你尝试去理解它其中的原理之后,你会发现对指针的认识又深入了一点儿呢!
等号右边强制将 array 这个一位数组重新划分成 3 * 3 的二维数组,然后用数组指针指向它(本章最后说如果要使用指针来指向二维数组,只能使用数组指针,还记得吗?)。
So,p 指向的应该是这么一个二维数组:

1 2 3
4 5 6
7 8 9

所以,p[2][2] 的结果是 9。

动动手:
0. 编写一个程序,接收用户的输入,并将前 9 个字符以正方形矩阵(3 * 3)的方式输出。
程序实现如下:

答:

#include <stdio.h>

int main()
{
	int i = 0;
	char str[100];
	char *target = str;
	scanf("%s",str);

	while(i< 9){
		printf("%2c",*target++);
		i++;
		if(i%3 == 0)
		{
			printf("\n");
		}
	}	
} 

答案:

#include <stdio.h>

int main()
{
        int matrix[3][3] = {0};
        int i, j;

        for (i = 0; i < 3; i++)
        {
                for (j = 0; j < 3; j++)
                {
                        matrix[i][j] = getchar();
                }
        }

        for (i = 0; i < 3; i++)
        {
                for (j = 0; j < 3; j++)
                {
                        printf("%c ", matrix[i][j]);
                }
                printf("\n");
        }


        return 0;
}

1. 这次不限制正方形矩阵的尺寸,要求程序自动计算用户输入的字符,并以最大的正方形矩阵输出(比如用户输入 17 个字符,输出 4 * 4 矩阵)。
程序实现如下:

答:

#include <stdio.h>
#include <string.h>
#include <math.h>

int main()
{
	char str[100];
	char *target = str;
	int len,x=0;
	int i,j;
	
	fgets(str,100,stdin);
	len = strlen(str);

#if 0   //用这种方法算最大的x不行 
	while(1)
	{
		x++;
		if((x * x) > len);
			break;	
	}
	printf("x :%d\n",x);
	x = x-1;
#endif

	x = sqrt(len);
	for(i=0;i<x;i++)
	{
		for(j=0;j<x;j++)
		{
			printf("%2c",str[i*x + j]);
		}
		printf("\n");
	}
}

答案:

#include <stdio.h>
#include <string.h>
#include <math.h>

#define MAX 1024

int main()
{
        int length, aver;
        int i, j;
        char str[MAX];

        scanf("%s", str);

        length = strlen(str);
        aver = sqrt(length);

        for (i = 0; i < aver; i++)
        {
                for (j = 0; j < aver; j++)
                {
                        printf("%c ", str[i * aver + j]);
                }
                printf("\n");
        }

        return 0;
}

2. 下表为广州市最近两年(2014年8月份 ~ 2016年8月份)的 PM2.5 检测数据表,请按要求编程。

\

1

2

3

4

5

6

7

8

9

10

11

12

2014

/

/

/

/

/

/

/

31.3

35.5

58.7

49.6

55.5

2015

59.8

54.9

33.1

38.2

26.6

20.5

27.8

38.5

41.5

44.7

38.1

41.5

2016

34.9

36.4

47.5

37.9

30.6

23.4

26.6

34.3

/

/

/

/

要求A:编写一个程序,用户输入待查询年月份(输入格式:2015-03),输出该月份的 PM2.5 值。
程序实现如下:

答:

int main()
{
	int str[10];
	char *target = str;
	int year,month;
	float PM[3][12]={
		{0,0,0,0,0,0,0,31.3,35.5,58.7,19.6,55.5},
		{59.8,54.9,33.1,38.2,26.6,20.5,27.8,38.5,41.5,44.7,38.1,41.5},
		{34.9,36.4,47.5,37.9,30.6,23.4,26.6,34.4,0,0,0,0}
	};
   
	printf("请输入待查询年月份(年-月);");
	scanf("%d-%d",&year,&month);

	if((year<=2016 && year >= 2014) && (month <=12 && month >= 1) )
	{
		if(PM[year-2014][month-1] == 0)
		{
			printf("抱歉,该月份未收录数据!\n");
		}
		else{
			printf("%d年%d月广州的PM2.5值是:%.1f\n",year,month,PM[year-2014][month-1]);
		}
	}
	else{
		printf("抱歉,该年份未收录数据!\n");
	}	
}

答案:

#include <stdio.h>

int main()
{
        float pm25[3][12] = {
                {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.3, 35.5, 58.7, 49.6, 55.5},
                {59.8, 54.9, 33.1, 38.2, 26.6, 20.5, 27.8, 38.5, 41.5, 44.7, 38.1, 41.5},
                {34.9, 36.4, 47.5, 37.9, 30.6, 23.4, 26.6, 34.3, 0.0, 0.0, 0.0, 0.0}
        };
        int year, month;

        printf("请输入待查询年月分(年-月): ");
        scanf("%d-%d", &year, &month);

        if (year < 2014 || year > 2016 || month < 1 || month > 12)
        {
                printf("输入数据错误!\n");
        }
        else
        {
                year -= 2014;
                month -= 1;
                if (pm25[year][month])
                {
                        printf("%d年%d月广州的PM2.5值是: %.2f\n", year + 2014, month + 1, pm25[year][month]);
                }
                else
                {
                        printf("抱歉,该月份未收录数据!\n");
                }
        }

        return 0;
}

要求B:将所有记录的数据打印为横向直方图。
程序实现如下:

答:参考答案

#include <stdio.h>

int main()
{
	int year,month;
	float max,min;
	int i,j,data,step;
	float PM[3][12]={
		{0,0,0,0,0,0,0,31.3,35.5,58.7,19.6,55.5},
		{59.8,54.9,33.1,38.2,26.6,20.5,27.8,38.5,41.5,44.7,38.1,41.5},
		{34.9,36.4,47.5,37.9,30.6,23.4,26.6,34.4,0,0,0,0}
	};
	max=max=PM[1][0];
	for(i=0;i<3;i++)
	{
		for(j=0;j<12;j++)
		{
			if(PM[i][j])
			{
				min=min>PM[i][j] ? PM[i][j] : min;
				max=max<PM[i][j] ? PM[i][j] : max;	
			}	
		}	
	}
	printf("最小值:%.2f ,最大值:%.2f\n",min,max);
	
	
	// 计算步进值
    if ((int)(max - min) > 80)
    {
            step = 2;
    }
    else
    {
            step = 1;
    }
	
	//打印直方图
	for(i=0;i<3;i++)
	{
		for(j=0;j<12;j++)
		{
			data=PM[i][j];
			if(data)
			{
				printf("%d年%2d月: ", i + 2014, j + 1);
                while (data >= min)
                {
                        printf("*");
                        data -= step;
                }
                printf("\n");
			}	
		}	
	} 
} 

答案:

#include <stdio.h>

int main()
{
        float pm25[3][12] = {
                {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 31.3, 35.5, 58.7, 49.6, 55.5},
                {59.8, 54.9, 33.1, 38.2, 26.6, 20.5, 27.8, 38.5, 41.5, 44.7, 38.1, 41.5},
                {34.9, 36.4, 47.5, 37.9, 30.6, 23.4, 26.6, 34.3, 0.0, 0.0, 0.0, 0.0}
        };
        int i, j, step;
        float min, max, data;

        // 找出最大值和最小值
        min = max = pm25[1][0];
        for (i = 0; i < 3; i++)
        {
                for (j = 0; j < 12; j++)
                {
                        if (pm25[i][j])
                        {
                                min = min > pm25[i][j] ? pm25[i][j] : min;
                                max = max < pm25[i][j] ? pm25[i][j] : max;
                        }
                }
        }

        // 计算步进值
        if ((int)(max - min) > 80)
        {
                step = 2;
        }
        else
        {
                step = 1;
        }

        printf("最小值: %.2f, 最大值: %.2f\n", min, max);
        // 打印直方图
        for (i = 0; i < 3; i++)
        {
                for (j = 0; j < 12; j++)
                {
                        data = pm25[i][j];
                        if (data)
                        {
                                printf("%d年%2d月: ", i + 2014, j + 1);
                                while (data >= min)
                                {
                                        printf("*");
                                        data -= step;
                                }
                                printf("\n");
                        }
                }
        }

        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值