Я хочу преобразовать std :: string в тип данных char * или char [] .
std::string str = "string";
char* chr = str;
Результат: «ошибка: невозможно преобразовать« std :: string »в« char »...» .
Какие методы доступны для этого?
Я хочу преобразовать std :: string в тип данных char * или char [] .
std::string str = "string";
char* chr = str;
Результат: «ошибка: невозможно преобразовать« std :: string »в« char »...» .
Какие методы доступны для этого?
Ответы:
Он не будет автоматически конвертироваться (слава богу). Вы должны будете использовать метод, c_str()
чтобы получить версию строки C.
std::string str = "string";
const char *cstr = str.c_str();
Обратите внимание, что он возвращает const char *
; вам не разрешено изменять строку в стиле C, возвращаемую c_str()
. Если вы хотите обработать его, сначала скопируйте его:
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
Или в современном C ++:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
vector
был придуман именно как оболочка для динамических массивов, поэтому его использование в лучшем случае кажется упущенной возможностью, а в худшем - нарушением духа C ++.
std::string
это автоматически преобразует), а затем объясняю, что он должен использовать, с коротким примером кода. Забегая вперед, я также объясню некоторые побочные эффекты использования этой функции, одна из которых заключается в том, что вы не можете редактировать возвращаемую строку c_str()
. Вы ошибочно видите мои короткие примеры как реальный код для решения проблем, а это не так.
std::vector<char>
).
Подробнее здесь и здесь, но вы можете использовать
string str = "some string" ;
char *cstr = &str[0];
Если бы мне нужна изменяемая сырая копия строкового содержимого c ++, я бы сделал это:
std::string str = "string";
char* chr = strdup(str.c_str());
и позже:
free(chr);
Так почему бы мне не поиграться с std :: vector или new [] как кто-либо еще? Потому что, когда мне нужна изменяемая необработанная строка char * в стиле C, то, потому что я хочу вызвать код C, который изменяет строку, а код C освобождает вещи с помощью free () и выделяет с помощью malloc () (strdup использует malloc) . Поэтому, если я передам свою необработанную строку какой-либо функции X, написанной на C, у нее может быть ограничение на аргумент, который она должна разместить в куче (например, если функция может захотеть вызвать realloc для параметра). Но очень маловероятно, что он ожидал бы аргумент, выделенный (каким-то образом переопределенным пользователем) new []!
strdup
.
(Этот ответ относится только к C ++ 98.)
Пожалуйста, не используйте сырье char*
.
std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*
vector<char>(str.c_str(), str.c_str() + str.size() + 1)
, не назначая указатель на символ временный?
std::basic_string<>::c_str()
действует до тех пор, пока не string
будет изменено или уничтожено. Это также подразумевает, что оно возвращает то же значение при последующих вызовах, если string
оно не изменено.
vector
. И если бы нужно было написать код, исключающий исключения, без механизма RAII (т. Е. С использованием необработанных указателей), сложность кода была бы намного выше, чем у этого простого однострочного.
vector
имеет огромное количество накладных расходов и сложности. Если вы требуете, чтобы у вас был изменяемый массив символов, то фактически вектор символов в значительной степени является идеальной оболочкой C ++. Если ваше требование на самом деле просто требует указателя const-char, просто используйте c_str()
и все готово.
Если вам нужна строка в стиле C, представляющая тот же контент:
char const* ca = str.c_str();
Если вам нужна строка в стиле C с новым содержимым, одним из способов (учитывая, что вы не знаете размер строки во время компиляции) является динамическое распределение:
char* ca = new char[str.size()+1];
std::copy(str.begin(), str.end(), ca);
ca[str.size()] = '\0';
Не забудь об delete[]
этом позже.
Если вам нужен статически размещенный массив ограниченной длины:
size_t const MAX = 80; // maximum number of chars
char ca[MAX] = {};
std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca);
std::string
неявно преобразуется в эти типы по той простой причине, что для этого обычно требуется запах проекта. Убедитесь, что вам это действительно нужно.
Если вам определенно нужен char*
, вероятно , лучший способ:
vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector
&str.front(), &str.back()
(которых нет в C ++ 03) вместо более распространенных str.begin()
и str.end()
?
str.begin()
, или даже std::begin(str)
, итератор типа? Я не верю, string
что обязан быть в смежных воспоминаниях vector
, или это так?
&back() + 1
, а не&back()
Это было бы лучше в качестве комментария к ответу Бобобо, но у меня нет представителя для этого. Это выполняет то же самое, но с лучшими практиками.
Хотя другие ответы полезны, если вам когда-либо понадобится явно преобразовать std::string
в char*
const, const_cast
это ваш друг.
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
Обратите внимание, что это не даст вам копию данных; это даст вам указатель на строку. Таким образом, если вы измените элемент chr
, вы измените str
.
Чтобы быть строго педантичным, вы не можете «преобразовать std :: string в тип данных char * или char []».
Как показали другие ответы, вы можете скопировать содержимое std :: string в массив char или сделать const char * для содержимого std :: string, чтобы получить к нему доступ в стиле «C» ,
Если вы пытаетесь изменить содержимое std :: string, тип std :: string имеет все методы, чтобы сделать все, что вам может понадобиться.
Если вы пытаетесь передать его какой-то функции, которая принимает char *, есть std :: string :: c_str ().
Вот еще одна надежная версия от Protocol Buffer
char* string_as_array(string* str)
{
return str->empty() ? NULL : &*str->begin();
}
// test codes
std::string mystr("you are here");
char* pstr = string_as_array(&mystr);
cout << pstr << endl; // you are here
if (str[str.length()-1] != 0) str.push_back(0)
Преобразование в стиле ООП
converter.hpp
class StringConverter {
public: static char * strToChar(std::string str);
};
converter.cpp
char * StringConverter::strToChar(std::string str)
{
return (char*)str.c_str();
}
использование
StringConverter::strToChar("converted string")
Ради полноты не забывайте std::string::copy()
.
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy()
не NUL прекращать. Если вам нужно обеспечить терминатор NUL для использования в строковых функциях C:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
Чтобы получить const char *
из std::string
использования c_str()
функцию-член:
std::string str = "string";
const char* chr = str.c_str();
Чтобы получить неконстантный char *
объект из, std::string
вы можете использовать data()
функцию-член, которая возвращает неконстантный указатель начиная с C ++ 17:
std::string str = "string";
char* chr = str.data();
Для более старых версий языка вы можете использовать конструкцию диапазона, чтобы скопировать строку в вектор, из которого можно получить неконстантный указатель:
std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();
Но учтите, что это не позволит вам изменить строку, содержащуюся в этом str
, только данные копии могут быть изменены таким образом. Обратите внимание, что это особенно важно в старых версиях языка, чтобы использовать c_str()
здесь, потому что тогда std::string
не было гарантировано, что будет завершено нулем, пока не c_str()
был вызван.
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
Кроме того, вы можете использовать векторы, чтобы получить записываемый символ *, как показано ниже;
//this handles memory manipulations and is more convenient
string str;
vector <char> writable (str.begin (), str.end) ;
writable .push_back ('\0');
char* cstring = &writable[0] //or &*writable.begin ()
//Goodluck
Это тоже будет работать
std::string s;
std::cout<<"Enter the String";
std::getline(std::cin, s);
char *a=new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
std::cout<<a;
c_str
безумия.