【问题标题】:Are there any modern alternatives of std::strchr() for C++?对于 C++,有 std::strchr() 的任何现代替代品吗?
【发布时间】:2020-01-21 16:41:09
【问题描述】:

我在我的代码中广泛使用std::strchr(),但最近我开始考虑让我的代码更具可读性和现代性。我希望有类似于std::any_of/std::string::find_first_of 的功能,它采用单个字符而不是容器。所以我在问自己如何将我的代码“更新”到 C++17。

while (std::strchr("abcd", input) == nullptr) { //how to get rid of this C function?
        //do smth
}

有什么想法吗?

谢谢,祝你有美好的一天!

【问题讨论】:

标签: c++ c-strings strchr


【解决方案1】:

看起来strchr 的现代 c++ 替代品是std::char_traits<char>::find。也是 constexpr!

while (std::char_traits<char>::find("abcd", input) == nullptr) { //how to get rid of this C function?
    //do smth
}

但是,我不确定这是否比您已有的更具可读性。 如果您的目标是纯粹的可读性,那么使用瘦内联包装器包装标准库函数没有任何问题。

inline bool DoesStringContainSubstring(const char* str, const char* subStr) { return std::strchr(str, subStr) != nullptr; }

【讨论】:

    【解决方案2】:

    更新代码是没有意义的,因为字符串文字的类型是字符数组。

    创建一个例如 std::string 的中间对象来执行这样一个简单的任务是个坏主意。

    对于像数组一样声明的 c 字符串,使用 C 字符串函数。 C 字符串函数经过优化,有时仅使用一对机器指令即可执行。

    与其他容器一起使用它们的成员函数或标准算法。

    例如比较两种方法

    const char *s = "abcd";
    
    const char *p = strchr( s, c );
    
    if ( p )
    {
        //...
    }
    

    甚至喜欢

    const char *s = "abcd";
    
    if ( const char *p = strchr( s, c ) )
    {
        //...
    }
    

    const char *s = "abcd";
    size_t n = std::strlen( s );
    
    auto it = std::find( s, s + n, c );
    
    if ( it != s + n )
    {
        //...
    }
    

    在 C++ 17 中的可读性更低

    const char *s = "abcd";
    size_t n = std::strlen( s );
    
    if ( auto it = std::find( s, s + n, c ); it != s + n )
    {
        //...
    }
    

    显然第一种方法效率更高。

    另一方面,如果您有一个应该接受 c 字符串的通用函数 和/或 std::string 类型的对象,那么如果函数没有更改它们,则使用 std::string_view 作为函数参数。

    【讨论】:

      【解决方案3】:

      如果可以将 C 字符串存储在数组中,则可以像这样使用std::find

      constexpr char charset[] = "abcd";
      while (std::find(std::begin(charset), std::end(charset), input) 
             == std::end(charset)) 
      {...}
      

      【讨论】:

      • 一般来说这种方法不适合,因为数组的大小可能大于存储的字符串的大小。
      • @vlad 你的意思是如果charset[50] = "abcd"?是的,但不确定这种情况是否属于您需要考虑的事项...我也可以说:在一般情况下(对于大型数组),这整个方法很糟糕,因为它具有线性运行时,最好将您的字符集放入首先是哈希图,循环中的查找会快得多。
      • 除了这种情况,程序可以处理指向 c 字符串第一个字符的指针。在这种情况下,您的方法无效。
      • @vlad 这正是我包含第一句话以及第一行代码的原因。如果您在程序中将字符集作为文字,您可以轻松地将它们拉出到数组中。否则,事情就没那么简单了。
      【解决方案4】:

      您可以使用std::stringfind_first_of。示例:

      std::string string{"abcdefglrkemf..."};
      
      while (string.find_first_of("def") != std::string::npos)
          //...
      

      但是如果你不想创建一个新的std::string 对象,strstr 是要走的路。但请注意,这会影响性能。

      【讨论】:

      【解决方案5】:

      您可以将std::find 与字符串一起使用,或者std::strings 自己的std::string::find

      【讨论】:

      • 使用std::string_view 会减少浪费。
      • @Deduplicator 假设 OP 以字符串文字开头,是的。
      猜你喜欢
      • 2010-12-22
      • 1970-01-01
      • 2012-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-22
      相关资源
      最近更新 更多