Я хочу перетворити 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безумства повністю.