C语言程序与设计第四版课后习题 - 第八章(完结)

终于完成指针的习题了,太难了。。。

8.12 输出字符串中的整数

题目概述:

8.12 输人一个字符串,内有数字和非数字字符,例如:
a123x456 17960? 302tab5876

将其中连续的数字作为一个整数,依次存放到一数组 a 中。例如,123 放在 a[0],456 放在a[1]…共有多少个整数,并输出这此数。

题目思路:
  • 总体思路:要先定义一个字符数组来接收,然后一个再定义一个整型数组,用来存放字符串中的整数
  • 循环判断到字符串结束
    • 判断str+i所指向的字符是不是数字字符,如果是的话,j++,j此时记录的是字符串中有多少个整数字符
    • 当str+i所指向的字符不是数字字符,是其他字符,那么就要开始计算一串数字字符,并把他变为整数
    • 首先整数有个位十位百位,所以要循环,让e代表该位数所乘的位阶,然后把他存到digit
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
	char str[50] = { 0 };
	int a[10] = { 0 };
	int i = 0;
	int j = 0;
	int k = 0;		//位数
	int digit = 0;	//位数相加的整数
	int e = 0;		//位数要乘的位阶
	int n = 0;		//记录有多少整数
	int* pa = a;	//指向数组a的指针

	gets(str);

	while (*(str + i) != '\0')
	{
		if (*(str + i) >= '0' && *(str + i) <= '9')
		{
			j++;	//如果字符串中的字符是整型字符的话,记录有多少个整型字符
		}
		else		//如果字符串不是整型字符,开始把记录多少位数的整型字符变成整数
		{
			if (j > 0)
			{
				e = 1;
				digit = 0;
				for (k = 0; k < j; k++)
				{
					digit += (*(str + i - 1 - k) - '0') * e;
					e = e * 10;
				}
				*pa = digit;
				pa++;
				n++;
				j = 0;
			}
		}

		i++;
	}

	if (j > 0)
	{
		e = 1;
		digit = 0;
		for (k = 0; k < j; k++)
		{
			digit += (*(str + i - 1 - k) - '0') * e;
			e = e * 10;
		}
		*pa = digit;
		pa++;
		n++;
		j = 0;
	}

    printf("该字符串中一共有多少%d个整数\n", n);
	for (i = 0; i < n; i++)
	{
		printf("%d ", *(a + i));
	}


	return 0;
}

运行结果如下:
在这里插入图片描述

本题核心代码就是这个,下面进行讲解

while (*(str + i) != '\0')
	{
		if (*(str + i) >= '0' && *(str + i) <= '9')
		{
			j++;	//如果字符串中的字符是整型字符的话,记录有多少个整型字符
		}
		else		//如果字符串不是整型字符,开始把记录多少位数的整型字符变成整数
		{
			if (j > 0)
			{
				e = 1;
				digit = 0;
				for (k = 0; k < j; k++)
				{
					digit += (*(str + i - 1 - k) - '0') * e;
					e = e * 10;
				}
				*pa = digit;
				pa++;
				n++;
				j = 0;
			}
		}

		i++;
	}

从else语句开始分析

  • 首先是为什么要-‘0’,是因为在字符串里面的数字是数字字符,所以我们要-'0’使他变成整数

  • 而为什么是 (*(str + i - 1 - k) - '0')

    • 原因是:在循环体里面我们有一个if语句的判断,当if语句不是数字字符的时候,他就会走else语句,也就是说,当他走else语句的时候,他就不是数字字符了,而是其他字符,其实指针指向的是这里
      在这里插入图片描述

      • 也就是’x’的地址,所以,在我们计算位数的时候需要-1,使他指到’3’处
        在这里插入图片描述

      • 但是,由于我们计算的是位数相加,所以我们要-k,当k=0时,str+i-1-k就是’3’的地址
        在这里插入图片描述

        • 当k=1时,str+i-1-k就是’2’的地址,此时e是10,所以得出2 * 100=200
          在这里插入图片描述

        • 当k=2时,str+i-1-k就是‘1’的地址,此时e是100,所以得出1*100 = 100
          在这里插入图片描述

        • 当k=3时,不满足循环条件,跳出循环

  • 然后用一个pa的指针指向数组a,把数组存在此处,pa++

  • n++,记录这个字符串有多少个整数

  • 循环结束

循环结束后,你会发现循环体内的语句我又重复了一遍,这是为什么呢?

  • 那是因为防止末尾的字符串是数字,无法复制,为什么无法复制?在这里插入图片描述

    • 因为循环判断,当*(str+i)指向的是’\0’,不满足循环条件跳出循环,而跳出循环之后,对末尾的数字就无法操作了,所以在跳出循环之后需要再操作一次

8.13 矩阵转置

题目概述:
题目思路:
  • 画一个对角线

对角线的值不变,然后让对角线外的对称值进行互换,既然是互换,那么就会要有一个中间变量temp进行互换

对应的下标如下:
在这里插入图片描述

  • 本题的难点就是如何用指针表示二维数组,从而进行行列互换

    • 现在我们就来学习如何用指针来表示二维数组,我们要知道arr[i]是等价于*(arr +i)的,所以二维数组的表示就是

      arr[i][j] <==> *(arr + i)[j] <==> *(*(arr + i) + j)
      
代码实现:

我们可以先写成二维数组的形式,再用上述的转换变成指针表示

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define ROW 3
#define COL 3
void swap(int(*arr)[3], int row, int col)
{
	int temp = 0;
	int i = 0;
	int j = 0;

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < i; j++)	//为什么要小于i?因为j小于col的话会把他换回去,也就是实现了两次互换
		{
			temp = arr[i][j];
			arr[i][j] = arr[j][i];
			arr[j][i] = temp;
		}
	}
}
int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int i = 0;
	int j = 0;
	int row = ROW;
	int col = COL;

	swap(arr, row, col);

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}


	return 0;
}

指针表示:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define ROW 3
#define COL 3
void swap(int(*arr)[3], int row, int col)
{
	int temp = 0;
	int i = 0;
	int j = 0;

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < i; j++)	//为什么要小于i?因为j小于col的话会把他换回去,也就是实现了两次互换
		{
			temp = *(*(arr + i) + j);
			*(*(arr + i) + j) = *(*(arr + j) + i);
			*(*(arr + j) + i) = temp;
		}
	}
}
int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int i = 0;
	int j = 0;
	int row = ROW;
	int col = COL;

	swap(arr, row, col);

	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%d ", *(*(arr + i) + j));
		}
		printf("\n");
	}


	return 0;
}

运行结果如下:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值