преобразовать символ * в std :: string


262

Мне нужно использовать std::stringдля хранения данных, полученных fgets(). Для этого мне нужно преобразовать char*возвращаемое значение из fgets()в std::stringдля хранения в массиве. Как это может быть сделано?

Ответы:


376

std::string есть конструктор для этого:

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

Обратите внимание, что эта конструкция копирует список символов в sи sне должно быть nullptr, иначе поведение не определено.


6
что будет если это так?
Карсон Майерс

14
Стандарт говорит, что параметр конструктора «не должен быть нулевым указателем» - он не указывает, что выбрасываются какие-либо исключения.

24
Это мелкая или глубокая копия?

4
@pushkin Нет, strэто просто имя переменной. Это может быть что угодно: S, abc, l, I, strHelloWorld. Очевидно, что некоторые варианты лучше, чем другие. Но для этого примера strэто вполне приемлемо.
Разочарованный

10
@ Madhatter это глубокая копия. Распределение указателей останется, и строка сама сделает новое выделение.
moodboom

127

Если вы уже знаете размер символа *, используйте это вместо

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, когда она заполнена?
IcedDante

2
int size = strlen (data);
Влад

@vlad: идея в том, что вы знаете размер из какого-то другого источника и / или данные не являются C-строкой (имеют встроенные нули или не заканчиваются нулем). Если у вас есть C-строка, вы можете просто сделать myString = data; он будет работать strlen или эквивалент для вас.
Евгений

1
@huseyintugrulbuyukisik Вам по-прежнему необходимо правильно распоряжаться исходной памятью - std :: string будет копировать байты, но не станет владельцем.
Евгений

2
@ZackLee он выделит новую память для байтов и скопирует их все туда, насколько это возможно. Если вам нужен потенциал для мелкого копирования, вам нужно скопировать одну std :: string в другую. Тогда некоторые реализации могли бы сделать поверхностную копию, я думаю.
Евгений

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*
Стив Джессоп

1
правильно, вы не можете (не должны) изменять данные в std :: string с помощью c_str (). Если вы намереваетесь изменить данные, то строка c из c_str () должна быть 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 Standard Library.

Во многом лишнее в общем случае:

string mystring = "your string here"s;

Но это позволяет вам использовать auto, также с широкими строками:

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

И вот где это действительно сияет:

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

2

Я только что боролся с MSVC2005, чтобы использовать std::string(char*)конструктор, как самый лучший ответ. Поскольку я вижу этот вариант в списке № 4 на http://en.cppreference.com/w/cpp/string/basic_string/basic_string , которому всегда доверяют , я полагаю, что даже старый компилятор предлагает это.

Мне потребовалось так много времени, чтобы понять, что этот абсолютный конструктор отказывается соответствовать (unsigned char*)аргументу! Я получил эти непонятные сообщения об ошибках о несоответствии с std::stringтипом аргумента, что определенно не было тем, к чему я стремился. Просто аргументированно std::string((char*)ucharPtr)решил мою проблему ... ах!


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

9
Это приведет к неопределенному поведению.

1
Имея только эти две строки, dataостается неинициализированным (пустым).
хелтонбайкер

1
Без указания истинной «длины» указателя этот код может привести к потере данных, ваш std :: string будет «короче», чем исходный символ *
Andiana

0

Не уверен, почему никто кроме Эрика не упомянул об этом, но согласно этой странице оператор присваивания работает просто отлично. Нет необходимости использовать конструктор, .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 говорит, что не доверяйте SE

Комментарий 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. Он говорит значение и ничего о буферах или владении указателем.
Эрик ван Вельзен,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.