Я хочу перетворити 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();
Зауважте, що він повертає a 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 за параметром). Але малоймовірно, що він очікує аргументу, виділеного з (деяким переробленим користувачем) новим []!
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
має величезну кількість накладних витрат і складність. Якщо ваша вимога полягає в тому, що у вас є змінний масив char, то насправді вектор символів - це майже ідеальна обгортка C ++. Якщо ваша вимога насправді просто вимагає вказівника const-char, тоді просто використовуйте c_str()
і все закінчено.
Якщо ви просто хочете рядок у стилі С, що містить однаковий вміст:
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()
Це було б краще, як коментар до відповіді bobobobo, але у мене немає відповіді на це. Це здійснює те саме, але з кращими методами.
Хоча інші відповіді корисні, якщо ви коли - небудь потрібно перетворити std::string
в char*
явному вигляді без сопзЬ, const_cast
є вашим другом.
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
Зауважте, що це не дасть вам копії даних; це дасть вам вказівник на рядок. Таким чином, якщо ви модифікуєте елемент chr
, ви модифікуєте str
.
Якщо припустити, що вам просто потрібна рядок у стилі С, щоб перейти як вхід:
std::string str = "string";
const char* chr = str.c_str();
Щоб бути строго педантичним, ви не можете "перетворити std :: string у тип даних char * або char []."
Як показали інші відповіді, ви можете скопіювати вміст рядка std :: в масив char, або зробити const char * до вмісту рядка std ::, щоб ви могли отримати доступ до нього в "C стилі" .
Якщо ви намагаєтесь змінити вміст std :: string, тип std :: string має всі методи для того, щоб зробити все, що вам може знадобитися для цього.
Якщо ви намагаєтеся передати його якій-небудь функції, яка займає знак *, є std :: string :: c_str ().
Для повноти, не забувайте 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);
Ось ще одна надійна версія від 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)
Перетворення в стилі OOP
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")
Крім того, ви можете використовувати вектори, щоб отримати графічний знак *, як показано нижче;
//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
Для отримання a const char *
з std::string
використання використовуйте функцію- c_str()
член:
std::string str = "string";
const char* chr = str.c_str();
Щоб отримати non-const char *
від an, std::string
ви можете використовувати функцію data()
member, яка повертає покажчик non-const з 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()
не буде викликано.
Це також спрацює
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
безумства повністю.