将char *转换为std :: string


262

我需要使用std::string来存储由检索的数据fgets()。为此,我需要将char*返回值从fgets()转换为std::string并存储在数组中。如何才能做到这一点?

Answers:


376

std::string 为此有一个构造函数:

const char *s = "Hello, World!";
std::string str(s);

请注意,此构造会深度复制字符列表,s并且s不应将其复制为nullptr,否则行为未定义。


6
如果会发生什么呢?
— 卡森·迈尔斯

14
Standard表示构造函数参数“不得为null指针”-它未指定引发任何异常。

24
是浅拷贝还是深拷贝?

4
@pushkin No str只是一个变量名。它可以是任何东西:S,abc,l,I,strHelloWorld。显然,有些选择比其他选择更好。但是对于这个例子str是完全可以接受的。
— 幻灭了

10
@Madhatter这是一个深复制。指针分配将保留,字符串将使自己成为新分配。
— moodboom

127

如果您已经知道char *的大小,请改用它

char* data = ...;
int size = ...;
std::string myString(data, size);

这不使用strlen。

编辑:如果字符串变量已经存在,请使用assign():

std::string myString;
char* data = ...;
int size = ...;
myString.assign(data, size);

1
有点疑问,尤金。如果直到例程的稍后才填充数据,那么如何初始化myString?您只是在填充myString变量时声明了吗?
— IcedD​​ante

2
int大小= strlen(数据);
— 弗拉德

@vlad:这个想法是,您知道来自其他来源和/或数据的大小不是C字符串(具有嵌入的null或不以null结尾)。如果您有C字符串,则只需执行myString = data;它会为您运行strlen或等效功能。
— 尤金2015年

1
@huseyintugrulbuyukisik您仍然需要正确处理原始内存-std :: string将复制字节,并且不拥有所有权。
— 尤金(Eugene)

2
@ZackLee它将为这些字节分配新的内存,并将它们全部复制到那里,直到达到为止。如果希望进行浅拷贝,则需要将一个std :: string复制到另一个。然后,我认为某些实现可以做一个浅表复制。
— 尤金(Eugene)

30

大多数答案都谈论建造 std::string。

如果已经构建,则只需使用赋值运算符。

std::string oString;
char* pStr;

... // Here allocate and get character string (e.g. using fgets as you mentioned)

oString = pStr; // This is it! It copies contents from pStr to oString

28

我需要使用std :: string来存储fgets()检索到的数据。

为什么fgets()在编程C ++时使用?为什么不std::getline()呢?


18

通过构造函数传递它:

const char* dat = "my string!";
std::string my_string( dat );

您可以使用函数string.c_str()进行其他选择:

std::string my_string("testing!");
const char* dat = my_string.c_str();

3
c_str()返回const char*
— Steve Jessop

1
正确,您不能(不应)通过c_str()修改std :: string中的数据。如果您打算更改数据,然后从c_str(在C字符串)应memcpy'd
— 卡森·迈尔斯

11
const char* charPointer = "Hello, World!\n";
std::string strFromChar;
strFromChar.append(charPointer);
std::cout<<strFromChar<<std::endl;

6
char* data;
stringstream myStreamString;
myStreamString << data;
string myString = myStreamString.str();
cout << myString << endl;

5

我想提到一种使用用户定义文字的新方法s。这不是什么新鲜事物,但是会更加普遍,因为它是在C ++ 14标准库中添加的。

在一般情况下是多余的:

string mystring = "your string here"s;

但是它允许您对宽字符串也使用自动:

auto mystring = U"your UTF-32 string here"s;

这才是真正闪耀的地方:

string suffix;
cin >> suffix;
string mystring = "mystring"s + suffix;

2

我一直在努力与MSVC2005一起使用std::string(char*)构造函数,就像最受好评的答案一样。正如我在始终受信任的http://en.cppreference.com/w/cpp/string/basic_string/basic_string上将此变体列出为#4一样,我认为即使是旧的编译器也可以提供此变体。

我花了很长时间才意识到这个构造函数绝对拒绝与之匹配(unsigned char*)!我收到了关于无法与std::string参数类型匹配的这些无法理解的错误消息,这绝对不是我想要的。只是用争论std::string((char*)ucharPtr)解决了我的问题......!


0
char* data;
std::string myString(data);

9
这将导致不确定的行为。

1
仅使用这两行,data仍未初始化(空)。
— heltonbiker 2011年

1
如果没有提供指针的真正“长度”,此代码可能会导致数据丢失,您的std :: string会比原始char *“更短” *
— Andiana

0

不知道为什么除了Erik之外没有人提到这一点,但是根据此页面,赋值运算符可以正常工作。无需使用构造函数,.assign()或.append()。

std::string mystring;
mystring = "This is a test!";   // Assign C string to std:string directly
std::cout << mystring << '\n';

1
它似乎确实可以正常工作,但是当我这样做时,我开始在程序结束时遇到Valgrind报告可访问块的问题,这源于=(和+=)内部的“新” 。似乎不是像这样的文字发生,而是像char*事情一样。本文讨论了此类报告是否实际上是泄漏的问题。但是,如果我将分配更改destString = std::string(srcCharPtr);为valgrind,泄漏报告将消失。YMMV。
— HostileFork说不要信任2014年

HostileFork的评论可能会让您相信,从char *构造字符串(例如从fgets构造)将使std :: string管理此内存的寿命。然而,这种情况并非如此。参见标准21.4.2.7和.9 Constructs an object of class basic_string and determines its initial string value from the array。它说的是价值,与缓冲区或指针所有权无关。
— Erik van Velzen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.