华为OD机试 - 统计文本数量(Python/JS/C/C++ 2025 A卷 100分)

在这里插入图片描述

2025A卷华为OD机试统一考试题库清单(持续收录中)以及考点说明(Python/JS/C/C++)

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

一、题目描述

有一个文件,包含以一定规则写作的文本,请统计文件中包含的文本数量。

规则如下:

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++ 2025 A卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哪 吒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值