Pergunta

passei cerca de 4 horas ontem tentando corrigir esse problema no meu código. I simplificou o problema para o exemplo abaixo.

A idéia é armazenar uma string em um stringstream terminando com std :: extremidades, depois recuperá-lo mais tarde e compará-la com a string original.

#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;
}

Como você provavelmente pode adivinhar, o código acima quando executado não irá imprimir nada.

Embora, se impresso, ou olhou no depurador (VS2005), OLÁ e olhar oi idêntica, sua .length () Na realidade difere por 1. Isso é o que eu estou supondo que está causando o operador "==" para falhou.

A minha pergunta é o porquê. Eu não entendo por que std :: extremidades é um personagem invisível adicionado a corda oi, tornando oi e Olá comprimentos diferentes, embora tenham conteúdo idêntico. Além disso, este personagem invisível não se aparadas com impulso da guarnição. No entanto, se você usar strcmp para comparar .c_str () das duas cordas, a comparação funciona corretamente.

A razão que eu usei std :: extremidades, em primeiro lugar é porque eu tive problemas no passado com dados de lixo stringstream de retenção no final do fluxo. std :: extremidades resolvido isso para mim.

Foi útil?

Solução

std::ends insere um caractere nulo no fluxo. Obtendo o conteúdo como um std::string vai manter esse caractere nulo e criar uma cadeia com que caractere nulo nas respectivas posições.

caracteres nulos Então, na verdade, um std :: string pode conter incorporado. O conteúdo seguinte std :: string são diferente:

ABC
ABC\0

Um zero binário não espaço em branco é. Mas também não é impressão, para que você não vai vê-lo (a menos que seus monitores de terminais que ele seja especialmente).

Comparando usando strcmp irá interpretar o conteúdo de um std::string como uma string C quando você passa .c_str(). Ele vai dizer

Hmm, caracteres antes do primeiro \0 (terminação caractere nulo) são ABC , então eu levá-la a corda é ABC

E, assim, ele não vai ver nenhuma diferença entre os dois acima. Você provavelmente está tendo esse problema:

std::stringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "b"); // will fail!

O assert irá falhar, porque a seqüência que usa o stringstream ainda é o antigo que contém "Olá". O que você fez é apenas substituindo o primeiro caractere. Você quer fazer isso:

std::stringstream s;
s << "hello";
s.str(""); // reset the sequence
s << "b";
assert(s.str() == "b"); // will succeed!

Leia também esta resposta: Como reutilizar um ostringstream

Outras dicas

std::ends é simplesmente um caractere nulo. Tradicionalmente, cordas em C e C ++ terminam com um caractere nulo (ASCII 0), no entanto verifica-se que std::string realmente não exigem essa coisa. De qualquer forma a passo através de seu ponto de código de ponto vemos algumas coisas interessantes acontecendo:

int main( int argc, char** argv )
{

O "hello" literal string é uma tradicional terminado constante de cadeia zero. Copiamos que todo na OLÁ std::string.

    const std::string HELLO( "hello" );

    std::stringstream testStream;

agora colocar o OlÁ string (incluindo o arrasto 0) para o stream, seguido por um segundo nulo que é colocada ali pela chamada para std::ends.

    testStream << HELLO << std::ends;

Nós extrair uma cópia do material que colocamos no stream (a string literal "Olá", mais os dois terminadores nulos).

    std::string hi = testStream.str();

Em seguida, comparar as duas seqüências usando o operator == na classe std::string. Este operador (provavelmente) compara o comprimento dos objetos string - incluindo como nunca caracteres nulos muitos de fuga. Note-se que a classe std::string não exige que o array de caracteres subjacente para terminar com um nulo à direita - dito de outra forma ele permite que a corda para conter caracteres nulos para que o primeiro dos dois à direita caracteres nulos é tratada como parte do hi corda

Uma vez que as duas cadeias são diferentes do número de valores nulos de arrasto, a comparação falha.

    if( HELLO == hi )
    {
        std::cout << HELLO << "==" << hi << std::endl;
    }

    return 0;
}

Embora, se impresso, ou olhou no depurador (VS2005), OlÁ e oi parecem idênticos, sua .length () in fato difere por 1. Isso é o que eu sou supondo que está causando o operador "==" a falhar.

Razão de ser, o comprimento é diferente por um caractere nulo final.

A minha pergunta é o porquê. eu não entender por que std :: extremidades é um personagem invisível adicionado a corda oi, tornando oi e OLÁ diferente comprimentos, apesar de terem conteúdo idêntico. Além disso, este personagem invisível não recebe aparadas com impulso da guarnição. No entanto, se você usa strcmp para comparar .c_str () de as duas cordas, as obras de comparação corretamente.

strcmp é diferente de std::string - está escrito de volta nos primeiros dias, quando cordas foram encerrados com um nulo -. Assim, quando se chega ao primeiro nulo à direita no hi ele pára de olhar

A razão que eu usei std :: extremidades na primeiro lugar é porque eu tive problemas no passado com stringstream retendo dados de lixo na extremidade de o fluxo. std :: extremidades resolvido que, para me.

Às vezes é uma boa idéia para compreender a representação subjacente.

Você está adicionando um char NULL para OLÁ com std :: extremidades. Quando você inicializa oi com str () você está removendo o caractere NULL. As cordas são diferentes. não strcmp não comparar std :: cordas, ele compara char * (é uma função C).

std :: extremidades adiciona um terminador nulo, (char) '\ 0'. Você poderia usá-lo com as classes strstream obsoletos, para adicionar o terminador nulo.

Você não precisa dele com stringstream, e na verdade ele parafusos as coisas, porque o terminador nulo não é "o terminador nulo especial que termina a string" para stringstream, para stringstream é só outro personagem, o personagem zeroth . stringstream apenas acrescenta, e que aumenta a contagem de caracteres (no seu caso) para sete, e faz a comparação com "Olá" falhar.

Eu acho que ter uma boa maneira de comparar strings é usar o método std::find. Não misture métodos C e std::string ones!

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