我正在从一个结构体中读取字符串,这些字符串在文件中有固定的长度,并使用'\0'
进行填充。如果存储的字符串需要整个长度,则它们不是以零结尾的。
我目前正在使用以下方式构建std::string
:
// char MyString[1000];
std::string stdmystring(MyString, ARRAYSIZE(MyString));
然而,这也复制了填充。现在我可以修剪字符串,但有没有一种优雅且快速的方法来防止首次复制呢?
速度比空间更重要,因为这在循环中运行。
我正在从一个结构体中读取字符串,这些字符串在文件中有固定的长度,并使用'\0'
进行填充。如果存储的字符串需要整个长度,则它们不是以零结尾的。
我目前正在使用以下方式构建std::string
:
// char MyString[1000];
std::string stdmystring(MyString, ARRAYSIZE(MyString));
简单的解决方案有:
首先计算正确的长度
strnlen
std::find(MyString,MyString+ARRAYSIZE(MyString),'\0')
,这在我看来不会更慢请注意,如果您的字符串适合缓存,那么它很可能会支配额外的循环成本。
预留最大字符串大小(您说过空间不重要),并编写一个循环,将字符附加到超出宽度或达到 nul 时(如 copy_until
)
实际上创建一个初始化为 nuls 的最大大小字符串,strncpy
到其中,并选择擦除 unused
nuls(如果您想要正确的大小)
第二个选项仅使用单个循环,而第三个则从概念上使用两个循环(在字符串构造函数中以及在复制中)。但是,每个字符的 push_back
似乎比简单的字符赋值更昂贵,因此我不会感到惊讶,如果 #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];
< p > reserve()
函数可以保证你所需的内存分配,因为你知道字符串的最大大小并且它永远不会超过该大小。
对 += 运算符函数的调用可能会被内联,但仍然需要检查字符串是否具有所需的容量,这在您的情况下是浪费的。事实上,这可能与先使用 strlen 找到字符串的确切长度相同或更糟,因此您必须进行测试。
std::string
的实现,但我认为在这里使用reserve
可能是一种悲观的做法:它可能会阻止小字符串优化,在OP的情况下这可能很重要,具体取决于平均字符串长度。 - dyp我认为最直接的方法是通过多分配一个字节来扩大内部MyString
数组,始终将最后一个字节置为空,然后使用std::string
的C字符串构造函数。(请记住,由于文件I/O限制,大多数情况下C字符串构造函数使用的算法应该是可以接受的)。