【华为OD-E卷 - 敏感字段加密 100分(python、java、c++、js、c)】
题目
给定一个由多个命令字组成的命令字符串:
字符串长度小于等于127字节,只包含大小写字母,数字,下划线和偶数个双引号; 命令字之间以一个或多个下划线_进行分割; 可以通过两个双引号””来标识包含下划线_的命令字或空命令字(仅包含两个双引号的命令字),双引号不会在命令字内部出现; 请对指定索引的敏感字段进行加密,替换为****(6个*),并删除命令字前后多余的下划线_。 如果无法找到指定索引的命令字,输出字符串ERROR**
输入描述
- 输入为两行,第一行为命令字索引K(从0开始),第二行为命令字符串S
输出描述
- 输出处理后的命令字符串,如果无法找到指定索引的命令字,输出字符串ERROR
用例
用例一:
输入:
1
password__a12345678_timeout_100
输出:
password_******_timeout_100
用例二:
输入:
password_******_timeout_100
输出:
aaa_password_******_timeout_100_""
python解法
- 解题思路:
- 这段代码的目标是处理一段字符串,根据输入的索引 k,将字符串中的第 k 个部分替换为 “******”,并返回替换后的字符串。字符串的分割规则如下:
分割规则:
双引号内的内容作为一个整体,不会被进一步分割。
其他部分根据下划线 _ 分割。
索引范围检查:
如果 k 超出分割后的部分数量,返回 “ERROR”。
替换部分:
将索引为 k 的部分替换为 “******”。
重新拼接字符串:
使用下划线 _ 将处理后的部分重新拼接成一个字符串。
import re# 输入参数
k = int(input()) # 要替换的部分索引
s = input() # 输入的字符串# 处理字符串的函数
def process_command(k, s):# 使用正则表达式分割字符串# pattern:# - `"[^"]*"` 匹配双引号内的内容,包括引号# - `|` 表示或# - `[^_]+` 匹配非下划线的连续字符pattern = re.compile(r'"[^"]*"|[^_]+')matches = pattern.findall(s) # 查找所有匹配的部分# 检查索引 k 是否有效if k >= len(matches): # 如果 k 超出范围return "ERROR" # 返回错误信息# 将第 k 个部分替换为 "******"matches[k] = "******"# 使用下划线将所有部分重新拼接成字符串return "_".join(matches)# 调用函数并输出结果
print(process_command(k, s))
java解法
- 解题思路
- 这段代码的目标是处理一段字符串,根据输入的索引 idx,将字符串中的第 idx 个部分替换为 “******”,并返回替换后的结果。如果 idx 超出字符串的部分数量,返回 “ERROR”。字符串的分割规则如下:
分割规则:
双引号内的内容作为一个整体,不会被进一步分割。
其他部分根据下划线 _ 分割。
索引范围检查:
如果 idx 超出分割后的部分数量,返回 “ERROR”。
替换部分:
将索引为 idx 的部分替换为 “******”。
重新拼接字符串:
使用下划线 _ 将所有部分重新拼接成一个字符串
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in); // 创建 Scanner 对象读取输入int idx = Integer.parseInt(in.nextLine()); // 读取第一个输入行作为索引String cmd = in.nextLine(); // 读取第二个输入行作为字符串System.out.println(procCmd(idx, cmd)); // 调用处理函数并输出结果}// 处理命令字符串public static String procCmd(int idx, String cmd) {// 定义正则表达式:// - `\"[^\"]*\"` 匹配双引号内的内容,包括双引号// - `[^_]+` 匹配非下划线的连续字符Pattern pat = Pattern.compile("\"[^\"]*\"|[^_]+");Matcher mat = pat.matcher(cmd); // 使用正则表达式匹配输入字符串StringBuilder res = new StringBuilder(); // 用于存储结果字符串int cnt = 0; // 记录当前部分的索引while (mat.find()) { // 遍历所有匹配的部分if (cnt++ == idx) { // 如果当前部分的索引等于目标索引res.append("******"); // 替换为 "******"} else {res.append(mat.group()); // 否则将原始部分加入结果}res.append("_"); // 在每部分后添加下划线}// 检查索引是否超出范围if (idx >= cnt) {return "ERROR"; // 如果目标索引大于等于总部分数,返回 "ERROR"}// 删除结果末尾多余的下划线并返回return res.substring(0, res.length() - 1);}
}
C++解法
- 解题思路
- 这段代码的目标是根据输入的索引 index,将字符串中的第 index 个部分替换为 “******”,并输出处理后的字符串。如果 index 超出了分割部分的数量,输出 “ERROR”。
字符串分割规则:
双引号包裹的内容:
双引号中的内容被视为一个整体,不会被分割。
双引号可以成对出现,也可以嵌套字符。
下划线 _ 分割部分:
未被双引号包裹的内容以下划线 _ 为分隔符分割为多个部分。
处理步骤:
遍历字符串,维护一个临时变量 part 用于存储当前部分。
使用标志变量 insideQuotes 记录当前是否在双引号范围内。
每当遇到下划线 _ 且不在双引号范围时,将当前部分加入结果,并根据索引判断是否替换为 “******”。
遍历结束后,处理最后一部分内容。
检查是否超出索引范围:
如果超出范围,输出 “ERROR”。
如果未超出范围,输出拼接后的结果。
#include <iostream>
#include <string>int main() {int index; // 用于存储输入的目标索引std::cin >> index; // 读取目标索引std::string line;std::cin.ignore(); // 忽略上一次输入的换行符std::getline(std::cin, line); // 读取完整的一行字符串std::string part; // 用于存储当前解析的部分int count = 0; // 记录当前部分的索引bool insideQuotes = false; // 标记当前是否在双引号范围内std::string result; // 用于存储最终的拼接结果// 遍历整个字符串for (size_t i = 0; i < line.size(); ++i) {if (line[i] == '\"') {// 遇到双引号时切换 insideQuotes 状态insideQuotes = !insideQuotes;part.push_back(line[i]); // 将双引号加入当前部分}else if (!insideQuotes && line[i] == '_') {// 遇到下划线且不在双引号范围时if (!part.empty()) { // 当前部分非空if (count == index) { // 如果当前部分是目标索引result += "******"; // 替换为 "******"}else {result += part; // 否则加入原部分}result += "_"; // 添加下划线分隔符count++; // 增加部分计数part.clear(); // 清空当前部分}}else {part.push_back(line[i]); // 将字符加入当前部分}}// 处理最后一部分if (!part.empty()) { // 如果最后一部分非空if (count == index) {result += "******"; // 替换为 "******"}else {result += part; // 加入原部分}}else if (result.back() == '_') {result.pop_back(); // 删除结果末尾多余的下划线}// 检查是否超出索引范围if (count >= index) {std::cout << result << std::endl; // 输出处理后的结果}else {std::cout << "ERROR" << std::endl; // 索引超出范围时输出 "ERROR"}return 0;
}
C解法
更新中
JS解法
输入的第一个行:一个整数 k,表示要替换的部分索引。
输入的第二行:一个命令字符串,由 "_” 分隔多个部分,部分内容可能用双引号 " 包裹,双引号包裹的内容视为一个整体。
目标是:
按规则解析命令字符串。
如果索引 k 超出解析的部分数量,返回 “ERROR”。
否则,将索引为 k 的部分替换为 “******”,并返回处理后的字符串。
const readline = require("readline");// 创建 CommandProcessor 类
class CommandProcessor {constructor() {this.lines = []; // 用于存储输入的两行内容}// 处理输入,每次读取一行processInput(line) {this.lines.push(line); // 将当前行添加到 `lines`if (this.lines.length === 2) { // 当读取到两行时开始处理const k = parseInt(this.lines[0]); // 第一行是索引 kconst commandStr = this.lines[1]; // 第二行是命令字符串console.log(this.encryptSensitiveField(commandStr, k)); // 输出处理结果this.lines.length = 0; // 重置 `lines`,以便处理下一组输入}}// 将索引为 `index` 的部分替换为 "******"encryptSensitiveField(commandStr, index) {const commandList = this.parseCommands(commandStr); // 解析命令字符串为部分列表if (index >= commandList.length) { // 如果索引超出部分数量,返回 "ERROR"return "ERROR";}commandList[index] = "******"; // 替换目标部分为 "******"return commandList.join("_"); // 使用下划线将部分拼接为字符串返回}// 解析命令字符串为部分列表parseCommands(str) {let parts = []; // 存储解析后的部分let current = []; // 存储当前部分的字符for (let i = 0; i < str.length; i++) {if (str[i] === "_" && current[0] !== '"') {// 遇到下划线且当前部分不在双引号内时,将当前部分加入列表parts.push(current.join(""));current = [];} else if (str[i] === '"' && current.length !== 0) {// 遇到双引号且当前部分非空时,结束当前部分并加入列表parts.push(current.join("") + '"');current = [];} else {current.push(str[i]); // 将字符加入当前部分}}if (current.length) parts.push(current.join("")); // 处理最后一部分return parts.filter((part) => part !== ""); // 过滤掉空部分}
}// 创建 `readline` 接口,用于读取输入
const rl = readline.createInterface({input: process.stdin,output: process.stdout,
});// 创建命令处理器实例
const processor = new CommandProcessor();// 监听每行输入
rl.on("line", (line) => {processor.processInput(line); // 调用 `processInput` 处理当前输入行
});
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏