web-dev-qa-db-fra.com

Fractionner la chaîne par des espaces simples

Dupliquer possible:
Comment diviser une chaîne en C++?

Je dois diviser une chaîne par des espaces simples et la stocker dans un tableau de chaînes. Je peux y arriver en utilisant un istringstream, mais ce que je ne suis pas capable de faire, c'est ceci:

Je veux que chaque espace termine le mot actuel. Donc, s'il y a deux espaces consécutifs, un élément de mon tableau doit être vide.

Par exemple:

(le trait de soulignement indique l'espace)

This_is_a_string.
gets split into:
A[0] = This
A[1] = is
A[2] = a
A[3] = string.

This__is_a_string.
gets split into:
A[0] = This
A[1] = ""
A[2] = is
A[3] = a
A[4] = string.

Comment puis-je implémenter cela?

31
xbonez

Vous pouvez même développer votre propre fonction de partage (je sais, un peu démodé):

size_t split(const std::string &txt, std::vector<std::string> &strs, char ch)
{
    size_t pos = txt.find( ch );
    size_t initialPos = 0;
    strs.clear();

    // Decompose statement
    while( pos != std::string::npos ) {
        strs.Push_back( txt.substr( initialPos, pos - initialPos ) );
        initialPos = pos + 1;

        pos = txt.find( ch, initialPos );
    }

    // Add the last one
    strs.Push_back( txt.substr( initialPos, std::min( pos, txt.size() ) - initialPos + 1 ) );

    return strs.size();
}

Ensuite, il vous suffit de l'invoquer avec un vecteur <string> en tant qu'argument:

int main()
{
    std::vector<std::string> v;

    split( "This  is a  test", v, ' ' );
    dump( cout, v );

    return 0;
}

Recherchez le code permettant de fractionner une chaîne dans IDEone .

J'espère que cela t'aides.

25
Baltasarq

Si le délimiteur est strictement composé d'un seul caractère, Probablement std::getline sera valide.
Par exemple:

int main() {
  using namespace std;
  istringstream iss("This  is a string");
  string s;
  while ( getline( iss, s, ' ' ) ) {
    printf( "`%s'\n", s.c_str() );
  }
}
26
Ise Wisteria

Pouvez-vous utiliser boost ?

samm$ cat split.cc
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

#include <boost/foreach.hpp>

#include <iostream>
#include <string>
#include <vector>

int
main()
{
    std::string split_me( "hello world  how are   you" );

    typedef std::vector<std::string> Tokens;
    Tokens tokens;
    boost::split( tokens, split_me, boost::is_any_of(" ") );

    std::cout << tokens.size() << " tokens" << std::endl;
    BOOST_FOREACH( const std::string& i, tokens ) {
        std::cout << "'" << i << "'" << std::endl;
    }
}

exemple de réalisation:

samm$ ./a.out
8 tokens
'hello'
'world'
''
'how'
'are'
''
''
'you'
samm$ 
4
Sam Miller

Si vous êtes réticent à l’optimisation, vous pouvez utiliser l’ancien operator>> classique, avec std::noskipws:

EDIT: mises à jour après test.

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <sstream>

void split(const std::string& str, std::vector<std::string>& v) {
  std::stringstream ss(str);
  ss >> std::noskipws;
  std::string field;
  char ws_delim;
  while(1) {
    if( ss >> field )
      v.Push_back(field);
    else if (ss.eof())
      break;
    else
      v.Push_back(std::string());
    ss.clear();
    ss >> ws_delim;
  }
}

int main() {
  std::vector<std::string> v;
  split("hello world  how are   you", v);
  std::copy(v.begin(), v.end(), std::ostream_iterator<std::string>(std::cout, "-"));
  std::cout << "\n";
}

http://ideone.com/62McC

3
Robᵩ

Si vous n'êtes pas opposé au boost, boost.tokenizer est suffisamment flexible pour le résoudre.

#include <string>
#include <iostream>
#include <boost/tokenizer.hpp>

void split_and_show(const std::string s)
{
    boost::char_separator<char> sep(" ", "", boost::keep_empty_tokens);
    boost::tokenizer<boost::char_separator<char> > tok(s, sep);
    for(auto i = tok.begin(); i!=tok.end(); ++i)
            std::cout << '"' << *i << "\"\n";
}
int main()
{
    split_and_show("This is a string");
    split_and_show("This  is a string");

}

test: https://ideone.com/mN2sR

2
Cubbi

Vous pouvez aussi simplement utiliser l'ancienne mode 'strtok'

http://www.cplusplus.com/reference/clibrary/cstring/strtok/

C'est un peu bizarre mais n'implique pas l'utilisation de boost (ce n'est pas une mauvaise chose).

En gros, vous appelez strtok avec la chaîne que vous voulez scinder et le délimiteur (dans ce cas, un espace) et il vous renverra un char *. 

Du lien:

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This, a sample string.";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}
2
TurqMage

Vous pouvez utiliser la fonction simple strtok () (*) à partir d'ici . Notez que les jetons sont créés sur des délimiteurs

#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="- This is a string";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}
0
user349026