如何正确/最佳/最简单地将C风格字符串转换为std::string?
转换应该接受一个max_length参数,并且在第一个\0字符出现之前,如果在max_length个字符之内遇到\0,则截断字符串。
如何正确/最佳/最简单地将C风格字符串转换为std::string?
转换应该接受一个max_length参数,并且在第一个\0字符出现之前,如果在max_length个字符之内遇到\0,则截断字符串。
string::string
提供了两个可能符合您需求的构造函数:string ( const char * s, size_t n );
string ( const string& str, size_t pos, size_t n = npos );
例子:
#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;
}
输出:
15:[Hello world]
11:[Hello world]
p
视为简单数组,因此将创建一个长度为15的字符串,在使用cout << ...
打印时会作为一个11个字符的以null结尾的字符串。这可能不是您要寻找的内容。char*
为字符串,然后保留其长度和指定的n
之间的最大值。我认为这是最简单的解决方案,就编写所需内容而言。std::string str(c_str, strnlen(c_str, max_length));
根据Christian Rau的要求:
strnlen
在POSIX.1-2008中被指定,并且在GNU的glibc和Microsoft运行时库中可用。它尚未在其他一些系统中找到;您可以退回到Gnulib的替代方法。
strnlen
是标准的C++函数吗?如果不是,您应该提到这种非可移植性。 - Christian Raustd::string the_string(c_string);
if(the_string.size() > max_length)
the_string.resize(max_length);
这实际上比看起来要棘手得多,因为你不能调用strlen
除非字符串实际上是以nul结尾的。实际上,如果没有一些额外的限制条件,这个问题几乎需要发明一个新函数,一个strlen
的版本永远不会超过某个长度。但是:
如果包含C风格字符串的缓冲区至少保证是max_length
字符(可能在末尾有'\0'
),那么可以使用std::string
的地址-长度构造函数,并在之后修剪:
std::string result( c_string, max_length );
result.erase( std::find( result.begin(), result.end(), '\0' ), result.end() );
如果你知道c_string
是以空字符结尾的字符串(但可能比max_length
长),你可以使用strlen
:
std::string result( c_string, std::min( strlen( c_string ), max_length ) );
有一个接受两个指针参数的构造函数,所以代码很简单
std::string cppstr(cstr, cstr + min(max_length, strlen(cstr)));
如果长度小于max_length
,那么这也将像std::string cppstr(cstr)
一样高效。
std::string ( const string& str, size_t pos, size_t n = npos )
,将pos作为0传递。你的const char* C风格字符串将会被隐式转换为第一个参数的const string类型。const char *c_style = "012abd";
std::string cpp_style = std::string(c_style, 0, 10);
更新:从 cpp_style
初始化中删除了 "new"
new
的使用 - kbyrd