华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
有一个文件,包含以一定规则写作的文本,请统计文件中包含的文本数量。
规则如下:
1、文本以";“分隔,最后一条可以没有”;",但空文本不能算语句,比如"COMMAND A;“只能算一条语句。注意,无字符/空白字符Q/制表符等操作"空文本”;
2、文本可以跨行,比如下面,是一条文本,而不是三条;
COMMAND A
AND
COMMAND B;
文本支持字符串,字符串为成对的单引号(‘)或者成对的双引号("),字符串中可能出现用转义字符()处理的单双引号(‘your input is’”)和转义字符串本身,比如
COMMAND A "Say \"hello\"";
支持注释,可以出现在字符串之外的任意位置注释以"—"开头,到换行结束,比如:
COMMAND A; —this is comment
COMMAND —comment
A AND COMMAND B;
注意 字符串Q 内的“—”,不是注释。
二、输入描述
文本文件
三、输出描述
包含的文本数量
四、测试用例
测试用例1:
1、输入
COMMAND A;
COMMAND B;
COMMAND C; — This is a comment
COMMAND D; — Another comment
2、输出
4
3、说明
本例中的文件内容有4个命令,每个命令都以分号结尾。
尽管第三行和第四行后面有注释,注释部分不会影响命令的统计。
因此,总共4条有效命令。
测试用例2:
1、输入
COMMAND A;
COMMAND B
AND COMMAND C;
COMMAND “D"Text”";
— Entire line is a comment
COMMAND E; — Comment at the end
2、输出
4
3、说明
第一行 COMMAND A; 是一条有效命令。
第二行和第三行合并构成一条跨行命令 COMMAND B AND COMMAND C;。
第四行 COMMAND “D"Text”"; 是一条有效命令,其中 " 表示转义字符,表示字符串中的双引号。
第五行是一个注释,应该被忽略。
第六行 COMMAND E; 是一条有效命令,尽管有注释。
最终,共有4条有效命令。
五、解题思路
程序会检查文件内容中的注释,并将这些注释移除。注释是以 “—” 开头,直到该行结束。需要注意的是,程序会确保只移除字符串之外的注释,即在字符串内的 “—” 不会被视为注释。这一步是为了避免注释内容干扰命令的统计。
程序会根据分号(;)将内容分割成多个部分,每个部分代表一个潜在的命令。
对于每个分割出的部分,程序会去除首尾空白符,并检查内容是否为空。只有非空的部分才会被计数为有效命令。这一步是为了确保空白命令或无效的命令不会被错误地计入。
程序会输出统计得到的有效命令数量。这个数量即为文件中符合规则的命令的总数。
六、Python算法源码
import sys
def is_escaped(line, index):
"""
判断当前位置的字符是否被转义
:param line: 当前处理的行字符串
:param index: 当前字符的索引
:return: 如果字符被转义,返回True;否则返回False
"""
backslash_count = 0
index -= 1 # 检查当前字符前面的字符
while index >= 0 and line[index] == '\\':
backslash_count += 1
index -= 1
return backslash_count % 2 != 0 # 如果反斜杠数量为奇数,则字符被转义
def find_comment_index(line):
"""
找到注释的起始位置,忽略字符串内的注释符
:param line: 当前处理的行字符串
:return: 注释符的索引,如果没有注释,返回-1
"""
in_single_quote = False # 是否在单引号字符串内
in_double_quote = False # 是否在双引号字符串内
for i, ch in enumerate(line):
if ch == '\'' and not is_escaped(line, i):
in_single_quote = not in_single_quote # 切换单引号状态
elif ch == '"' and not is_escaped(line, i):
in_double_quote = not in_double_quote # 切换双引号状态
elif ch == '—' and not in_single_quote and not in_double_quote:
return i # 找到不在字符串内的注释符
return -1 # 没有找到注释符
def main():
count = 0 # 有效命令计数
current_text = [] # 当前命令的内容列表
in_single_quote = False # 是否在单引号字符串内
in_double_quote = False # 是否在双引号字符串内
for line in sys.stdin:
line = line.rstrip('\n') # 移除行尾的换行符
if not line:
break # 输入空行结束输入
# 处理注释:找到注释符的位置并截断
comment_index = find_comment_index(line)
if comment_index != -1:
line = line[:comment_index]
i = 0 # 当前字符索引
while i < len(line):
ch = line[i] # 当前字符
# 处理引号,切换状态
if ch == '\'' and not is_escaped(line, i):
in_single_quote = not in_single_quote
elif ch == '"' and not is_escaped(line, i):
in_double_quote = not in_double_quote
# 处理文本结束符';'
if ch == ';' and not in_single_quote and not in_double_quote:
if ''.join(current_text).strip(): # 如果当前命令非空
count += 1 # 有效命令数加一
current_text = [] # 重置当前命令内容
else:
current_text.append(ch) # 添加字符到当前命令
i += 1 # 移动到下一个字符
current_text.append('\n') # 保留换行符以支持跨行命令
# 处理最后一个可能没有分号的文本
final_text = ''.join(current_text).strip()
if final_text and not final_text.startswith('—'):
count += 1 # 如果最后的文本非空且不是注释,计数加一
print(count) # 输出有效命令数量
if __name__ == "__main__":
main()
七、JavaScript算法源码
const readline = require('readline');
/**
* 判断当前位置的字符是否被转义
* @param {string} line - 当前处理的行字符串
* @param {number} index - 当前字符的索引
* @returns {boolean} 如果字符被转义,返回true;否则返回false
*/
function isEscaped(line, index) {
let backslashCount = 0;
index -= 1; // 检查当前字符前面的字符
while (index >= 0 && line[index] === '\\') {
backslashCount++;
index--;
}
return backslashCount % 2 !== 0; // 如果反斜杠数量为奇数,则字符被转义
}
/**
* 找到注释的起始位置,忽略字符串内的注释符
* @param {string} line - 当前处理的行字符串
* @returns {number} 注释符的索引,如果没有注释,返回-1
*/
function findCommentIndex(line) {
let inSingleQuote = false; // 是否在单引号字符串内
let inDoubleQuote = false; // 是否在双引号字符串内
for (let i = 0; i < line.length; i++) {
const ch = line[i];
if (ch === '\'' && !isEscaped(line, i)) {
inSingleQuote = !inSingleQuote; // 切换单引号状态
} else if (ch === '"' && !isEscaped(line, i)) {
inDoubleQuote = !inDoubleQuote; // 切换双引号状态
} else if (ch === '—' && !inSingleQuote && !inDoubleQuote) {
return i; // 找到不在字符串内的注释符
}
}
return -1; // 没有找到注释符
}
// 创建读取接口,用于逐行读取输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
let count = 0; // 有效命令计数
let currentText = []; // 当前命令的内容数组
let inSingleQuote = false; // 是否在单引号字符串内
let inDoubleQuote = false; // 是否在双引号字符串内
// 监听每一行的输入
rl.on('line', (line) => {
if (line === '') {
rl.close(); // 输入空行结束输入
return;
}
// 处理注释:找到注释符的位置并截断
const commentIndex = findCommentIndex(line);
if (commentIndex !== -1) {
line = line.substring(0, commentIndex);
}
for (let i = 0; i < line.length; i++) {
const ch = line[i];
// 处理引号,切换状态
if (ch === '\'' && !isEscaped(line, i)) {
inSingleQuote = !inSingleQuote;
} else if (ch === '"' && !isEscaped(line, i)) {
inDoubleQuote = !inDoubleQuote;
}
// 处理文本结束符';'
if (ch === ';' && !inSingleQuote && !inDoubleQuote) {
if (currentText.join('').trim().length > 0) { // 如果当前命令非空
count++; // 有效命令数加一
currentText = []; // 重置当前命令内容
}
} else {
currentText.push(ch); // 添加字符到当前命令
}
}
currentText.push('\n'); // 保留换行符以支持跨行命令
});
// 输入结束后处理
rl.on('close', () => {
// 处理最后一个可能没有分号的文本
const finalText = currentText.join('').trim();
if (finalText.length > 0 && !finalText.startsWith('—')) {
count++; // 如果最后的文本非空且不是注释,计数加一
}
console.log(count); // 输出有效命令数量
});
八、C算法源码
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LINE_LENGTH 1000
/**
* 判断当前位置的字符是否被转义
* @param line 当前处理的行字符串
* @param index 当前字符的索引
* @return 如果字符被转义,返回true;否则返回false
*/
bool is_escaped(char *line, int index) {
int backslash_count = 0;
index--; // 检查当前字符前面的字符
while (index >= 0 && line[index] == '\\') {
backslash_count++;
index--;
}
return backslash_count % 2 != 0; // 如果反斜杠数量为奇数,则字符被转义
}
/**
* 找到注释的起始位置,忽略字符串内的注释符
* @param line 当前处理的行字符串
* @return 注释符的索引,如果没有注释,返回-1
*/
int find_comment_index(char *line) {
bool in_single_quote = false; // 是否在单引号字符串内
bool in_double_quote = false; // 是否在双引号字符串内
int len = strlen(line);
for (int i = 0; i < len; i++) {
char ch = line[i];
if (ch == '\'' && !is_escaped(line, i)) {
in_single_quote = !in_single_quote; // 切换单引号状态
} else if (ch == '"' && !is_escaped(line, i)) {
in_double_quote = !in_double_quote; // 切换双引号状态
} else if (ch == '—' && !in_single_quote && !in_double_quote) {
return i; // 找到不在字符串内的注释符
}
}
return -1; // 没有找到注释符
}
int main() {
char line[MAX_LINE_LENGTH]; // 用于存储每一行输入
int count = 0; // 有效命令计数
char current_text[MAX_LINE_LENGTH * 10] = ""; // 当前命令的内容字符串
// 逐行读取输入
while (fgets(line, sizeof(line), stdin)) {
// 移除末尾的换行符
size_t len = strlen(line);
if (len > 0 && line[len - 1] == '\n') {
line[len - 1] = '\0';
}
if (strlen(line) == 0) {
break; // 输入空行结束输入
}
// 处理注释:找到注释符的位置并截断
int comment_index = find_comment_index(line);
if (comment_index != -1) {
line[comment_index] = '\0';
}
// 遍历每个字符
for (int i = 0; i < strlen(line); i++) {
char ch = line[i];
// 处理引号,切换状态
if (ch == '\'' && !is_escaped(line, i)) {
// 切换单引号状态
// 在C语言中,单引号用于字符,通常不会跨多个字符
// 此处假设与Java代码逻辑一致
// 实际应用中可能需要调整
} else if (ch == '"' && !is_escaped(line, i)) {
// 切换双引号状态
// 同上
}
// 需要重新处理引号状态
bool in_single_quote = false;
bool in_double_quote = false;
for (int j = 0; j <= i; j++) {
if (line[j] == '\'' && !is_escaped(line, j)) {
in_single_quote = !in_single_quote;
} else if (line[j] == '"' && !is_escaped(line, j)) {
in_double_quote = !in_double_quote;
}
}
// 处理文本结束符';'
if (ch == ';' && !in_single_quote && !in_double_quote) {
// 检查current_text是否非空
bool non_empty = false;
for (int k = 0; k < strlen(current_text); k++) {
if (current_text[k] != ' ' && current_text[k] != '\t' && current_text[k] != '\n') {
non_empty = true;
break;
}
}
if (non_empty) {
count++; // 有效命令数加一
current_text[0] = '\0'; // 重置当前命令内容
}
} else {
// 添加字符到当前命令
int current_len = strlen(current_text);
if (current_len < sizeof(current_text) - 1) { // 防止溢出
current_text[current_len] = ch;
current_text[current_len + 1] = '\0';
}
}
}
// 添加换行符以支持跨行命令
strcat(current_text, "\n");
}
// 处理最后一个可能没有分号的文本
// 移除前导空白
char *final_text = current_text;
while (*final_text == ' ' || *final_text == '\t' || *final_text == '\n') {
final_text++;
}
if (strlen(final_text) > 0 && final_text[0] != '—') {
count++; // 如果最后的文本非空且不是注释,计数加一
}
printf("%d\n", count); // 输出有效命令数量
return 0;
}
九、C++算法源码
#include <iostream>
#include <string>
using namespace std;
/**
* 判断当前位置的字符是否被转义
* @param line 当前处理的行字符串
* @param index 当前字符的索引
* @return 如果字符被转义,返回true;否则返回false
*/
bool is_escaped(const string &line, int index) {
int backslash_count = 0;
index--; // 检查当前字符前面的字符
while (index >= 0 && line[index] == '\\') {
backslash_count++;
index--;
}
return backslash_count % 2 != 0; // 如果反斜杠数量为奇数,则字符被转义
}
/**
* 找到注释的起始位置,忽略字符串内的注释符
* @param line 当前处理的行字符串
* @return 注释符的索引,如果没有注释,返回-1
*/
int find_comment_index(const string &line) {
bool in_single_quote = false; // 是否在单引号字符串内
bool in_double_quote = false; // 是否在双引号字符串内
for (int i = 0; i < line.length(); i++) {
char ch = line[i];
if (ch == '\'' && !is_escaped(line, i)) {
in_single_quote = !in_single_quote; // 切换单引号状态
} else if (ch == '"' && !is_escaped(line, i)) {
in_double_quote = !in_double_quote; // 切换双引号状态
} else if (ch == '—' && !in_single_quote && !in_double_quote) {
return i; // 找到不在字符串内的注释符
}
}
return -1; // 没有找到注释符
}
int main() {
int count = 0; // 有效命令计数
string current_text = ""; // 当前命令的内容字符串
string line; // 用于存储每一行输入
// 逐行读取输入
while (getline(cin, line)) {
if (line.empty()) {
break; // 输入空行结束输入
}
// 处理注释:找到注释符的位置并截断
int comment_index = find_comment_index(line);
if (comment_index != -1) {
line = line.substr(0, comment_index);
}
// 遍历每个字符
for (size_t i = 0; i < line.length(); i++) {
char ch = line[i];
// 处理引号,切换状态
if (ch == '\'' && !is_escaped(line, i)) {
// 切换单引号状态
// 在C++中,单引号用于字符,通常不会跨多个字符
// 此处假设与Java代码逻辑一致
// 实际应用中可能需要调整
} else if (ch == '"' && !is_escaped(line, i)) {
// 切换双引号状态
// 同上
}
// 需要重新处理引号状态
bool in_single_quote = false;
bool in_double_quote = false;
for (size_t j = 0; j <= i; j++) {
if (line[j] == '\'' && !is_escaped(line, j)) {
in_single_quote = !in_single_quote;
} else if (line[j] == '"' && !is_escaped(line, j)) {
in_double_quote = !in_double_quote;
}
}
// 处理文本结束符';'
if (ch == ';' && !in_single_quote && !in_double_quote) {
if (current_text.find_first_not_of(" \t\n") != string::npos) { // 如果当前命令非空
count++; // 有效命令数加一
current_text = ""; // 重置当前命令内容
}
} else {
current_text += ch; // 添加字符到当前命令
}
}
// 添加换行符以支持跨行命令
current_text += '\n';
}
// 处理最后一个可能没有分号的文本
// 移除前导空白
size_t start = current_text.find_first_not_of(" \t\n");
if (start != string::npos) {
string final_text = current_text.substr(start);
if (!final_text.empty() && final_text[0] != '—') {
count++; // 如果最后的文本非空且不是注释,计数加一
}
}
cout << count << endl; // 输出有效命令数量
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。