2014-10-03 4 views
1

데이터 조각을 구분하기 위해 \ 0을 사용하고 행을 구분하기 위해 \ n을 사용하는 소켓에서 큰 버퍼를 읽으려고합니다.C++ getline()은 0을 포함하는 문자열 스트림을 읽을 때 이상하게 동작합니다.

필자는 getline()이 각 행을 쉽게 얻을 수 있다고 생각했지만 이상하게 행동했습니다.

getline()의 구분 기호로 \ n을 사용하고 있습니다.

string line; 
string test1 = "aaa,123\nbbb\nccc,456\n"; 
stringstream ss1(test1); 
while(std::getline(ss1, line, '\n')) { 
    cout << line << endl; 
    } 
// outputs: 
// aaa,123 
// bbb 
// ccc,456 

string test2 = "aaa\0123\0\nbbb\0\nccc\0456\0\n"; 
stringstream ss2(test2); 
while(std::getline(ss2, line, '\n')) { 
    cout << line << endl; 
    } 
// outputs: 
// aaa 
// 3 

왜이 문제가 test2에서 발생합니까? 3은 어디에서 오는 것입니까? 이 작업을 수행하려면 \ 0을 제거해야합니까? 소켓 recv() 할 때 내 버퍼 문자열을 표시하는 더 쉽고/좋은 방법 있는가?

+0

왜 소켓의 데이터가 처음부터 줄에 null이 있습니까? 텍스트 일 ​​예정이라면, 널 (null)을 포함해서는 안됩니다. – Barmar

+2

오, 나는 3이 어디서 왔는지 보았습니다. 첫 번째'\ 0'은 널이 아니며'\ 012'의 시작입니다. 이것은 캐리지 리턴입니다. 그 다음 3이 뒤 따른다. –

+1

줄 바꾸기가 아니라 줄 바꿈입니다. CR은 '\ 015'입니다. LF는 C 개행 문자이기도합니다. – Barmar

답변

3

\0을 특수 기호로 사용하십시오. 문자열이 끝나는 시점을 보여줍니다.

예를 들어 "a string"을 입력하면 컴파일러에서 자동으로 \0을 끝에 추가하여 문자열의 끝을 의미합니다. 그러나 문자열 중간에 \0이있는 것은 합법적입니다. 단지 무시 된 이후의 모든 내용을 의미합니다.

기본적으로 getline뿐만 아니라 문자열에서 수행하는 모든 작업은 문자열을 "aaa"으로 처리하고 첫 번째 문자 인 \0 다음을 모두 무시합니다. 하지만 ... @Fred 라슨으로

은 3 출처

아, 내가 볼 지적한다. 첫 번째 \ 0은 null이 아니며 \ 012의 시작이며 캐리지 리턴입니다. 그 다음 3이 뒤 따른다.

실제로 문자열은 "aaa\n3"으로 처리됩니다. 그래서 당신이하는 결과를 얻을 수 있습니다.

편집 : Galik 덕분에 언급 한 규칙이 문자열 리터럴/C 문자열에만 적용될 수 있다고 덧붙입니다. std::string s와는 다른 경우 일 수 있습니다. 문자열의 길이는 미리 알고 있습니다.

+0

@ 갤릭 괜찮습니다. 어디에서 잘못했는지 알고 싶습니다. – BWG

+0

@Galik 문자열 리터럴의 문자열 생성자는 사실입니다! 여기가 중요합니다. 보다 일반적으로 임베디드 NUL은 배열에 적절하게 배치되며 해당 리터럴을 사용하는 코드는 무시할 필요가 없습니다 (예를 들어, 전체 길이를 지정하는 쓰기가 모든 데이터를 찾을 수 있습니다). 무시할 ASCIIZ 처리 일뿐입니다 . –

+0

그리고 제가 말하고있는 것은 기술적 인면에서 올바르지 않을 수도 있다는 것을 알고 있습니다 만, 실용적인면에서는 올바른 것이라고 생각합니다. 그게 아니라면 그냥 지울거야. – BWG

0

\ 0은 표준 문자열 종결 자 기호입니다. 따라서 문자 단위로 문자를 읽거나 리 플리 미터로 \ 0을 피할 수 있습니다.