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

C++ 从最多X个字符构造std::string,在null字符处停止,c++,stdstring,c++03,C++,Stdstring,C++03,我正在从一个文件的结构中读取字符串,其中每个字符串都有固定的长度,并带有'\0'填充。如果存储的字符串需要整个长度,则它们不会以零结尾 我目前正在用以下内容构建std::strings: // char MyString[1000]; std::string stdmystring(MyString, ARRAYSIZE(MyString)); 但是,这也会复制填充。我现在可以修剪绳子了,但是有没有一种优雅而快捷的方法来防止复制呢 速度比空间更重要,因为这是一个循环。简单的解决方案是: 先算出

我正在从一个文件的结构中读取字符串,其中每个字符串都有固定的长度,并带有
'\0'
填充。如果存储的字符串需要整个长度,则它们不会以零结尾

我目前正在用以下内容构建
std::string
s:

// char MyString[1000];
std::string stdmystring(MyString, ARRAYSIZE(MyString));
但是,这也会复制填充。我现在可以修剪绳子了,但是有没有一种优雅而快捷的方法来防止复制呢

速度比空间更重要,因为这是一个循环。

简单的解决方案是:

  • 先算出正确的长度

    • 按照迪特尔的建议使用
      strnlen
    • 或者
      std::find(MyString,MyString+ARRAYSIZE(MyString),'\0')
      哪个IME不会更慢
    请注意,如果您的字符串适合缓存,那么这可能会支配额外的循环成本

  • 保留最大字符串大小(您确实说过空格不太重要),并编写一个循环来追加字符,直到耗尽宽度或达到nul(如
    copy\u,直到

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


  • 第二个选项只使用一个循环,而第三个概念上使用两个循环(它在字符串中,然后在副本中)。然而,每个字符的
    后推
    似乎比简单的字符分配更昂贵,因此如果#3在现实中更快,我也不会感到惊讶。个人资料,看看

    如果大小不是问题,一种可能的方法是创建一个空的
    std::string
    ,然后使用
    reserve()
    预先分配可能需要的空间,然后添加每个字符,直到遇到
    '\0'

    std::string stdmystring;
    stdmystring.reserve(MyString_MAX_SIZE) ;
    for(size_t i=0;i<MyString_MAX_SIZE && MyString[i]!='\0';++i);
    stdmystring+=MyString[i];
    
    std::string stdmysting;
    stdmystring.reserve(MyString\u MAX\u SIZE);
    
    对于(size_t i=0;i我认为最简单的方法是将内部
    MyString
    数组过度分配一个字节,始终空终止最后一个字节,并使用
    std::string
    的C字符串构造函数。(请记住,您的进程很可能是文件上的I/O绑定,因此C-string构造函数使用的任何算法都可以)。

    您可以使用POSIX strnlen来确定大小。(您应该这样做,否则string::size()总是数组大小)没错,这绝对是一个优化。如果没有第二个循环来确定大小(这就是我所想的…),我会使用这个方法。稍后我将不得不研究一些
    std::string
    实现,但我认为
    reserve
    可能是一种悲观的看法:它可能会阻止小字符串优化,这可能对OP的情况很重要,这取决于平均长度和字符串长度。是的,这是正确的,但取决于情况。短字符串字符串必须适合长字符串的大小、容量和指针所用的空间,以及相应的大小和一些标志位/位,以区分短字符串和长字符串。通常短字符串的容量略小于3个机器字。如果平均字符串大小可以适应该保留()这确实会对性能造成不利影响,但如果有大量足够长的字符串没有首先保留,则可能会因为多次分配和复制而变得更糟。至少在Visual Studio中,从已知大小构建的字符串使用memcpy,并且比任何其他方法都快,因此我将使用Dieter的方法。