【问题标题】:Comparing with more than one char in C++与 C++ 中的多个字符进行比较
【发布时间】:2018-03-16 18:47:14
【问题描述】:

假设我有一个存储在char c 中的输入,并且在有条件的情况下我需要检查它是否是两个不同字符中的一个,例如'n''N'。很明显,我可以使用逻辑 OR 运算符创建条件:

if(c == 'n' || c == 'N')
...

但是,如果条件明显多于两个,则需要使用明显更多的逻辑运算符,并且编写、查看和编辑将变得乏味。有没有办法浓缩这个过程?为了使它看起来像这样:

if(c == '[N][n]')
...

有类似的东西存在吗?

【问题讨论】:

  • 您可以设置并测试成员资格。
  • 查看std::string::find_any_* 函数。
  • if(c = 'n' || c = 'N') --> if(c == 'n' || c == 'N')
  • 也许使用合适的容器和std::any_of
  • tolower(whatever) == 'lowercase_letter'

标签: c++ char


【解决方案1】:

您可以将匹配的字符组成一个字符串,并查看字符串中是否存在有问题的字符:

char c;
std::string good_chars = "nNyYq";
if(good_chars.find(c) != std::string::npos) {
    std::cout << "it's good!";
}

【讨论】:

  • 对 O(1) 问题的 O(N) 解决方案。您从事硬件租赁业务吗?
  • @Bathsheba O(n)?在这种情况下,n 对您来说是什么?在我看来,一切都是不变的......
  • find 是一个 O(N) 遍历。
  • @Bathsheba 我想如果你在谈论我对“查找一个字符是否在 N 个好字符的集合中”问题的解决方案,那么它是 O(n) 是对的,但是一旦他实现了这一点,n 就是一个常量(除非好的字符集在运行时发生变化,但没有指定)。请记住,即使 for(int i=0; i &lt; 999999; i++) { } 也是 O(1)...
【解决方案2】:

低技术含量的解决方案是改用switch 语句。如果您有很多匹配字符,使用case 标签可能会更容易阅读和编辑。

bool matches(char c)
{
    switch (c)
    {
        case 'n':
        case 'N':
        case 'a':
        case 'b':
        case 'c':
        return true;
    }
    return false;
}

更高级的解决方案是将字符存储在容器中。 std::set 是一个选项:

bool matches(char c)
{
    // note: might want to use static storage for `chars`
    std::set<char> const chars =
    {
        'n',
        'N',
        'a',
        'b',
        'c',
    };
    return chars.find(c) != end(chars);
}

std::string 允许更简洁的形式,就可读性和可维护性而言,这可能是好是坏:

bool matches(char c)
{
    // note: might want to use static storage for `chars`
    std::string const chars = "nNabc";
    return chars.find(c) != std::string::npos;
}

请注意,不同的容器具有不同的算法复杂性特征,如果像 match 这样的函数实际上应该成为性能瓶颈,这可能是相关的。

【讨论】:

  • 您应该注意,按照您的演示顺序,方法是 O(1)、O(log N),然后是 O(N)。
  • 开关真的是 O(1) 吗?我希望最坏的情况仍然是 O(n) 测试,直到你匹配
  • @Bathsheba:我不确定这是否接近于过早的优化。 OP 的问题主要是关于代码变得“编写、查看和编辑乏味”。不过,我将添加一条关于容器选择对算法复杂性有影响的说明。
【解决方案3】:

如果您的扫描不区分大小写,您可以使用 to_upper or to_lower API:

char c = 'n';
if( static_cast<unsigned char>('N') == std::toupper(static_cast<unsigned char>(c)) )
    // do something

或者:

char c = 'n';
if( static_cast<unsigned char>('n') == std::tolower(static_cast<unsigned char>(c)) )
    // Do something

【讨论】:

  • 这两个函数实际上要求您将参数转换为unsigned char。有关详细信息,请参阅en.cppreference.com/w/cpp/string/byte/toupper
  • @ChristianHackl:已编辑。
  • 为什么是 C 风格的演员而不是 static_cast&lt;unsigned char&gt;?无论如何,这不再是反对投票的理由,所以我将其删除。
猜你喜欢
  • 1970-01-01
  • 2014-09-18
  • 2015-03-14
  • 2020-04-15
  • 2020-07-01
  • 2021-03-04
  • 2018-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多