我想我会做一些不同的工作,把它std::string
当作一个集合,并使用一种算法。使用 C++0x lambda,它看起来像这样:
bool has_special_char(std::string const &str) {
return std::find_if(str.begin(), str.end(),
[](unsigned char ch) { return !(isalnum(ch) || ch == '_'); }) != str.end();
}
至少当您处理char
(not wchar_t
) 时,isalnum
通常会使用表格查找,因此它通常会(相当多)比任何基于find_first_of
(通常会使用线性搜索)更快。IOW,这是 O(N) (N=str.size()),其中基于的东西find_first_of
将是 O(N*M), (N=str.size(), M=pattern.size())。
如果您想使用纯 C 来完成这项工作,您可以使用scanf
理论上不可移植的扫描集转换,但基本上所有最近/流行的编译器都支持:
char junk;
if (sscanf(str, "%*[A-Za-z0-9_]%c", &junk))
/* it has at least one "special" character
else
/* no special characters */
这里的基本思想非常简单:扫描集会跳过所有连续的非特殊字符(但不会将结果分配给任何东西,因为*
),然后我们尝试再读取一个字符。如果成功,则意味着至少有一个字符没有被跳过,所以我们必须至少有一个特殊字符。如果失败,则意味着扫描集转换匹配整个字符串,因此所有字符都是“非特殊”的。
正式地,C 标准表示尝试将范围放入像这样的扫描集转换是不可移植的(除了扫描集的开头或结尾之外的任何地方都有一个“-”给出实现定义的行为)。甚至有一些编译器(来自 Borland)会因此而失败——它们会将A-Z
三个可能的字符视为完全匹配,“A”、“-”和“Z”。大多数当前的编译器(或更准确地说,标准库实现)采用这种假设的方法:“AZ”匹配任何大写字符。