C ++: Comment diviser une chaîne en chaînes plus petites de taille égale?

En C ++, comment diviser une chaîne en une chaîne plus petite de taille égale?

Par exemple, j’ai une chaîne “012345678” et je souhaite la scinder en 5 chaînes plus petites. Cela devrait me renvoyer quelque chose comme “01”, “23”, “45”, “67”, “8”.

J’ai du mal à déterminer la longueur des petites chaînes. Dans l’exemple précédent, la chaîne d’origine a une taille de 9 et je souhaite la scinder en 5 chaînes plus petites. Chaque chaîne, à l’exception de la dernière, doit donc avoir une longueur de 9/5 = 1, mais la dernière sera de longueur 9 – 1 * 4 = 5, ce qui est inacceptable.

Donc, la définition formelle de ce problème : la chaîne originale est divisée EXACTEMENT en n chaînes, et aucune des deux chaînes ne devrait différer de plus de 1 en longueur.

Je ne me concentre pas sur la syntaxe ou la bibliothèque C ++. C’est comment concevoir un algorithme pour que la chaîne renvoyée puisse avoir une taille presque égale.

Pour diviser N éléments en M parties , avec des longueurs inférieures à une unité, vous pouvez utiliser la formule (N*i+N)/M - (N*i)/M tant que longueur de la i ème partie, comme illustré ci-dessous.

  #include  #include  using namespace std; int main() { ssortingng text = "abcdefghijklmnopqrstuvwxyz"; int N = text.length(); for (int M=3; M<14; ++M) { cout <<" length:"<< N <<" parts:"<< M << "\n"; int at, pre=0, i; for (pre = i = 0; i < M; ++i) { at = (N+N*i)/M; cout << "part " << i << "\t" << pre << "\t" << at; cout << "\t" << text.substr(pre, at-pre) << "\n"; pre = at; } } return 0; } 

Par exemple, lorsque M vaut 4 ou 5, le code ci-dessus produit:

  length:26 parts:4 part 0 0 6 abcdef part 1 6 13 ghijklm part 2 13 19 nopqrs part 3 19 26 tuvwxyz length:26 parts:5 part 0 0 5 abcde part 1 5 10 fghij part 2 10 15 klmno part 3 15 20 pqrst part 4 20 26 uvwxyz 

Ma solution:

 std::vector split(std::ssortingng const & s, size_t count) { size_t minsize = s.size()/count; int extra = s.size() - minsize * count; std::vector tokens; for(size_t i = 0, offset=0 ; i < count ; ++i, --extra) { size_t size = minsize + (extra>0?1:0); if ( (offset + size) < s.size()) tokens.push_back(s.substr(offset,size)); else tokens.push_back(s.substr(offset, s.size() - offset)); offset += size; } return tokens; } 

Code de test:

 int main() { std::ssortingng s; while (std::cin >> s) { std::vector tokens = split(s, 5); //output std::copy(tokens.begin(), tokens.end(), std::ostream_iterator(std::cout, ", ")); std::cout << std::endl; } } 

Consortingbution:

 012345 0123456 01234567 012345678 0123456789 01234567890 

Sortie:

 01, 2, 3, 4, 5, 01, 23, 4, 5, 6, 01, 23, 45, 6, 7, 01, 23, 45, 67, 8, 01, 23, 45, 67, 89, 012, 34, 56, 78, 90, 

Démo en ligne: http://ideone.com/gINtK

Cette solution a tendance à rendre les jetons égaux, c'est-à-dire que tous les jetons peuvent ne pas avoir la même taille.

Il suffit de connaître la longueur des sous-chaînes;
Supposons que m est la size() de votre chaîne:

 int k = (m%n == 0)? n : nm%n; 

Alors, k des sous-chaînes doivent être de longueur m/n et nk de longueur m/n+1 .

Vous obtenez des iterators où vous voulez le scinder, puis vous les utilisez pour construire de nouvelles chaînes. Par exemple:

 std::ssortingng s1 = "ssortingng to split"; std::ssortingng::iterator halfway = s1.begin() + s1.size() / 2; std::ssortingng s2(s1.begin(), halfway); std::ssortingng s3(halfway, s1.end()); 

Disons que la longueur de la chaîne est L et qu’elle doit être divisée en n sous-chaînes.

 # Find the next multiple of `n` greater than or equal to `L` L = 9 n = 5 LL = n * (L / n) if LL < L: LL += n # Split a string of length LL into n equal sizes. The string is at # most (n-1) longer than L. lengths = [(LL / n) for x in range (n)] # Remove one from the first (or any) (LL-L) elements. for i in range (LL-L): lengths [i] = lengths [i] - 1 # Get indices from lengths. s = 0 idx = [] for i in lengths: idx.append (s) s = s + i idx.append (L) print idx 

EDIT: OK, OK, j'ai oublié que cela devrait être C ++.

EDIT: Ici ça va ...

 #include  #include  unsigned int L = 13; unsigned int n = 5; int main () { int i; unsigned int LL; std::vector lengths, idx; /* Find the next multiple of `n` greater than or equal to `L` */ LL = n * (L / n); if (LL < L) LL += n; /* Split a string of length LL into n equal sizes. The string is at most (n-1) longer than L. */ for (i = 0; i < n; ++i) lengths.push_back (LL/n); /* Remove one from the first (or any) (LL-L) elements. */ for (i = 0; i < LL - L; ++i) --lengths [i]; /* Get indices from lengths. */ int s = 0; for (auto &ii: lengths) { idx.push_back (s); s += ii; } idx.push_back (L); for (auto &i : idx) std::cout << i << " "; std::cout << std::endl; return 0; } 

Essayez substr .