「PAT乙级真题解析」Basic Level 1052 卖个萌 (问题分析+完整步骤+伪代码描述+提交通过代码)

题目给定三组符号集合作为"手", "眼", "口"的姿势, 要求根据用户输入的序号使用对应序号的"手", "眼", "口"以"[左手]([左眼][口][右眼])[右手]"的形式输出表情。 输出的部分很简单, 只要使用序号作为索引取到符号输出即可, 所以本题的重点不是输出, 而是如何从输入生成用于取数的符号集合. 对于一些封装层次比较高的语言, 完全可以使用正则之类的方法提取出符号生成集合. 也可以使用字符串分割的方式生成集合. 对于C语言, 需要自行实现符号提取逻辑.

#算法#数据结构#需求分析#pat考试#c语言

Table of Contents

乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。

PAT乙级BasicLevelPractice 1052

问题分析

题目给定三组符号集合作为"手", "眼", "口"的姿势, 要求根据用户输入的序号使用对应序号的"手", "眼", "口"以"[左手]([左眼][口][右眼])[右手]"的形式输出表情。 输出的部分很简单, 只要使用序号作为索引取到符号输出即可, 所以本题的重点不是输出, 而是如何从输入生成用于取数的符号集合. 对于一些封装层次比较高的语言, 完全可以使用正则之类的方法提取出符号生成集合. 也可以使用字符串分割的方式生成集合. 对于C语言, 需要自行实现符号提取逻辑.

如何提取符号

题设规定"每个符号括在一对方括号 []内", 所以"["标记着符号开始, 而"]"标记着符号结束. 所以在遇到"["时, 设置符号索引为下一个符号的序号, 字符存储索引为0, 然后直到遇到"]"之前都读取字符. 在遇到"]"时, 意味着符号结束, 在当前符号字符串的末尾加上结束符"\0". 这样之后再读入字符也是没有影响的(但是要避免继续读入索引越界)。 同时要记录符号的个数, 即, "]"的个数.

完整描述步骤

  1. 获取输入: "手", "眼", "口"的输入
  2. 从输入中提取"手", "眼", "口"的符号集合
  3. 获取用户请求数目
  4. 对于每一个请求:
    • 获取用户的5个符号选择
    • 检查5个符号选择是否都是大于0且小于对应的符号集合个数
      • 如果符号选择合法, 则输出包情报
      • 否则, 输出"Are you kidding me? @/@"(需要注意字符的转义)

伪代码描述

  1. get input of hands, eyes and mouses
  2. extract signs and generate sign set of hands, eyes and mouses:
    • init sign_index = 0, char_index = 0;
    • for char in input:
      • if char == '[':
        • sign_index++;
        • char_index = 0; contine;
      • else if char == ']':
        • signs_set[sign_index][char_index] = '\0';
      • else:
        • signs_set[sign_index][char_index] = char;
  3. get input: user query amount
  4. for each query:
    • get input: left_hand_index, left_eye_index, mouse_index, right_eye_index, right_hand_index
    • if indexes of user query is all in [1, hands_amount/eyes_amount/mouses_amount]:
      • print([左手]([左眼][口][右眼])[右手])
    • else:
      • print("Are you kidding me? @/@")

完整提交代码

/*
# 问题分析
题目给定三组符号集合作为"手", "眼", "口"的姿势, 
要求根据用户输入的序号使用对应序号的"手", "眼", "口"以"[左手]([左眼][口][右眼])[右手]"的形式输出表情。
输出的部分很简单, 只要使用序号作为索引取到符号输出即可,
所以本题的重点不是输出, 而是如何从输入生成用于取数的符号集合.
对于一些封装层次比较高的语言, 完全可以使用正则之类的方法提取出符号生成集合.
也可以使用字符串分割的方式生成集合.
对于C语言, 需要自行实现符号提取逻辑.
 
# 如何提取符号
题设规定"每个符号括在一对方括号 []内", 所以"["标记着符号开始, 而"]"标记着符号结束.
所以在遇到"["时, 设置符号索引为下一个符号的序号, 字符存储索引为0, 然后直到遇到"]"之前都读取字符.
在遇到"]"时, 意味着符号结束, 在当前符号字符串的末尾加上结束符"\0". 这样之后再读入字符也是没有影响的(但是要避免继续读入索引越界)。
同时要记录符号的个数, 即, "]"的个数.
 
# 完整描述步骤
1. 获取输入: "手", "眼", "口"的输入
2. 从输入中提取"手", "眼", "口"的符号集合
3. 获取用户请求数目
4. 对于每一个请求:
    - 获取用户的5个符号选择
    - 检查5个符号选择是否都是大于0且小于对应的符号集合个数
        - 如果符号选择合法, 则输出包情报
        - 否则, 输出"Are you kidding me? @\/@"(需要注意字符的转义)
 
# 伪代码描述
1. get input of hands, eyes and mouses
2. extract signs and generate sign set of hands, eyes and mouses:
    - init sign_index = 0, char_index = 0;
    - for char in input:
        - if char == '[':
            - sign_index++;
            - char_index = 0;
            contine;
        - else if char == ']':
            - signs_set[sign_index][char_index] = '\0';
        - else:
            - signs_set[sign_index][char_index] = char;
3. get input: user query amount
4. for each query:
    - get input: left_hand_index, left_eye_index, mouse_index, right_eye_index, right_hand_index
    - if indexes of user query is all in [1, hands_amount/eyes_amount/mouses_amount]:
        - print([左手]([左眼][口][右眼])[右手])
    - else:
        - print("Are you kidding me? @\/@")
*/
 
 
#include <stdio.h>
 
int read_signs(char signs[11][5]) {
  char input[50];
  fgets(input, 50, stdin);
  int char_index = 0, sign_index = 0;
  for (int i = 0; input[i] && sign_index < 11; i++) {
    if (input[i] == '[') {
      sign_index++;
      char_index = 0;
      continue;
    } else if (input[i] == ']') {
      signs[sign_index][char_index] = 0;
    } else {
      signs[sign_index][char_index] = input[i];
    }
    char_index++;
  }
 
  return sign_index;
}
 
int main() {
  char hands[11][5];
  char eyes[11][5];
  char mouses[11][5];
 
  int hands_amount = read_signs(hands);
  int eyes_amount = read_signs(eyes);
  int mouses_amount = read_signs(mouses);
 
  int case_amount;
  scanf("%d", &case_amount);
  int indexes[5];
  for (int i = 0; i < case_amount; i++) {
    for (int j = 0; j < 5; j++) {
      scanf("%d", &indexes[j]);
    }
    if (indexes[0] > 0 
        && indexes[1] > 0 
        && indexes[2] > 0 
        && indexes[3] > 0 
        && indexes[4] > 0 
        && indexes[0] <= hands_amount 
        && indexes[1] <= eyes_amount 
        && indexes[2] <= mouses_amount
        && indexes[3] <= eyes_amount
        && indexes[4] <= hands_amount) {
      printf("%s(%s%s%s)%s\n", hands[indexes[0]], eyes[indexes[1]],
             mouses[indexes[2]], eyes[indexes[3]], hands[indexes[4]]);
    } else {
      printf("Are you kidding me? @\\/@\n");
    }
  }
  return 0;
}
「PAT乙级真题解析」Basic Level 1052 卖个萌 (问题分析+完整步骤+伪代码描述+提交通过代码) | 生活糖果