std :: string을 char *로


335

std :: stringchar * 또는 char [] 데이터 형식 으로 변환하고 싶습니다 .

std::string str = "string";
char* chr = str;

결과 : "오류가 ... '문자'에 대한 '표준 : : 문자열을'변환 할 수 없습니다" .

이를 위해 어떤 방법을 사용할 수 있습니까?

c++  string  char 

답변:


672

자동으로 변환되지 않습니다 (신께 감사합니다). 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);

4
@ Kerrek SB : 예를 들어 실제 코드에서 스마트 포인터를 사용 하거나이 c_str광기를 완전히 피할 가능성이 높습니다 .
orlp

14
답은 부피가 크고 우아하며 로컬이 아니며 원시 배열을 사용하므로 예외 안전에주의가 필요합니다. vector동적 배열의 래퍼로 정확하게 발명되었으므로 그것을 사용하지 않으면 기껏해야 기회가없는 것처럼 보이고 최악의 경우 C ++의 정신을 위반합니다.
Kerrek SB

21
우선, 네, 대답은 거대합니다. 먼저 OP의 오류 ( std::string자동으로 변환 할 생각 )를 설명한 다음 짧은 코드 샘플을 사용하여 그가 사용해야하는 것을 설명합니다. 앞으로도이 함수 사용의 부작용에 대해 설명합니다.이 중 하나는에 의해 반환 된 문자열을 편집 할 수 없다는 것 c_str()입니다. 내 짧은 예제를 실제 문제 해결 코드로 잘못 본다.
orlp

8
나는 그 답을 내려 놓았다. 이 답변은 실제로 유용하지 않으며 수락 된 사실이 가장 불행합니다. 이 답변은 좋은 C ++ 프로그래밍 관행과 예외 안전을 완전히 무시하고 훨씬 우수한 솔루션이 있으며 그중 일부는이 질문에 대한 다른 답변 (예 : ildjarn에서 사용하는 답변)으로 제공됩니다 std::vector<char>.
James McNellis

114
@ james-mcnellis, 나는 내가 원하는 것을 정확하게 대답했기 때문에이 대답을 올바른 것으로 선택 했습니다 ... 더 이상은 아닙니다. 나는 당신이 내가해야한다고 생각하는 것을 묻지 않았고, 내가하고 있다고 생각하는 것에 대해 다른 해결책을 요구하지 않았으며, 좋은 관행을 요구하지 않았습니다. 내가 무슨 일을하고 있는지, 내 코드가 어디에서 구현되는지, 어떤 조건 하에서 일인지 모릅니다. 어떤 사람들은 질문을 읽고 이해하고 실제로 요청되는 것에 대답하는 법을 배워야합니다. 여기서 과시 할 필요가 없습니다.

150

자세한 내용은 여기여기에서 사용할 수 있습니다

string str = "some string" ;
char *cstr = &str[0];

15
FWIW, 내 책에서 이것은 실제로 묻는 질문에 대한 유일한 정답입니다. std :: string은 본질적으로 변경 가능합니다. 문자열의 내용을 수정하는 것처럼 들리는 사람들은 어떻게 든 악마의 작업 에이 사실이 누락 된 것 같습니다.
Jay Freeman -saurik- 1

2
네, 정답입니다. 사용 빈도를 감안할 때 msoft의 lockbuffer와 같이이를 수행하는 표준 방법이 없다는 것은 바보입니다.
Erik Aronesty

1
0을 0u로 변경했습니다. 일부 컴파일러 / 라이브러리는 & str [0] 구문에 대해 경고가
온전히

str이 삭제되면 char cstr이 null이됩니다. 그래서 여기서는 문자열의 포인터 만 char 포인터에 할당되어 있다고 생각합니다. 따라서 문자열을 char로 변환하는 것은 문자 그대로 완료되지 않았습니다. 문자열은 char * 만 가리 키지 만 값은 변환되지 않습니다. 나 맞아???
Samitha Chathuranga

5
이것은 C ++ 11 전용입니다. 이전 버전에는 연속 저장 장치가 없거나 종료 null이 없습니다.
Flamefire

39

c ++ 문자열 내용의 변경 가능한 원시 복사본이 필요하다면 다음과 같이하십시오.

std::string str = "string";
char* chr = strdup(str.c_str());

그리고 나중에 :

free(chr); 

그렇다면 왜 std :: vector 또는 다른 사람처럼 new []를 사용하지 않습니까? 때문에 나는 변경 가능한 C 스타일의 원시 문자를 필요로 할 때 * 문자열, 그럼 내가 문자열을 변경하고 C 코드의 malloc () (에서는 StrDup 사용의 malloc에) 무료 () 및 할당과 물건의 할당을 해제 C 코드를 호출하기 원하기 때문에 . 따라서 원시 문자열을 C로 작성된 일부 함수 X 에 전달하면 힙에 할당해야한다는 인수에 제약 이 있을 수 있습니다 (예 : 함수가 매개 변수에서 realloc을 호출하려는 경우). 그러나 (일부 사용자가 정의한) new []로 할당 된 인수를 기대할 가능성은 거의 없습니다!


어디 strdup에서 왔는지 설명해야합니다 .
LF

22

(이 답변은 C ++ 98에만 적용됩니다.)

raw를 사용하지 마십시오 char*.

std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*

1
나는 실제로 오늘 일찍이 같은 것을 필요로했다. vector<char>(str.c_str(), str.c_str() + str.size() + 1)char 포인터를 임시로 할당하지 않고 말할 수 있습니까?
Kerrek SB

1
@Kerrek : 예,의 반환 값 은 변경되거나 파괴 std::basic_string<>::c_str()될 때까지 유효합니다 string. 이것은 또한 string수정되지 않는 한 후속 호출에서 동일한 값을 반환한다는 것을 의미합니다 .
ildjarn

2
@friendzis : vector이런 식으로 사용하는 속도 나 공간 오버 헤드가 없습니다 . 그리고 만약 RAII 메커니즘없이 (예를 들어, raw 포인터를 사용하여) 예외 안전 코드 를 작성한다면 , 코드의 복잡성은이 단순한 단일 라이너보다 훨씬 더 높습니다.
ildjarn

7
vector엄청난 양의 오버 헤드와 복잡성이 있는 신화입니다 . 요구 사항에 가변 char 배열 이 있어야하는 경우 실제로 문자 벡터는 이상적인 C ++ 래퍼입니다. 요구 사항이 실제로 const-char 포인터를 요구하면 사용 c_str()하고 완료하십시오.
Kerrek SB

3
@ ildjarn : 사실, 기본적으로 입니다.
궤도에서 가벼움 레이스

14
  • 동일한 내용을 나타내는 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

1
&str.front(), &str.back()더 일반 str.begin()적이고 str.end()? ( C ++ 03에는없는) 이유는 무엇 입니까?
Armen Tsirunyan

1
무엇에 대한 str.begin(), 또는 std::begin(str), 반복자 같은? 나는 string같은 연속적인 기억에 의무가 있다고 생각하지 vector않습니까?
xtofl

1
@ xtofl : 나는 이미 그것들을 편집했다. 그리고 C ++ 11부터는 의무가있다. 이것은 C ++ 03에서 암시 적이었습니다.
궤도에서 가벼움

@xtofl : C ++ 03에는 없습니다. C ++ 11에서 우리는 front () 및 back () 함수와 함께 보증을 받았습니다. 어쨌든 원래 답변에서 잘못 사용되었습니다
Armen Tsirunyan

1
@Tomalak : 그들은 당신이 필요한 점에서 잘못했다 &back() + 1,하지&back()
아르 멘 Tsirunyan

12

이것은 bobobobo의 답변에 대한 의견으로 더 좋지만 그에 대한 담당자는 없습니다. 그것은 똑같은 일을하지만 더 나은 방법으로 달성합니다.

다른 답변이 유용하지만 혹시 변환해야하는 경우 std::stringchar*const를하지 않고 명시 적으로, const_cast당신의 친구입니다.

std::string str = "string";
char* chr = const_cast<char*>(str.c_str());

이렇게하면 데이터 사본이 제공 되지 않습니다 . 문자열에 대한 포인터를 제공합니다. 따라서의 요소를 수정하면을 수정 chr합니다 str.


6

입력으로 전달하려면 C 스타일 문자열이 필요하다고 가정합니다.

std::string str = "string";
const char* chr = str.c_str();

4

엄격하게 의미를 가지기 위해 "std :: string을 char * 또는 char [] 데이터 형식으로 변환 할 수 없습니다."

다른 답변에서 알 수 있듯이 std :: string의 내용을 char 배열로 복사하거나 std :: string의 내용에 const char *를 만들어 "C 스타일"로 액세스 할 수 있습니다. .

std :: string의 내용을 변경하려는 경우 std :: string 유형에는 필요한 모든 작업을 수행 할 수있는 모든 메소드가 있습니다.

char *를 사용하는 함수에 전달하려고하면 std :: string :: c_str ()이 있습니다.


4

여기에 하나 더 강력한 버전이 있습니다 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

문자열이 비어 있는지 확인하기 위해 +1 또한 문자열이 0으로 끝나지 if (str[str.length()-1] != 0) str.push_back(0)
않았

4

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")

나는 캐스트로 char 캐스트가 c_str의 출력에서 ​​const를 제거하는 방법을 좋아합니다 .c_str이 const char *를 리턴하는 이유는 읽기 전용 버전의 것을 제공하여 잠재적 인 메모리 액세스 문제를 제거하는 것이라고 생각합니다. OP는 char *를 원하지만 대신 c_str의 const char * 출력을 사용하는 것이 더 좋을 것이라고 생각합니다 .char *를 사용하는 함수는 일반적으로 const char *도 사용합니다 (함수는 가정하지 않음) 입력을 변경하는 것과 같은 작업을 수행하십시오.
Felipe Valdes

3

완전성을 위해 잊지 마십시오 std::string::copy().

std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];

str.copy(chrs, MAX);

std::string::copy()NUL이 종료되지 않습니다. C 문자열 함수에 사용하기 위해 NUL 종료자를 확인해야하는 경우 :

std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];

memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);

3

반복자를 사용하여 만들 수 있습니다.

std::string str = "string";
std::string::iterator p=str.begin();
char* chr = &(*p);

행운을 빕니다.


3

unique_ptr을 사용하여 안전한 orlp char * 응답 버전 :

std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());

3

을 구 const char *에서 std::string사용 c_str()멤버 함수 :

std::string str = "string";
const char* chr = str.c_str();

비 const를 얻으려면 char *에서 std::string당신은 사용할 수있는 data()C ++ (17) 이후 const가 아닌 포인터를 반환하는 멤버 함수를 :

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사본의 데이터만이 방식으로 변경 될 수 있습니다. 이전 버전의 언어에서는 호출이 끝날 때까지 null로 종료되는 것이 보장되지 않았 c_str()으므로 여기 에서 사용하는 것이 특히 중요 합니다.std::stringc_str()



2

또는 벡터를 사용하여 아래와 같이 쓰기 가능한 char *를 얻을 수 있습니다.

//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은 이미 컨테이너이므로 문자열에 push_back (0)을 수행하고 & str [0]을 수행 할 수 있습니다.
GaspardP

1

이것은 또한 작동합니다

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;  
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.