std :: vector <char>에서 std :: string을 생성하는 방법은 무엇입니까?


115

(분명한) C 스타일 문자열을 먼저 빌드 한 다음이를 사용하여 std :: string을 만드는 것이 부족합니다. 문자 벡터에서 문자열을 초기화하는 더 빠르고 / 대안 / "더 나은"방법이 있습니까?


4
복사하지 않고 할 수 있습니까? 다른 말로 하면 새로운 객체로서 std::vector<char> v2(std::move(v))a와 같은 일 을하는 것 std::string입니다.
tobi_s 2010 년

답변:


197

음, 가장 좋은 방법은 다음 생성자를 사용하는 것입니다.

template<class InputIterator> string (InputIterator begin, InputIterator end);

다음과 같은 결과가 나타납니다.

std::vector<char> v;
std::string str(v.begin(), v.end());

41

나는 당신이 할 수 있다고 생각합니다

std::string s( MyVector.begin(), MyVector.end() );

여기서 MyVector는 std :: vector입니다.


1
설정하지 않는 한 런타임에 잘못된 반복자에 대해 주장하는 VS2013을 제외하고 _ITERATOR_DEBUG_LEVEL=1(이 경우 제대로 작동하는 것 같습니다).
Cameron

35

C ++ 11을 사용하면 할 수 있습니다. std::string(v.data())또는 벡터 '\0'의 끝에 a가 없으면 std::string(v.data(), v.size()).


C ++ 98에서도 std :: string (& v [0]) 할 수 있다고 생각합니다. 물론 이것은 벡터가 null로 끝나는 경우입니다.
Jamie

1
@Jamie은 : 그건 그렇고, C ++ 98, string(&v[0], v.size())도 작동해야하지만 후에 만 assert(not v.empty());, 벡터가 비어 둘 경우 이후 v[0]v.front()정의되지 않은 동작을 호출한다. 즉, 주소 연산자를 사용할 필요가 없다는 구문상의 단순 성과는 별도로 data()빈 벡터에서도 작동하는 C ++ 11 함수 의 진정한 이점입니다 .
Adam H. Peterson

매우 사실입니다. 불행히도 내 프로젝트는 가까운 미래에 Visual Studio 2008에서 멈춰 있습니다. 벡터 길이를 먼저 확인하는 것이 좋습니다.
Jamie

벡터에 '\ 0'이 포함되지 않은 경우 std::string(v.data())더 긴 문자열이 나올 수 있습니다. 따라서 이런 식으로 사용하지 마십시오.
heLomaN

@heLomaN : std::string(v.data(), v.size())정확한 이유에 대해 답변에 명시 적으로 언급 된 의 문제는 무엇입니까 ?
Sz.

12
std::string s(v.begin(), v.end());

v는 반복 가능한 거의 모든 것입니다. (특히 begin () 및 end ()는 InputIterators를 반환해야합니다.)


3

완전성을 위해 다른 방법은 std::string(&v[0])(문자열이 null로 끝나고 std::string(v.data())일반적으로 선호되는 것을 확인해야하지만 .

차이점은 .data ()로는 할 수없는 버퍼를 수정하려는 함수에 벡터를 전달하기 위해 앞의 기술을 사용할 수 있다는 것입니다.


data()버퍼를 수정하는 데 사용할 수없는 이유는 무엇 입니까? data()상수가 아닌 벡터 를 호출 하면 a를 반환하는 것처럼 보입니다 T *(그리고 벡터가 const이면 'v [0]`은 T const &어쨌든 a를 반환 합니다).
Adam H. Peterson

@ AdamH.Peterson 표준에 대한 감독 인 것 같습니다. Std :: vector의 데이터에는 const 및 non-const 함수가 모두있는 반면 현재 표준에서 std :: string에는 const 함수 만 있습니다. en.cppreference.com/w/cpp/string/basic_string/data C ++ 17은 상수가 아닌 버전을 추가하므로 무기한이 아닐 수도 있습니다. 그러나 현재 표준에서는 "데이터를 통해 액세스되는 문자 배열을 수정하면 동작이 정의되지 않았습니다."라고 명시되어 있습니다.
Riot

v문자열 이면 참 이지만 대상 유형은 문자열이고 v벡터입니다. (하지만 C ++ 17 문자열을 벡터와 패리티를 줄 것이다 있는지 좋다.)
아담 H. 피터슨

@ AdamH.Peterson 물론 맞습니다. 질문에 대한 답변은 얼마 전에 이루어졌고, 전체 질문은 확인하지 않고 독점적으로 문자열에 관한 것이라고 생각했습니다.
Riot

2

나는 Stefan의 대답 (Sep 11 '13)을 좋아하지만 조금 더 강하게 만들고 싶습니다.

벡터가 null 종결 자로 끝나는 경우 (v.begin (), v.end ())를 사용해서는 안됩니다. v.data ()를 사용해야합니다 (또는 C ++ 17 이전의 경우 & v [0]). .

v에 null 종결자가 없으면 (v.begin (), v.end ())를 사용해야합니다.

begin () 및 end ()를 사용하고 벡터에 종결 0이 있으면 문자열 "abc \ 0"으로 끝납니다. 예를 들어 길이가 4이지만 실제로는 "abc"여야합니다.


1
vector<char> vec;
//fill the vector;
std::string s(vec.begin(), vec.end());

설명과 코드를 추가해 주시겠습니까?
Paul Floyd

1
C ++ 11 문자열 라이브러리 템플릿은 다음과 같습니다. default (1) string (); (2) 문자열 복사 (const string & str); 부분 문자열 (3) 문자열 (const string & str, size_t pos, size_t len ​​= npos); c- 문자열에서 (4) 문자열 (const char * s); 버퍼에서 (5) 문자열 (const char * s, size_t n); 채우기 (6) 문자열 (size_t n, char c); 범위 (7) 템플릿 <class InputIterator> 문자열 (InputIterator 먼저, InputIterator 마지막); 이니셜 라이저 목록 (8) 문자열 (initializer_list <char> il); 이동 (9) 문자열 (문자열 && str) noexcept; 우리는 7 번째 템플릿을 따르고 있습니다.
TechCat

안녕하세요 @TechCat! 다음 질문에 답하기 전에 좋은 답변 작성에 대해 읽어보십시오 . SO에서 숙박을 즐기십시오!
Diggy.

설명으로 답변을 수정 해 주시겠습니까?
Paul Floyd
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.