Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am reading strings from a structure in a file where each string has a fixed length, with '\0' padding. They are not zero-terminated if the stored string needs the whole length.

I'm currently constructing std::strings out of those like this:

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

However, this copies the padding, too. I could trim the string now, but is there an elegant and quick way to prevent the copying in the first place?

Speed is more important than space, because this runs in a loop.

like image 432
Felix Dombek Avatar asked Sep 09 '15 16:09

Felix Dombek


2 Answers

Simple solutions are:

  1. Just calculate the correct length first

    • either use strnlen as Dieter suggested
    • or std::find(MyString,MyString+ARRAYSIZE(MyString),'\0') which IME isn't any slower

    note that if your string fits in cache, that will likely dominate the extra loop cost

  2. reserve the max string size (you did say space was less important), and write a loop appending characters until you exhaust the width or hit a nul (like copy_until)

  3. actually create a max-size string initialized with nuls, strncpy into it, and optionally erase unused nuls if you want the size to be correct

The second option uses only a single loop, while the third notionally uses two (it in the string ctor, and then in the copy). However, the push_back of each character seems more expensive than the simple character assignment, so I wouldn't be surprised if #3 were faster in reality. Profile and see!

like image 165
Useless Avatar answered Oct 25 '22 00:10

Useless


Well If size is not a problem one potential way to do it is to create an empty std::string then use reserve() to pre-allocate the space potentially needed and then add each char until you come across '\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];

reserve() garanties you one memory allocation since you know the max_size and the string will never get larger than that.

The calls to += operator function will probably be inlined but it still has to check that the string has the needed capacity which is wasteful in your case. Infact this could be the same or worse than simply using strlen to find the exact length of the string first so you have to test it.

like image 41
Abstraction Avatar answered Oct 25 '22 01:10

Abstraction