「PAT乙级真题解析」Basic Level 1006 (问题分析+完整步骤+伪代码描述+提交通过代码)
[PAT练级笔记] 04 Basic Level 1006
#算法#数据结构#pat考试#c语言#需求分析
Table of Contents
乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。
问题分析
思路: 以终为始拆解问题
根据题目要求, 给定一个不超过3位数的正整数, 比如: 234, 输出"BBSSS1234", 表示这个正整数有 2 个“百”、3 个“十”、以及个位的 4。其中:
- "BB"表示 2 个“百”
- "SSS"表示 3 个“十”
- "1234"表示个位数为 4
按照这个逻辑, 我们可以将题目的要求重新描述为以下形式
- 给定一个不超过3位数的正整数,
- (如果有百位) 百位是多少, 就输出多少个"B"
- (如果有十位) 十位是多少, 就输出多少个"S"
- 个位数是多少, 就输出从1开始直到这个位数值的各个数字
- 样例:
- "345" -> "BBBSSSS12345"
- "234" -> "BBSSS1234"
- "123" -> "BSS123"
- "12" -> "S12"
- "2" -> "12"
进一步, 我们可以思路用更接近代码的形式描述为如下步骤
- 获取正整数 【数据输入】
- (如果有百位, 则) 查看百位数, 获取百位数的数值, 存储(或直接输出), 对应个数的"B"
- 如何获取百位的数值. "给你一个200, 你要对它做怎样的运算会得到2?"/"给你一个223, 你要对它做怎样的运算会得到2?"
- 200 / 100 = 2; 234 / 100 = 2 (余34)
- 如何获取百位的数值. "给你一个200, 你要对它做怎样的运算会得到2?"/"给你一个223, 你要对它做怎样的运算会得到2?"
- (如果有十位, 则) 查看十位数, 获取十位数的数值, 存储(或直接输出), 对应个数的"S"
- 如何获取十位的数值. "给你一个30, 你要对它做怎样的运算会得到3?"/"给你一个234, 你要对它做怎样的运算会得到3?"
- 30 / 10 = 3; 234 / 100 = 2 (余34) 34 / 3 = 3 (余4)
- 如何获取十位的数值. "给你一个30, 你要对它做怎样的运算会得到3?"/"给你一个234, 你要对它做怎样的运算会得到3?"
- 查看个位数, 获取个位数的数值, 存储(或直接输出), 从1到对应值的各个数字
- 如何获取个位的数值.
- 输出答案
数据存储的考虑
我们需要存储的数据有:
- 输入数据
- 我们可以将输入数据跟它的含义一样存储成数值类型; 也可以存储成字符串类型;
- 计算过程中还没有全部转化格式的结果.
更多细节上的考虑
- "查看百位数 -> 查看十位数 -> 查看个位数"的过程分析
- 这个过程可以看成是对正整数各个数位从左到右的遍历.
- 关于如何遍历数据的各个数位, 我们在1001中提及过. 需要我们通过数学逻辑来事先对一个数值类型的整数的"遍历/循环操作"
- 同样在1001中提及, 我们可以将正整数存储成字符串, 用依次访问字符串的各个字符来达到依次处理整数各个数位的目的。依次访问对应了【循环】结构,而且整数输入后位数(即字符串中有效值的个数)是固定的, 所以循环的次数是固定的, 优先采用for循环。
- 由于只可能是3位数, 2位数, 1位数这三种情况, 所以我们也可以直接针对这三种情况直接检查属于哪种情况(条件判断), 然后执行对应处理
- 这是区别于"循环遍历"的另一个方案. 如果比较两个方案:
- 从可行性上两个方案都可行;
- 从实现难易程度上,这个方案更加易于实现;
- 从通用性(比如问题变为给定不超过4位数的正整数后是否需要改动代码的量)来说, 遍历更优.
- 这是区别于"循环遍历"的另一个方案. 如果比较两个方案:
- 这个过程可以看成是对正整数各个数位从左到右的遍历.
自我加餐
如果题设给定的正整数改为不超过9位数的正整数,该如何解决?
完整提交代码
/*
思路: 以终为始拆解问题
根据题目要求, 给定一个不超过3位数的正整数, 比如: 234,
输出"BBSSS1234", 表示这个正整数有 2 个“百”、3 个“十”、以及个位的 4
其中: "BB"表示 2 个“百”
"SSS"表示 3 个“十”
"1234"表示个位数为 4
按照这个逻辑, 我们可以将题目的要求重新描述为以下形式:
给定一个不超过3位数的正整数,
(如果有百位) 百位是多少, 就输出多少个"B"
(如果有十位) 十位是多少, 就输出多少个"S"
个位数是多少, 就输出从1开始直到这个位数值的各个数字
样例:
"345" -> "BBBSSSS12345"
"234" -> "BBSSS1234"
"123" -> "BSS123"
"12" -> "S12"
"2" -> "12"
进一步, 我们可以思路用更接近代码的形式描述为如下步骤:
1. 获取正整数 【数据输入】
2. (如果有百位, 则) 查看百位数, 获取百位数的数值, 存储(或直接输出), 对应个数的"B"
- 如何获取百位的数值. "给你一个200, 你要对它做怎样的运算会得到2?"/"给你一个223, 你要对它做怎样的运算会得到2?"
- 200 / 100 = 2; 234 / 100 = 2 (余34)
3. (如果有十位, 则) 查看十位数, 获取十位数的数值, 存储(或直接输出), 对应个数的"S"
- 如何获取十位的数值. "给你一个30, 你要对它做怎样的运算会得到3?"/"给你一个234, 你要对它做怎样的运算会得到3?"
- 30 / 10 = 3; 234 / 100 = 2 (余34) 34 / 3 = 3 (余4)
4. 查看个位数, 获取个位数的数值, 存储(或直接输出), 从1到对应值的各个数字
- 如何获取个位的数值.
5. 输出答案
【更多细节上的考虑】
"查看百位数 -> 查看十位数 -> 查看个位数"的过程分析
- 这个过程可以看成是对正整数各个数位从左到右的遍历.
- 关于如何遍历数据的各个数位, 我们在1001中提及过. 需要我们通过数学逻辑来事先对一个数值类型的整数的"遍历/循环操作"
- 同样在1001中提及, 我们可以将正整数存储成字符串, 用依次访问字符串的各个字符来达到依次处理整数各个数位的目的
- 采用字符串储存的方案, 由于后续依次访问需要使用【循环】
- 整数输入后位数(即字符串中有效值的个数)是固定的, 所以循环的次数是固定的, 优先采用for循环
- 由于只可能是3位数, 2位数, 1位数这三种情况, 所以我们也可以直接针对这三种情况直接检查属于哪种情况(条件判断), 然后执行对应处理
- 这是区别于"循环遍历"的另一个方案. 从可行性上哪个方案都可以, 从通用性(比如问题变为给定不超过4位数的正整数后是否需要改动代码的量)来说, 遍历更优.
【数据的存储】
我们需要存储的数据有:
1. 输入数据
- 我们可以将输入数据跟它的含义一样存储成数值类型; 但我们
2. 计算过程中还没有全部转化格式的结果.
*/
void change_format_of_number(int number){
/*转换不超过3位数的正整数的表示格式. 转换逻辑如下:
(if有百位 / if是三位数, 则) 查看百位数, 获取百位数的数值, 存储(或直接输出), 对应个数的"B"
(if有十位 / if是两位数, 则) 查看十位数, 获取十位数的数值, 存储(或直接输出), 对应个数的"S"
查看个位数, 获取个位数的数值, 存储(或直接输出), 从1到对应值的各个数字
*/
if (number >= 100) {
int value_in_hundred = number / 100;
for (int i = 0; i < value_in_hundred; i++){
printf("B");
}
}
if (number >= 10){
int value_in_ten = (number % 100) / 10;
for (int i = 0; i < value_in_ten; i++){
printf("S");
}
}
int digit = number % 10;
for (int i = 1; i <= digit; i++){
printf("%d", i);
}
printf("\n");
}
int main(){
int number;
scanf("%d", &number);
change_format_of_number(number);
return 0;
}