合法驼峰命名分小驼峰(首字母小写,后续单词首字母大写,如myFirstName)和大驼峰(各单词首字母均大写,如MyFirstName),禁用空格、下划线等分隔符,数字可出现在中间或末尾,但不可开头,且通常避免连续大写字母。

什么是合法的驼峰命名(CamelCase)?
严格来说,C++ 标准不定义“驼峰命名法”,但工程中普遍接受:camelCase(小驼峰:首字母小写,后续单词首字母大写,无分隔符)或 PascalCase(大驼峰:所有单词首字母大写)。检查前必须明确规则——比如是否允许数字、下划线、空格,是否禁止连续大写字母(如 XMLParser 是否算合法)。常见误判点是把 iPhone 或 parseURL 当作非法,其实它们符合小驼峰惯例。
用 std::isalpha 和 std::islower 逐字符判断
最直接的方式是遍历字符串,结合 ASCII 字符分类函数。注意:必须先排除空字符串、首字符非法(小驼峰要求首字符小写)、纯数字等边界情况。
关键逻辑:
-
camelCase要求第一个字符是小写字母:std::islower(str[0])且std::isalpha(str[0]) - 后续字符可以是小写字母、大写字母或数字,但不能出现
_、-、空格等分隔符 - 不允许连续两个大写字母(除非你明确接受 Acronym 风格,如
parseXMLData) - 不能以数字开头(C++ 标识符本身就不允许),但驼峰字符串作为普通字符串时,数字出现在中间或末尾是允许的(如
user1Count)
示例片段(仅校验基础小驼峰):
立即学习“C++免费学习笔记(深入)”;
bool isCamelCase(const std::string& s) {
if (s.empty()) return false;
if (!std::islower(static_cast<unsigned char>(s[0])) || !std::isalpha(static_cast<unsigned char>(s[0])))
return false;
bool prevWasUpper = false;
for (size_t i = 1; i < s.length(); ++i) {
unsigned char c = s[i];
if (std::isalpha(c)) {
if (std::isupper(c)) {
if (prevWasUpper) return false; // 连续大写
prevWasUpper = true;
} else {
prevWasUpper = false;
}
} else if (!std::isdigit(c)) {
return false; // 非字母非数字
} else {
prevWasUpper = false; // 数字重置状态
}
}
return true;
}
为什么不能只靠正则表达式(std::regex)?
std::regex 在 C++11/14 中性能差、编译开销大,且部分标准库实现(如 libstdc++)对 Unicode 支持弱——而驼峰字符串可能含非 ASCII 字母(如 caféName)。更实际的问题是:正则很难优雅表达“不能连续两个大写字母”这种状态依赖逻辑。例如 "^[a-z][a-zA-Z0-9]*$" 会放过 XMLHttp,但它是否合法取决于团队约定,正则无法动态判断上下文。
如果坚持用正则,至少加一层预过滤:
- 先用
s.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")快速排除非法字符 - 再用正则匹配基础结构,避免全量扫描
- 注意
std::regex构造函数抛异常,需try/catch
区分标识符校验和普通字符串校验
如果你实际想检查的是“能否作为 C++ 变量名”,那要额外满足:std::isidentifier(C++23)或手动验证首字符不是数字、不是关键字(如 class、return)。但驼峰命名检查通常用于代码生成、lint 工具或配置解析,此时字符串只是内容,不涉及编译器语义。容易混淆的点是:传入 "_myVar" 或 "MyVar",前者是下划线开头(非驼峰),后者是 PascalCase(不是小驼峰)——必须按目标场景明确接受哪种子集。
真正麻烦的不是逻辑,而是模糊需求:团队说“要驼峰”,但没说是否允许 getHTTPResponse、是否接受单字母前缀(iCount)、是否忽略数字位置。这些都得在调用前协商清楚,否则代码写得再严谨也白搭。


















