문제
어제 약 4 시간을 코드 에서이 문제를 해결하려고 노력했습니다. 아래의 예에 대한 문제를 단순화했습니다.
아이디어는 std :: end로 끝나는 문자열에 문자열을 저장 한 다음 나중에 검색하여 원래 문자열과 비교하는 것입니다.
#include <sstream> #include <iostream> #include <string> int main( int argc, char** argv ) { const std::string HELLO( "hello" ); std::stringstream testStream; testStream << HELLO << std::ends; std::string hi = testStream.str(); if( HELLO == hi ) { std::cout << HELLO << "==" << hi << std::endl; } return 0; }
아마도 추측 할 수 있듯이, 실행시 위의 코드는 아무것도 인쇄하지 않습니다.
인쇄되거나 디버거 (vs2005)에서 보았을 때 Hello and Hi는 동일하게 보이지만 .length ()는 실제로 1만큼 다릅니다. 이것이 제가 "=="연산자가 실패하게하는 것입니다.
내 질문은 이유입니다. STD :: ENDS가 왜 문자열 HI에 추가 된 보이지 않는 캐릭터인지 이해하지 못합니다. 또한이 보이지 않는 캐릭터는 부스트 트림으로 다듬어지지 않습니다. 그러나 strcmp를 사용하여 두 문자열의 .c_str ()를 비교하면 비교가 올바르게 작동합니다.
내가 STD ::를 처음 사용한 이유는 스트림 끝에 StringStream이 쓰레기 데이터를 유지하는 데 과거에 문제가 있었기 때문입니다. STD :: ENDS는 저를 위해 그것을 해결했습니다.
해결책
std::ends
널 문자를 스트림에 삽입합니다. 컨텐츠를 a로 가져옵니다 std::string
그 널 문자를 유지하고 각 위치에서 해당 널 문자로 문자열을 만듭니다.
따라서 실제로 std :: 문자열에는 내장 된 널 문자가 포함될 수 있습니다. 다음 std :: 문자열 내용 ~이다 다른:
ABC
ABC\0
이진 0은 공백이 아닙니다. 그러나 인쇄 할 수 없으므로 터미널이 특별히 표시되지 않는 한 볼 수 없습니다.
사용 비교 strcmp
a의 내용을 해석합니다 std::string
통과 할 때 C 문자열로 .c_str()
. 말할 것입니다
흠, 첫 번째 캐릭터
\0
(널 문자 종료)입니다 알파벳, 그래서 나는 그것을 끈이다 알파벳
따라서 위의 둘 사이의 차이는 보이지 않을 것입니다. 아마도이 문제가있을 것입니다.
std::stringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "b"); // will fail!
StringStream이 사용하는 시퀀스는 여전히 "Hello"를 포함하는 오래된 것이기 때문에 어설 싱은 실패 할 것입니다. 당신이 한 일은 첫 번째 캐릭터를 덮어 쓰는 것입니다. 당신은 이것을하고 싶습니다 :
std::stringstream s;
s << "hello";
s.str(""); // reset the sequence
s << "b";
assert(s.str() == "b"); // will succeed!
또한이 답변을 읽으십시오. 타조 스트림 재사용 방법
다른 팁
std::ends
단순히 널 캐릭터입니다. 전통적으로 C와 C ++의 문자열은 널 (ASCII 0) 문자로 종료되지만 std::string
실제로 이것을 요구하지 않습니다. 어쨌든 당신의 코드 포인트를 통해 우리는 몇 가지 흥미로운 일이 계속되고 있습니다.
int main( int argc, char** argv )
{
문자열 문자 "hello"
전통적인 제로 종료 문자열 상수입니다. 우리는 그 전체를 std::string
안녕하세요.
const std::string HELLO( "hello" );
std::stringstream testStream;
우리는 이제 string
안녕하세요 (후행 0 포함)에 stream
, 그 다음에 전화로 두 번째 널이 있습니다. std::ends
.
testStream << HELLO << std::ends;
우리는 우리가 넣은 물건의 사본을 추출합니다. stream
(문자 문자열 "Hello", 두 개의 널 터미네이터).
std::string hi = testStream.str();
그런 다음 두 줄을 사용하여 비교합니다 operator ==
에 std::string
수업. 이 연산자 (아마도)는 길이를 비교합니다. string
객체 - 후행 널 캐릭터가 얼마나 많은지를 포함하여. 주목하십시오 std::string
클래스는 기본 문자 배열이 후행 Null로 끝나도록 요구하지 않습니다. 다른 방법으로 문자열에 널 문자를 포함 할 수 있도록하여 두 개의 후행 널 문자 중 첫 번째는 문자열의 일부로 처리됩니다. hi
.
두 줄은 후행 널 수에서 다르기 때문에 비교가 실패합니다.
if( HELLO == hi )
{
std::cout << HELLO << "==" << hi << std::endl;
}
return 0;
}
인쇄되거나 디버거 (vs2005)에서 보았을 때 Hello and Hi는 동일하게 보이지만 .length ()는 실제로 1만큼 다릅니다. 이것이 제가 "=="연산자가 실패하게하는 것입니다.
그 이유는 길이가 하나의 후행 널 문자로 다릅니다.
내 질문은 이유입니다. STD :: ENDS가 왜 문자열 HI에 추가 된 보이지 않는 캐릭터인지 이해하지 못합니다. 또한이 보이지 않는 캐릭터는 부스트 트림으로 다듬어지지 않습니다. 그러나 strcmp를 사용하여 두 문자열의 .c_str ()를 비교하면 비교가 올바르게 작동합니다.
strcmp
다릅니다 std::string
- 문자열이 널로 끝나는 초기에 뒤로 작성되었습니다. hi
그것은 외모를 멈 춥니 다.
내가 STD ::를 처음 사용한 이유는 스트림 끝에 StringStream이 쓰레기 데이터를 유지하는 데 과거에 문제가 있었기 때문입니다. STD :: ENDS는 저를 위해 그것을 해결했습니다.
때로는 근본적인 표현을 이해하는 것이 좋습니다.
std :: end와 함께 널 숯을 추가하고 있습니다. str ()로 HI를 초기화하면 널 숯을 제거합니다. 줄은 다릅니다. strcmp는 std :: 문자열을 비교하지 않으며 char*를 비교합니다 (C 함수).
STD :: ENDS는 널 터미네이터 (char) ' 0'을 추가합니다. 널 터미네이터를 추가하기 위해 더 이상 사용되지 않은 strstream 클래스와 함께 사용합니다.
당신은 stringstream으로 그것을 필요로하지 않으며, 실제로 널 터미네이터는 "문자열을 끝내는 특수 널 터미네이터"가 아니기 때문에 stringstream에 "Stringstream은 또 다른 캐릭터 인 Zeroth 캐릭터이기 때문에 물건을 망쳐 놓습니다. StringStream 은이를 추가하면 문자 수 (귀하의 경우)가 7로 증가하고 "hello"와 비교할 수 있습니다.
현을 비교할 수있는 좋은 방법이 있다고 생각합니다. std::find
방법. C 방법을 혼합하지 마십시오 std::string ones
!