문제

다음 C ++ 코드에서는 gcount() 내가 원했던 것보다 더 많은 수를 반환하고 있었기 때문에 getline() 최종 Newline 문자를 소비하지만 입력 스트림으로 보내지 않습니다.

그래도 내가 여전히 이해하지 못하는 것은 프로그램의 출력입니다. "Test n"을 입력하려면 왜 "EST n"을 얻습니까? 내 실수가 어떻게 영향을 미칩니다 첫 번째 끝에 원치 않는 쓰레기를 추가하기보다는 문자열의 성격? 그리고 어떻게 프로그램의 출력이 디버거에서 문자열이 보이는 방식과 어떻게 상충 되는가 (내가 기대하는대로 "테스트 n")?

#include <fstream>
#include <vector>
#include <string>
#include <iostream>

using namespace std;

int main()
{
    const int bufferSize = 1024;
    ifstream input( "test.txt", ios::in | ios::binary );

    vector<char> vecBuffer( bufferSize );
    input.getline( &vecBuffer[0], bufferSize );
    string strResult( vecBuffer.begin(), vecBuffer.begin() + input.gcount() );
    cout << strResult << "\n";

    return 0;
}
도움이 되었습니까?

해결책

또한이 결과, Windows Vista, Visual Studio 2005 SP2를 복제했습니다.

도대체 무슨 일이 일어나고 있는지 알아 내면이 게시물을 업데이트하겠습니다.

편집하다: 좋아, 우리는 간다. 문제 (그리고 사람들이 얻은 다른 결과)는 r에서 나온 것입니다. 무슨 일이 일어나는지 당신은 전화입니다 input.getline 결과를 Vecbuffer에 넣으십시오. getline 함수는 n에서 벗어나지 만 r을 제자리에 둡니다.

그런 다음 vecbuffer를 문자열 변수로 전송하지만 입력에서 gcount 함수를 사용합니다. 즉, 입력 변수에는 여전히 n을 포함하고 Vecbuffer는 그렇지 않기 때문에 하나의 숯이 너무 많이 얻을 수 있습니다.

결과적인 strresult는 다음과 같습니다.

-       strResult   "Test"
        [0] 84 'T'  char
        [1] 101 'e' char
        [2] 115 's' char
        [3] 116 't' char
        [4] 13 '␍'  char
        [5] 0   char

그러면 "테스트"가 인쇄 된 다음 캐리지 리턴 (커서를 라인의 시작 부분에 다시 넣음), 널 문자 (T를 덮어 쓰기) 및 마지막으로 커서를 새 라인에 올바르게 넣습니다. .

따라서 r을 제거하거나 vecbuffer에서 직접 문자열 길이를 가져 오는 함수를 작성하여 널 문자를 확인해야합니다.

다른 팁

Console 프로젝트로 구축 된 Visual Studio 2005 SP2 (실제로 "버전 8.0.50727.879")를 사용하여 코드가 컴파일 된 코드가있는 Windows XP Pro Service Pack 2 시스템에서 Tommy의 문제를 복제했습니다.

내 test.txt 파일에 단지 "테스트"와 CR이 포함 된 경우, 프로그램은 실행될 때 "EST"(주요 공간에 주목)를 뱉어냅니다.

내가 거친 추측을해야한다면,이 구현 버전에는 Windows Newline 캐릭터를 처리하는 버그가 Unix에서 처리되어야하는 것처럼 "같은 줄의 전면으로 이동"으로 처리해야한다고 말할 것입니다. 캐릭터), 그리고 다음 프롬프트의 일부를 유지하기 위해 첫 번째 캐릭터를 닦아냅니다.


업데이트:조금씩 놀고 나면 나는 그것이 일어나고있는 일입니다. 디버거에서 strresult를 보면 끝에 10 진수 13 값을 복사 한 것을 볼 수 있습니다. 그것은 Windows-Land의 ' n'인 CR이고 다른 곳은 "줄의 시작으로 돌아갑니다". 대신 생성자를 읽도록 변경하면 다음과 같습니다.

String strresult (vecbuffer.begin (), vecbuffer.begin () + input.gcount () -1);

... (CR이 복사되지 않도록) 그런 다음 예상 한 것처럼 "테스트"를 인쇄합니다.

나는 t가 실제로 쓰여진 다음 덮어 쓰고 있다고 확신합니다. RXVT 창 (Cygwin)에서 동일한 프로그램을 실행하면 예상 출력이 생성됩니다. 당신은 몇 가지를 할 수 있습니다. 당신이 당신의 오픈에서 ios :: binary를 제거하면 r n to n을 autoconvert 그리고 당신이 기대하는 것처럼 작동합니다.

파일 열기 대화의 열린 버튼에서 작은 아래쪽 화살표를 클릭하고 ...-> 이진 편집기를 사용하여 열기를 선택하여 바이너리 편집기에서 텍스트 파일을 열 수도 있습니다. 이렇게하면 파일을보고 실제로 n이 아니라 r n이 있음을 확인할 수 있습니다.

편집하다:출력을 파일로 리디렉션했는데 다음과 같이 기록하고 있습니다.

Test\r\0\r\n

0을 얻는 이유는 Gcount Returns 6 (6자가 스트림에서 6자가 제거 됨)이지만 최종 구분 기자가 버퍼에 복사되지 않기 때문입니다. 대신 ' 0'입니다. 문자열을 구성 할 때 실제로 ' 0'을 포함하도록 지시합니다. STD :: String은 임베디드 0에 아무런 문제가 없으며 요청대로 출력합니다. 일부 쉘은 분명히 빈 문자를 출력하고 T를 덮어 쓰고있는 반면, 다른 쉘은 아무것도하지 않으며 출력은 괜찮아 보이지만 ' 0'이 포함되어 있기 때문에 여전히 잘못되었을 것입니다.

cout << strResult.c_str() << "\n";

마지막 줄을 변경하면 0에서 중지되고 출력이 예상됩니다.

Windows XP Pro SP3 (32 비트)에서 Visual Studio 2005 SP2를 사용하여 코드를 테스트했으며 모든 것이 잘 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top