What is the correct/best/simplest way to convert a c-style string to a std::string.
The conversion should accept a max_length, and terminate the string at the first \0 char, if this occur before max_length charter.
What is the correct/best/simplest way to convert a c-style string to a std::string.
The conversion should accept a max_length, and terminate the string at the first \0 char, if this occur before max_length charter.
This page on string::string
gives two potential constructors that would do what you want:
string ( const char * s, size_t n );
string ( const string& str, size_t pos, size_t n = npos );
Example:
#include<cstdlib>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
int main(){
char* p= (char*)calloc(30, sizeof(char));
strcpy(p, "Hello world");
string s(p, 15);
cout << s.size() << ":[" << s << "]" << endl;
string t(p, 0, 15);
cout << t.size() << ":[" << t << "]" << endl;
free(p);
return 0;
}
Output:
15:[Hello world]
11:[Hello world]
The first form considers p
to be a simple array, and so will create (in our case) a string of length 15, which however prints as a 11-character null-terminated string with cout << ...
. Probably not what you're looking for.
The second form will implicitly convert the char*
to a string, and then keep the maximum between its length and the n
you specify. I think this is the simplest solution, in terms of what you have to write.
std::string str(c_str, strnlen(c_str, max_length));
At Christian Rau's request:
strnlen
is specified in POSIX.1-2008 and available in GNU's glibc and the Microsoft run-time library. It is not yet found in some other systems; you may fall back to Gnulib's substitute.
std::string the_string(c_string);
if(the_string.size() > max_length)
the_string.resize(max_length);
This is actually trickier than it looks, because you can't call strlen
unless the string is actually nul terminated. In fact, without some
additional constraints, the problem practically requires inventing a new
function, a version of strlen
which never goes beyond the a certain
length. However:
If the buffer containing the c-style string is guaranteed to be at least
max_length
char's (although perhaps with a '\0'
before the end),
then you can use the address-length constructor of std::string
, and
trim afterwards:
std::string result( c_string, max_length );
result.erase( std::find( result.begin(), result.end(), '\0' ), result.end() );
and if you know that c_string
is a nul terminated string (but perhaps
longer than max_length
, you can use strlen
:
std::string result( c_string, std::min( strlen( c_string ), max_length ) );
There is a constructor accepting two pointer parameters, so the code is simply
std::string cppstr(cstr, cstr + min(max_length, strlen(cstr)));
this is also going to be as efficient as std::string cppstr(cstr)
if the length is smaller than max_length
.
What you want is this constructor:
std::string ( const string& str, size_t pos, size_t n = npos )
, passing pos as 0. Your const char* c-style string will get implicitly cast to const string for the first parameter.
const char *c_style = "012abd";
std::string cpp_style = std::string(c_style, 0, 10);
UPDATE: removed the "new" from the cpp_style
initialization