S1E26:指向指针的指针 课后作业

测试题:
0. 你有听说过二级指针和三级指针吗?它们是什么?

答:二级指针:指向指针的指针    三级指针:指向指针的指针的指针

答案:二级指针其实就是指向指针的指针,而三级指针当然就是指向指针的指针的指针啦。

1. 请按下图写出每个变量的定义过程。
 

答:int *p1 = &num    int *p2 = &num    int **pp1 = &p1    int ***p3 = &pp1

答案:

int num = 520;
int *p1 = #
int *p2 = #
int **pp1 = &p1;
int ***p3 = &pp1;

2. 请问什么时候 *&p 和 p 等价,什么时候 &*p 和 p 等价?
答:什么时候*&p 都和 p等价,非定义变量的时候 &*p 和 p是等价的
答案: & 运算符的操作数必须是左值 ,因为只有左值才表示一个内存单元,才会有地址,运算结果是指针类型(地址);* 运算符的操作数必须是指针类型(地址),运算结果可以做左值。
结论:如果表达式 p 可以做左值,那么 *&p 和 p 等价;如果表达式 p 是指针类型(地址),那么 &*p 和 p 等价。

3. 如果有 int a[10];,请问 &a 和 &a[0] 表达式的类型有何不同?

答:&a代表整个数组的地址, &a[0]代表数组第一个元素的地址,结果都是一样的

答案:a 是一个数组,在 &a 这个表达式中,数组类型做左值,&a 表示取整个数组的首地址,类型是 int (*)[10];&a[0] 则表示数组 a 的第一个元素的首地址,虽然两个地址的数值相同,但后者的类型是 int *。

4. 假如定义了一个指针数组 pArray 如下,请定义一个指向它的数组指针 p,让下边程序可以顺利执行。

程序实现如下:

答:char *(*p)[4] = pArray (也可以,但会告警)

#include <stdio.h>

int main()
{
	char *pArray[4] = {
		"Hello",
		"How are you?",
		"Fine,thank you.And you?",
		"I'm fine too"
	};
	char *(*p)[4] = pArray;
	int i;
	
	for(i=0;i<4;i++)
	{
		printf("%s\n",(*p)[i]);
	}
	return 0;
}

答案:char *(*p)[4] = &pArray;

5. 定义以下变量:

char a[4][3][2] = {
        {
                {'a', 'b'}, {'c', 'd'}, {'e', 'f'}
        },
        {
                {'g', 'h'}, {'i', 'j'}, {'k', 'l'}
        },
        {
                {'m', 'n'}, {'o', 'p'}, {'q', 'r'}
        },
        {
                {'s', 't'}, {'u', 'v'}, {'w', 'x'}
        }
};
char (*pa)[2] = &a[1][0];
char (*ppa)[3][2] = &a[1];

想要通过指针 pa 和 ppa 访问数组 a 中的 'x' 元素,请问表达式应该怎么写?

答:*(*(pa+8) +1)                  *(*(*(ppa+2)+3)+1)(错误

答案:*(*(pa+8)+1) 和 *(*(*(ppa+2)+2)+1))。 &*#cI9;
解析:

如上图所示,*pa 被定义为一个一维数组,其跨度为 2 个字节,所以 *(pa + 8) 指向的是 {'w', 'x'} 这个数组,所以 *(*(pa + 8) + 1) 取出 'x' 元素;*ppa 被定义为一个二维数组,其跨度为 6 个字节,所以 *(ppa + 2) 指向的是 {{'s', 't'}, {'u', 'v'}, {'w', 'x'}} 这个二维数组,所以 *(*(*(ppa + 2) + 2) + 1) 取出 'x' 元素。

动动手答案:

0. 分割字符串。用户输入一个英文句子,你的程序将这个字符串按空格进行分割,返回由单词组成的二维数组。
要求:
  • 返回的二维数组必须尽可能地节省空间(利用C语言的变长数组来实现)
  • 不能使用现成的函数帮忙(你只能 #include <stdio.h>)

程序实现如下:
分割后的结果存放在 result 二维数组中,这个二维数组的尺寸是根据用户输入的单词长度而定的(再次提醒:不能使用 malloc 等没学过的知识噢~)

不论是一个空格还是多个空格,你的程序都能够正确识别出单词来:


答:没想出来代码构造(错误

答案:

#include <stdio.h>

int main()
{
        char str[1024];
        char *p = str;          // 用于间接寻址
        char *pos[1024] = {0};  // 记录每个单词的地址
        int len = 0;
        int cChar = 0, cWord = 0; // cChar 统计字符数, cWord 统计单词数
        int max = 0, i = 0, j;

        printf("请输入一个英文句子:");
        // 接收输入,顺带统计用户实际输入了多少个字符
        while ((str[len++] = getchar()) != '\n' && len + 1 < 1024)
                ;
        str[len-1] = '\0'; // str[len]存放的是'\n',将其替换为'\0'

        if (*p != ' ')
        {
                pos[i++] = p; // 记录第一个单词的地址
                cWord++;
        }

        while (len--)
        {
                if (*p++ == ' ')
                {
                        // 判断最大字符数
                        max = cChar > max ? cChar : max;
                        cChar = 0;

                        // 到底了,退出循环
                        if (*p == '\0')
                        {
                                break;
                        }

                        // 单词数加一
                        if (*p != ' ')
                        {
                                pos[i++] = p;
                                cWord++;
                        }
                }
                else // 没有else会把空格统计进去
                {
                        cChar++;
                }
        }
        max = --cChar > max ? cChar : max; // 最后会算多一个'\0',所以减去

        // 申请可变长数组,max+1,否则'\0'放不下
        char result[cWord][max+1];

        // 将分割好的单词放进二维数组里
        for (i = 0; i < cWord; i++)
        {
                for (j = 0; *(pos[i]+j) != ' ' && *(pos[i]+j) != '\0'; j++)
                {
                        result[i][j] = *(pos[i]+j);
                }
                result[i][j] = '\0';
        }

        // 打印结果
        printf("分割结果已存放到result[%d][%d]的二维数组中...\n", cWord, max+1);
        printf("现在依次打印每个单词:\n");
        for (i = 0; i < cWord; i++)
        {
                printf("%s\n", result[i]);
        }

        return 0;
}

1. 修改代码,使得程序允许用户指定分隔符。
程序实现如下:

答:没想出来代码构造(错误

答案:

#include <stdio.h>

int main()
{
        char str[1024];
        char *p = str;          // 用于间接寻址
        char *pos[1024] = {0};  // 记录每个单词的地址
        int len = 0;
        int cChar = 0, cWord = 0; // cChar 统计字符数, cWord 统计单词数
        int max = 0, i = 0, j;
        char delim = ' ';

        printf("请输入一个英文句子:");
        // 接收输入,顺带统计用户实际输入了多少个字符
        while ((str[len++] = getchar()) != '\n' && len + 1 < 1024)
                ;
        str[len-1] = '\0'; // str[len]存放的是'\n',将其替换为'\0'

        printf("请输入分割符:");
        scanf("%c", &delim);

        if (*p != delim)
        {
                pos[i++] = p; // 记录第一个单词的地址
                cWord++;
        }

        while (len--)
        {
                if (*p++ == delim)
                {
                        // 判断最大字符数
                        max = cChar > max ? cChar : max;
                        cChar = 0;

                        // 到底了,退出循环
                        if (*p == '\0')
                        {
                                break;
                        }

                        // 单词数加一
                        if (*p != delim)
                        {
                                pos[i++] = p;
                                cWord++;
                        }
                }
                else // 没有else会把空格统计进去
                {
                        cChar++;
                }
        }
        max = --cChar > max ? cChar : max; // 最后会算多一个'\0',所以减去

        // 申请可变长数组,max+1,否则'\0'放不下
        char result[cWord][max+1];

        // 将分割好的单词放进二维数组里
        for (i = 0; i < cWord; i++)
        {
                for (j = 0; *(pos[i]+j) != delim && *(pos[i]+j) != '\0'; j++)
                {
                        result[i][j] = *(pos[i]+j);
                }
                result[i][j] = '\0';
        }

        // 打印结果
        printf("分割结果已存放到result[%d][%d]的二维数组中...\n", cWord, max+1);
        printf("现在依次打印每个单词:\n");
        for (i = 0; i < cWord; i++)
        {
                printf("%s\n", result[i]);
        }

        return 0;
}


*BFh.w$~k`^3O)SG%&;o6>[-s
^!dyn$MX}SmW-.lCONL%~=E)z<

  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值