PAT乙题1002写出这个数,对于本题用C语言的一些看法与见解

1572ba52b02542eb9761c09200515e1e.png

首先先看下题目,题目的意思很清楚,就是输入一个自然数n,n要小于10的100次方,然后输出输入的每一位数字之和的拼音,而且拼音数字间有1空格,最后的一个拼音数字后面没有空格

理解了题目意思后,理一下思路(用C语言做)

首先,肯定是要给一个输入,然后还要给一个拼音数字的数组以char的形式,然后就是将每一位上面的数字取出来加起来有个sum总和,再按照sum总和去对应拼音数字。

实际操作上,我们肯定是先给一个输入:

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>

int main()
{
    int a = 0;
    scanf("%d", a);    

    return 0;
}

但是在后面写下去后,将进行试验的时候,会发现它给的数据1234567890987654321123456789

这个数据是很大的,用int会直接报错,因为太大了,而int的取值范围只有

-2147483648~+2147483647 

而这个远远大于这个范围了,所以不能用,那我们可以用long或者long long吗?当你使用的时候,你会发现也不行,更别说这个n是<10的100次方,所以这是第一个点:不能用int、long、long long

所以这里只能使用char,将其转换成字符来做,然后去字符的下标,这里又要注意了,下标要求的是数组或者指针类型的,那么这里的字符初始化就不能给单个字符,要么将其搞成数组,要么搞成指针。这里的话我是用了数组的类型

int main()
{
    char a[100];
    scanf("%s", &a);
    return 0;
}

这样子的话第一步就完成了,然后就是你要将这个字符中的每一位都取出来,然后求和,这个我想很简单,可以用while循环,也可以用for循环,然后将字符转换成数字,很简单就是

a[i] - "0"

这个你可以这么理解,将其转换成ASCII码值来计算

这里的话我使用的是while循环

int main()
{
	char a[100];
	int sum = 0;
	int i = 0;
	scanf("%s", &a);

	while (strlen(a) > i)
	{
		sum = sum + a[i] - '0';
		i++;
	}

	return 0;
}

这里我用的思路就是取一个i=0,将其看作下标,也就是可以理解成长度,每次都取一个位上面的数字,然后求和。

然后最后就是将求和的数字转换成拼音数字,这里又会发现一个问题,你如果直接在这个main里面进行转化的话,就会发现出现个问题

它会提示你的strlen出现问题,我想这按道理应该没有问题呀,strlen就是一个求长度的函数,可它给我报错,它这个报错的意思是:警告 C28278:出现函数名称,没有作用域中的原型 


2022.7.23 21:46修改:这里我发现了,这里的警告是因为没有引入头文件#include <string.h>

这里只需要引用头文件就会发现这个警告没了。


这块地方就是在外引入函数,然后用递归来写,很轻松就能完成。

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>

void num(int q) 
{
	char* ss[10] = { "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };
	if (q > 9) 
	{
		num(q / 10);
		printf(" ");
	}
	printf("%s", ss[q % 10]);
}

int main()
{
	char n[100];
	
	int sum = 0;
	int i = 0;
	scanf("%s", &n);
	while (strlen(n) > i)
	{
		sum = sum + n[i] - '0';
		i++;
	}
	if (sum == 0) 
	{
		num(0);
	}
	num(sum);
	
}

 


补充 2022.7.24 20.37

经过我的研究与学习,发现了可以不用引入外函数而直接在一个main函数里面操作出来

代码如下

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>
#include <string.h>

int main()
{
	char n[100];
	char* ss[10] = { "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };
	int sum = 0;
	int i = 0;
	int a = 0;
	int x = 0;
	int y = 0;
	int z = 0;
	scanf("%s", &n);
	while (strlen(n) > i)
	{
		sum = sum + n[i] - '0';
		i++;
	}
	//printf("%d\n", sum);
	x = sum / 100;
	y = sum / 10 % 10;
	z = sum % 10;
	if (x == 0 && y != 0)
	{
		printf("%s ", ss[y]);
		printf("%s", ss[z]);
	}
	else if (x == 0 && y == 0)
	{
		printf("%s", ss[z]);
	}
	else
	{
		printf("%s ", ss[x]);
		printf("%s ", ss[y]);
		printf("%s", ss[z]);
	}
	return 0;
}

这块地方就是外加了x,y,z。x代表百位上的数字,y代表十位上的数字,z代表个位上的数字。

我先说下为什么可以这么做,因为首先题目给出了输入的范围是小于10的100次方,也就是说最多有101位的数字,那最大也就是9个101位,总和位909。发现都是在1000以内,那么就可以用这个思想,就是将每一位上面的数字都取出来,然后转换。

原先我最开始的想法也是这样,但是那时候并没有考虑到范围的问题,而且取的话从左到右不好取,从右到左很好取,但是取了之后发现很麻烦,会发现你要输出的话要从最后开始输出,这样子就是嵌套了,那我还不如直接外设函数嵌套循环出来。所以这个就被我否决了

然后想到了这个范围的限制,也是给我们解题的方法,之后的if语句就是因为当前面位数的值为0的时候,而后面有值的时候,那个0是不输出的,所以就考虑到三种情况

  1.  百位为0,十位不为0
  2.  百位为0,十位为0
  3. 百位不为0

 所以就是这样子搞出来了

最后我其实是不推荐这样的做法,因为这样的作法比较繁琐,而且没有定义函数来嵌套循环的快,并且你想要想到这方面还是有点困难,因为要抓住输入的范围来做

但是我认为这种思想是很好的,而且其实也不大麻烦,并且很容易理解,只要明白了这个思路很快就能搞出来。而定义函数的话由于嵌套循环的缘故,很容易将自己的思维打乱、搞混。

所以说各有千秋,看大家喜欢哪种就用哪种吧


2022.7.25添加

可以修改下指针那块,我想可能大伙看指针看的不是很懂,就这么说吧

char 和 char*还是有细微的差别的,第一个是单个字符,而后者是指向char的指针变量

而我们这边明显有很多数据,相当于是字符数组了,所以单单的用char会出问题

但可以这么做:

char ss[10][5] = { "ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };

就将char这个改成这样,答案也是正确的。接下来我说下原理:

首先ss[10][5] 就是说ss这个里面有10个字符串,这10个字符串里又有5个元素

第一个10我想都懂,因为有10个元素,所以就是10个字符串

后者的5我也不是很清楚,但是如果说里面不填,空着。那会出现一个问题,由于后面的各个字符串中的元素各不相同,导致它无法分辨到底取几,这样就会报错

后面取5我是这么理解的,我本来认为是填4,因为字符串中最大的也就是ling,有4个元素,可是当放到PTA上去后,发现19分,扣了一分,所以我想5是因为还有个字符串的结束标志\0也算进去了,所以填5

这个方法适用于那些对指针不太清楚的小伙伴,很友好

总而言之,还是看大家喜欢用哪一种,各有千秋

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzzan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值