Pergunta

Uma peça de código comum que eu uso para divisão simples de cordas se parece com o seguinte:

inline std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

Alguém mencionou que isso silenciosamente "engolirá" erros que ocorrem em std::getline. E é claro que eu concordo que é esse o caso. Mas me ocorreu, o que poderia dar errado aqui na prática que eu precisaria me preocupar. Basicamente, tudo se resume a isso:

inline std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }

    if(/* what error can I catch here? */) {
        // *** How did we get here!? ***
    }

    return elems;
}

UMA stringstream é apoiado por um string, então não precisamos nos preocupar com nenhum dos problemas associados à leitura de um arquivo. Não há conversão de tipo acontecendo aqui desde getline simplesmente lê até ver o delímetro da linha ou EOF. Portanto, não podemos obter nenhum dos erros que algo é como boost::lexical_cast tem que se preocupar.

Eu simplesmente não consigo pensar em algo além de não alocar memória suficiente que pode dar errado, mas isso apenas jogará um std::bad_alloc bem antes do std::getline até acontece. o que estou perdendo?

Foi útil?

Solução

Não consigo imaginar quais erros essa pessoa acha que pode acontecer e você deve pedir que ela explique. Nada pode dar errado, exceto erros de alocação, como você mencionou, que são jogados e não engolidos.

A única coisa que vejo que você está perdendo diretamente é que ss.fail() é garantido que é verdadeiro após o loop while, porque essa é a condição que está sendo testada. (bool(stream) é equivalente a !stream.fail(), não stream.good().) Como esperado, ss.eof() também será verdadeiro, indicando que a falha foi devida ao EOF.

No entanto, pode haver alguma confusão sobre o que realmente está acontecendo. Porque Obter linha usos Delim-terminado campos em vez de Delim-separado campos, dados de entrada como "a\nb\n" tem dois em vez de três campos, e isso pode ser surpreendente. Para linhas, isso faz sentido completo (e é padrão POSIX), mas quantos campos, com um Delim do '-', você esperaria encontrar em "a-b-" Depois de se separar?


Aliás, aqui está como eu eu Escreva dividir:

template<class OutIter>
OutIter split(std::string const& s, char delim, OutIter dest) {
  std::string::size_type begin = 0, end;
  while ((end = s.find(delim, begin)) != s.npos) {
    *dest++ = s.substr(begin, end - begin);
    begin = end + 1;
  }
  *dest++ = s.substr(begin);
  return dest;
}

Isso evita todos os problemas com o iostreams em primeiro lugar, evita cópias extras (a corda de apoio do StringStream; mais a temperatura retornada por substrato pode até usar uma referência de C ++ 0x Rvalue para mover semântica se suportada, conforme escrito), tem o Comportamento que espero de Split (diferente do seu) e trabalha com qualquer contêiner.

deque<string> c;
split("a-b-", '-', back_inserter(c));
// c == {"a", "b", ""}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top