Question

Un morceau commun de code que j'utilise pour diviser la chaîne simple ressemble à ceci:

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

Quelqu'un a dit que cela en silence des erreurs « avaler » se produisant dans std::getline. Et bien sûr, je suis d'accord que ce soit le cas. Mais il me vint, ce qui pourrait mal tourner ici dans la pratique que je besoin de vous inquiéter. essentiellement tout se résume à ceci:

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

Un stringstream est soutenu par une string, donc nous n'avons pas à vous soucier des problèmes liés à la lecture d'un fichier. Il n'y a pas de conversion de type passe ici depuis getline lit simplement jusqu'à ce qu'il voit la ligne délimiteur ou EOF. Donc, nous ne pouvons pas obtenir l'une des erreurs que quelque chose comme boost::lexical_cast doit se préoccuper.

Je ne peux pas penser à quelque chose plus de ne pas allouer suffisamment de mémoire qui pourrait aller mal, mais ça va juste jeter un std::bad_alloc bien avant la std::getline a lieu même. Qu'est-ce que je manque?

Était-ce utile?

La solution

Je ne peux pas imaginer ce que cette personne pense des erreurs peut arriver, et vous devriez leur demander d'expliquer. Rien ne peut aller mal, sauf les erreurs d'allocation, comme vous l'avez mentionné, qui sont jetés et non avalés.

La seule chose que je vois que vous êtes absent directement que ss.fail() est garantie pour être vrai après la boucle while, parce que c'est la condition testée. (bool(stream) équivaut à !stream.fail(), pas stream.good().) Comme prévu, ss.eof() sera également vrai, indiquant l'échec était dû à EOF.

Cependant, il pourrait y avoir une certaine confusion sur ce qui se passe réellement. Parce que getline utilise delim - résiliés les champs plutôt que delim - séparés champs, entrée des données telles que "a\nb\n" a deux au lieu de trois champs, et cela pourrait être surprenant. Pour les lignes ce sens complet (et standard POSIX), mais combien de champs, avec delim de '-', seriez-vous attendre à trouver dans "a-b-" après la séparation?


Par ailleurs, voici comment je écrire divisée:

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

Cela permet d'éviter tous les problèmes avec iostreams en premier lieu, évite des copies supplémentaires (la chaîne de soutien du stringstream, ainsi que la température de retour par substr peut même utiliser une référence C ++ 0x rvalue pour la sémantique de déplacement si elle est soutenue, comme écrit) , a le comportement que j'attends de Split (différent du vôtre), et fonctionne avec tout récipient.

deque<string> c;
split("a-b-", '-', back_inserter(c));
// c == {"a", "b", ""}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top