You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++的switch语句中使用全名提升代码可读性?

问题描述

我是C新手,目前正在阅读Bjarne Stroustrup的《C编程原理与实践》。作为练习,我正在为终端计算器编写词法分析器和语法分析器,该分析器会判断表达式字符串中单个字符的类型,并为令牌分配对应的类型值。

以下是判断令牌类型的函数片段(为简化代码,未包含完整函数及所有分支):

switch(c)
{
    case '0': case '1': case '2': case '3': case '4': case '5': 
    case '6': case '7': case '8': case '9': case '.':
        return 'n'; // 'n' for number
    
    case '*': case '/':
        return 'm';     // m for multiplication or division

    case '(': case ')':
        return 'p'; // p for parenthesis

    case ' ':   // whitespace
        return 'w';
    
    default:
        throw std::invalid_argument("Invalid token: A non-valid character was passed to determineKind");
}

我使用字符表示令牌类型,是因为后续可以使用简洁的switch语句,而非可读性较差的、用字符串表示类型的if语句。但同时,'n'、'm'、'p'、'w'属于魔法常量,这又降低了解析器代码的可读性。

请问是否有办法在switch语句中使用“number”“whitespace”“parenthesis”这类全名,让代码更简洁易懂?


解决方案

用C++的**枚举类型(enum class)**就能完美解决这个问题——既保留switch语句的简洁性,又能用语义化全名替代魔法常量,大幅提升代码可读性。

1. 定义语义化枚举类

先定义一个enum class(推荐使用,避免命名污染和隐式类型转换问题),为每种令牌类型赋予清晰的名称:

#include <stdexcept>

enum class TokenKind {
    Number,        // 数字
    MulDiv,        // 乘除运算符
    Parenthesis,   // 括号
    Whitespace     // 空白符
};

2. 修改令牌类型判断函数

将原函数的返回类型改为TokenKind,直接返回枚举值替代魔法字符:

TokenKind determineKind(char c) {
    switch(c) {
        case '0': case '1': case '2': case '3': case '4': case '5': 
        case '6': case '7': case '8': case '9': case '.':
            return TokenKind::Number;
        
        case '*': case '/':
            return TokenKind::MulDiv;

        case '(': case ')':
            return TokenKind::Parenthesis;

        case ' ':
            return TokenKind::Whitespace;
        
        default:
            throw std::invalid_argument("Invalid token: A non-valid character was passed to determineKind");
    }
}

3. 后续switch语句示例

在语法分析器中使用令牌类型时,switch逻辑会非常直观,无需额外注释就能理解:

void processToken(TokenKind kind) {
    switch(kind) {
        case TokenKind::Number:
            // 处理数字逻辑
            break;
        case TokenKind::MulDiv:
            // 处理乘除运算逻辑
            break;
        case TokenKind::Parenthesis:
            // 处理括号逻辑
            break;
        case TokenKind::Whitespace:
            // 处理空白符逻辑
            break;
        // 按需添加其他分支
    }
}

为什么选enum class?

  • 强类型安全:枚举值不会隐式转换为整数,避免意外类型错误;
  • 无命名冲突:必须通过TokenKind::前缀访问枚举值,不用担心和其他代码的同名变量冲突;
  • 可读性强:语义化名称让代码自解释,无需依赖注释辅助理解。

若需兼容C++11之前的版本,也可以使用普通enum,但要注意避免命名空间冲突问题。


内容的提问来源于stack exchange,提问作者a_floating_point

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 04:58:17