从最多 X 个字符构造 std::string,在空字符处停止

Construct std::string from up to X characters, stopping at null char

我正在从文件中的结构中读取字符串,其中每个字符串都有固定长度,并带有 '[=12=]' 填充。如果存储的字符串需要整个长度,它们不是零终止的。

我目前正在用这样的东西构建 std::strings:

// char MyString[1000];
std::string stdmystring(MyString, ARRAYSIZE(MyString));

但是,这也会复制填充。我现在可以 trim 字符串,但是有没有一种优雅而快速的方法来首先防止复制?

速度比space更重要,因为它是循环运行的。

简单的解决方案是:

  1. 先计算正确的长度

    • 按照 Dieter 的建议使用 strnlen
    • std::find(MyString,MyString+ARRAYSIZE(MyString),'[=11=]') IME 并不慢

    请注意,如果您的字符串适合缓存,这可能会控制额外的循环成本

  2. 保留最大字符串大小(您确实说过 space 不太重要),并编写一个循环附加字符,直到您耗尽宽度或命中 nul(如 copy_until)

  3. 实际创建一个用 nuls 初始化的最大大小的字符串,strncpy 放入其中,如果您希望大小正确,可以选择删除 unused nuls

第二个选项只使用一个循环,而第三个选项名义上使用两个(它在字符串 ctor 中,然后在副本中)。然而,每个字符的 push_back 似乎比简单的字符分配更昂贵,所以如果 #3 在现实中更快,我不会感到惊讶。简介看看!

好吧,如果大小不是问题,一种可能的方法是创建一个空的 std::string,然后使用 reserve() 预分配可能需要的 space,然后添加每个字符,直到遇到 '[=13=]'.

std::string stdmystring;
stdmystring.reserve(MyString_MAX_SIZE) ;
for(size_t i=0;i<MyString_MAX_SIZE && MyString[i]!='[=10=]';++i);
stdmystring+=MyString[i];

reserve() 为您提供一个内存分配,因为您知道 max_size 并且字符串永远不会大于该值。

对 += 运算符函数的调用可能会被内联,但它仍然必须检查字符串是否具有所需的容量,这在您的情况下是浪费的。事实上,这可能与简单地使用 strlen 首先找到字符串的确切长度相同或更差,因此您必须对其进行测试。

我认为最直接的方法是将内部 MyString 数组过度分配一个字节,始终以 null 终止最后一个字节,并使用 std::string 的 C 字符串构造函数。 (请记住,您的进程很可能会 I/O 绑定到文件上,因此 C 字符串构造函数使用的任何算法都应该没问题)。