C++ 是否有 std::strchr() 的现代替代品?
Are there any modern alternatives of std::strchr() for C++?
我在我的代码中广泛使用 std::strchr()
,但最近我开始考虑让我的代码更具可读性和现代性。我希望有类似于 std::any_of/std::string::find_first_of
的功能,它采用单个字符而不是容器。所以我在问自己如何 "update" 我的代码到 C++17。
while (std::strchr("abcd", input) == nullptr) { //how to get rid of this C function?
//do smth
}
有什么想法吗?
谢谢,祝你有个愉快的一天!
您可以将 std::find
与字符串一起使用,或者 std::string
自己的 std::string::find。
您可以使用 std::string
的 find_first_of
。示例:
std::string string{"abcdefglrkemf..."};
while (string.find_first_of("def") != std::string::npos)
//...
但是如果您不想创建新的 std::string
对象,strstr
是可行的方法。但请注意,这会影响性能。
更新您的代码没有意义,因为字符串文字具有字符数组类型。
创建一个中间对象 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 字符串的通用函数
and/or 类型 std::string
的对象,然后如果函数不更改它们,则使用 std::string_view
作为函数参数。
如果可以将 C 字符串存储在数组中,则可以像这样使用 std::find
:
constexpr char charset[] = "abcd";
while (std::find(std::begin(charset), std::end(charset), input)
== std::end(charset))
{...}
看起来 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; }
我在我的代码中广泛使用 std::strchr()
,但最近我开始考虑让我的代码更具可读性和现代性。我希望有类似于 std::any_of/std::string::find_first_of
的功能,它采用单个字符而不是容器。所以我在问自己如何 "update" 我的代码到 C++17。
while (std::strchr("abcd", input) == nullptr) { //how to get rid of this C function?
//do smth
}
有什么想法吗?
谢谢,祝你有个愉快的一天!
您可以将 std::find
与字符串一起使用,或者 std::string
自己的 std::string::find。
您可以使用 std::string
的 find_first_of
。示例:
std::string string{"abcdefglrkemf..."};
while (string.find_first_of("def") != std::string::npos)
//...
但是如果您不想创建新的 std::string
对象,strstr
是可行的方法。但请注意,这会影响性能。
更新您的代码没有意义,因为字符串文字具有字符数组类型。
创建一个中间对象 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 字符串的通用函数
and/or 类型 std::string
的对象,然后如果函数不更改它们,则使用 std::string_view
作为函数参数。
如果可以将 C 字符串存储在数组中,则可以像这样使用 std::find
:
constexpr char charset[] = "abcd";
while (std::find(std::begin(charset), std::end(charset), input)
== std::end(charset))
{...}
看起来 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; }