Pergunta

Estou tendo dificuldade em usar o std :: string :: iterators em c ++. Esse código compila Fine (ainda não obtendo saída correta, mas isso é culpa minha: TODO, FIX O algoritmo) no Dev-C ++, e eu não recebo erros de tempo de execução. O erro é com o Visual Studio Express 2008 C ++, onde estou recebendo um erro apontando para <xstring>: "Expression: string iterator não dereferenciável" e aponta para a linha 112 do arquivo <xstring>.

Minha depuração me diz que eu posso estar tentando desreferenciar após o fim da entrada da frase, mas não consigo ver onde. Alguém pode lançar alguma luz?

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it < sentence.end())
    {
       while (*it != ' ' && it != sentence.end())
       {
          nextWordLength++;
          distanceFromWidth--;
          it++;
       }

       if (nextWordLength > distanceFromWidth)
       {
          *it = '\n';
          distanceFromWidth = width;
          nextWordLength = 0;
       }

       //skip the space
       it++;

   }

   return sentence;    
}
Foi útil?

Solução

Em primeiro lugar, use o operador! = () Em iteradores, não operador <():

while (it != sentence.end())

Em segundo lugar, isso é para trás: while (*it != ' ' && it != sentence.end())

Você faz algo com o iterador, do que verifica se o iterador é válido. Em vez disso, você deve verificar se é válido primeiro:

while (it != sentence.end() && *it != ' ')

Em terceiro lugar, você deve usar o iterador ++ sobre o iterador ++, embora isso não esteja relacionado ao seu travamento.


Quarto, uma questão principal está aqui:

*it = '\n';

Por causa da verificação precedente, while (it != sentence.end(), é possível alcançar essa desreferência do iterador enquanto estiver no final. Uma correção seria fazer isso:

if (it != sentence.end() && nextWordLength > distanceFromWidth)

Então agora, se você chegou ao fim, você para.


Depois de corrigir a edição anterior, agora o único problema é o seguinte:

//skip the space
++it;

Isso pressupõe que o personagem que você está pulando é de fato um espaço. Mas e o fim da string? Execute esta função com esta string:

"a test string " // <- space at end

E terá sucesso; Ele pula o espaço, colocando o iterador em end(), o loop sai e o sucesso.

No entanto, sem o espaço, ele falhará, porque você chegou ao fim e está pulando pelo fim. Para consertar, adicione um cheque:

//skip the space
if (it != sentence.end())
{
    ++it;
}

Resultando neste código final:

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it != sentence.end())
    {
        while (it != sentence.end() && *it != ' ')
        {
            nextWordLength++;
            distanceFromWidth--;
            ++it;
        }

        if (it != sentence.end() && nextWordLength > distanceFromWidth)
        {
            *it = '\n';
            distanceFromWidth = width;
            nextWordLength = 0;
        }

        //skip the space
        if (it != sentence.end())
        {
            ++it;
        }

    }

    return sentence;    
}

Você pode notar que isso parece ter muitos cheques redundantes. Isso pode ser corrigido:

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it != sentence.end())
    {
        while (*it != ' ')
        {
            nextWordLength++;
            distanceFromWidth--;

            ++it;

            // check if done
            if (it == sentence.end())
            {
                return sentence;
            }
        }

        if (nextWordLength > distanceFromWidth)
        {
            *it = '\n';
            distanceFromWidth = width;
            nextWordLength = 0;
        }

        //skip the space
        ++it;
    }

    return sentence;    
}

Espero que isso ajude!

Outras dicas

while (*it != ' ' && it != sentence.end())

muda para

while (it != sentence.end() && *it != ' ')

Portanto, a segunda expressão não é avaliada se a primeira se falsa.

   if (nextWordLength > distanceFromWidth)

provavelmente deveria mudar para

   if (it == sentence.end())
         break;
   if (nextWordLength > distanceFromWidth)

Quase certamente seu erro é o resultado de:

*it = '\n';

Desde o anterior, enquanto o loop, uma de suas condições de parada é:

it != sentence.end()

Se == sentença.end (), então *it = ' n' não voará

Existem mais erros, mas é esse que está causando seu problema atual.

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