Pergunta

No código C ++ seguinte, percebi que gcount() estava retornando um número maior do que eu queria, porque getline() consome o caractere final de nova linha, mas não enviá-lo para o fluxo de entrada.

O que eu ainda não entendo é a saída do programa, no entanto. Para a entrada de "Test \ n", por que eu recebo "est \ n"? Como é que o meu erro afeta o início caractere da string em vez de adicionar o lixo indesejado para o fim? E como é que a saída do programa está em desacordo com a forma como os olhares de cadeia no depurador ( "Test \ n", como seria de esperar)?

#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;
}
Foi útil?

Solução

Eu também duplicado este resultado, o Windows Vista, Visual Studio 2005 SP2.

Quando eu descobrir o que diabos está acontecendo, eu vou atualizar este post.

Editar : Ok, lá vamos nós. O problema (e os resultados diferentes pessoas estão recebendo) são do \ r. O que acontece é que você chama input.getline e colocou o resultado em vecBuffer. A função getline retira os \ n, mas deixa o \ r no lugar.

Você, então, transferir a vecBuffer numa variável de cadeia, mas usar a função gcount de entrada, ou seja, você vai ter um caractere muito, porque a variável de entrada ainda contém o n \, eo vecBuffer não.

O strResult resultante é:

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

Assim, em seguida, "Test" é impresso, seguido por um retorno de carro (coloca a volta cursor no início da linha), um caractere nulo (substituindo a T), e finalmente o \ n, o que coloca correctamente o cursor na a nova linha.

Então, você tem que retirar o \ r, ou escrever uma função que recebe o comprimento da corda diretamente do vecBuffer, a verificação de caracteres nulos.

Outras dicas

Eu duplicado o problema de Tommy em um sistema Windows XP Pro Service Pack 2 com o código compilado usando Visual Studio 2005 SP2 (na verdade, ele diz que "versão 8.0.50727.879"), construído como um projeto de console.

Se meu arquivo test.txt contém apenas "Test" e uma CR, os espetos de programa fora "est" (note o espaço à esquerda) quando for executado.

Se eu tivesse que dar um palpite, eu diria que esta versão da implementação tem um bug onde ele está tratando o caractere de nova linha Windows, como ele deve ser tratado em Unix (como um "ir para a frente da mesma linha" personagem), e, em seguida, ele apaga o primeiro personagem a parte espera do próximo prompt ou algo assim.


Update: Depois de jogar com ele um pouco, eu tenho certeza que é o que está acontecendo. Se você olhar para strResult no depurador, você vai ver que ele copiou um valor decimal 13 no final. Isso é CR, que no Windows-terra é '\ n', e em qualquer outro lugar é "retorno ao início da linha". Se eu em vez mudar o seu construtor para ler:

string strResult (vecBuffer.begin (), vecBuffer.begin () + input.gcount () - 1);

... (para que o CR não é copiado) então ela mostra "Test" como você esperaria.

Tenho a certeza de que o T está realmente ficando por escrito e, em seguida, substituído. Executando o mesmo programa em uma janela do rxvt (cygwin) produz a saída esperada. Você pode fazer algumas coisas. Se você se livrar dos ios :: binary em sua aberto ele irá converte automaticamente \ r \ n para \ n e as coisas vão funcionar como você espera.

Você também pode abrir o seu arquivo de texto no editor binário clicando na pequena seta para baixo no botão de abertura do diálogo de arquivo aberto e selecionando Abrir com ...-> Editor de binário. Isso permitirá que você olhar para o seu arquivo e confirmar que ele realmente tem \ r \ n e não apenas \ n.

Editar: I redirecionado a saída para um arquivo e ele está escrevendo para fora:

Test\r\0\r\n

A razão que você está recebendo o \ 0 é que gcount retornos 6 (6 caracteres foram removidos do fluxo), mas o delimitador final não é copiado para o buffer, um '\ 0' é em vez disso. quando você está construindo a corda, você está realmente dizendo a ele para incluir o '\ 0'. std :: string não tem nenhum problema com os embutidos 0 e saídas-lo como convidados. Alguns cascas são, aparentemente, a emissão de um caractere em branco e substituindo a T, enquanto outros não fazem nada ea saída parece bem, mas ainda é provavelmente errado, porque ele tem o embutido '\ 0'

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

Alterar a última linha para isto irá parar na \ 0 e também obter o resultado esperado.

Eu testei seu código usando o Visual Studio 2005 SP2 no Windows XP Pro SP3 (32 bits), e tudo funciona bem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top