Comment fractionner une chaîne telle que "102:330:3133:76531:451:000:12:44412
" par le caractère ":
" et placer tous les nombres dans un tableau int (la séquence de nombres sera toujours longue de 8) De préférence sans utiliser une bibliothèque externe telle que boost.
Aussi, je me demande comment je peux supprimer les caractères inutiles de la chaîne avant qu'elle ne soit traitée, tels que "$" et "#"?
stringstream
peut faire tout cela.
Fractionner une chaîne et stocker dans int array:
string str = "102:330:3133:76531:451:000:12:44412";
std::replace(str.begin(), str.end(), ':', ' '); // replace ':' by ' '
vector<int> array;
stringstream ss(str);
int temp;
while (ss >> temp)
array.Push_back(temp); // done! now array={102,330,3133,76531,451,000,12,44412}
Supprimez les caractères inutiles de la chaîne avant son traitement, tels que $
et #
: exactement comme le traitement de :
décrit ci-dessus.
La méthode standard en C utilise strtok
comme d’autres ont répondu. Cependant, strtok
ne ressemble pas à C++
- et aussi unsafe . La méthode standard en C++ utilise std::istringstream
std::istringstream iss(str);
char c; // dummy character for the colon
int a[8];
iss >> a[0];
for (int i = 1; i < 8; i++)
iss >> c >> a[i];
Si l'entrée a toujours un nombre fixe de jetons comme celui-ci, sscanf
peut être une autre solution simple.
std::sscanf(str, "%d:%d:%d:%d:%d:%d:%d:%d", &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8);
Je devais écrire du code comme celui-ci auparavant et j'ai trouvé une question sur Stack Overflow pour scinder une chaîne par un délimiteur. Voici la question initiale: link .
Vous pouvez utiliser ceci avec std::stoi
pour construire le vecteur.
std::vector<int> split(const std::string &s, char delim) {
std::vector<int> elems;
std::stringstream ss(s);
std::string number;
while(std::getline(ss, number, delim)) {
elems.Push_back(std::stoi(number));
}
return elems;
}
// use with:
const std::string numbers("102:330:3133:76531:451:000:12:44412");
std::vector<int> numbers = split(numbers, ':');
Voici un moyen… pas le plus malin mais rapide à écrire (8 répétitions sont tout près de garantir une boucle). Cette approche de l'analyse syntaxique est très utile, donc il est bon d'apprendre. !(iss >> c)
s'assure qu'il n'y a pas de caractères de fin non blancs dans la chaîne.
std::istringstream iss(the_string);
char c;
int n[8];
if (iss >> n[0] >> c && c == ':' &&
iss >> n[1] >> c && c == ':' &&
iss >> n[2] >> c && c == ':' &&
iss >> n[3] >> c && c == ':' &&
iss >> n[4] >> c && c == ':' &&
iss >> n[5] >> c && c == ':' &&
iss >> n[6] >> c && c == ':' &&
iss >> n[7] && !(iss >> c))
...
Vous pouvez utiliser strtok()
pour scinder votre chaîne, peut-être dans une boucle while.
Lorsque vous obtenez une chaîne individuelle, vous pouvez utiliser atoi(xxx)
pour la conversion en ints.
Vrai ! il n'y a pas magie elfique
Son un peu répondu ici aussi
#include <cstring>
#include <iostream>
#include<cstdlib>
#include<vector>
int main()
{
char input[100] = "102:330:3133:76531:451:000:12:44412";
char *token = std::strtok(input, ":");
std::vector<int> v;
while (token != NULL) {
v.Push_back( std::strtol( token, NULL, 10 ));
token = std::strtok(NULL, ":");
}
for(std::size_t i =0 ; i < v.size() ; ++i)
std::cout << v[i] <<std::endl;
}
Démo Ici
Pour supprimer les caractères '#' et '$', vous pouvez utiliser l'algorithme standard std::remove_if
. Cependant, tenez compte du fait que s'il existe par exemple la chaîne suivante "12 # 34", après avoir supprimé "#", vous obtiendrez un "1234". Si vous avez besoin que la chaîne obtenue ressemble à "12 34" ou "12:34", alors au lieu de std::remove_if
, il est préférable d'utiliser std::replace_if
.
Vous trouverez ci-dessous un exemple de code qui effectue la tâche. Vous devez inclure des en-têtes
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
int main()
{
char s[] = "102:$$330:#3133:76531:451:000:$12:44412";
std::cout << s << std::endl;
char *p = std::remove_if( s, s + std::strlen( s ),
[]( char c ) { return ( c == '$' || c == '#' ); } );
*p = '\0';
std::cout << s << std::endl;
const size_t N = 8;
int a[N];
p = s;
for ( size_t i = 0; i < N; i++ )
{
a[i] = strtol( p, &p, 10 );
if ( *p == ':' ) ++p;
}
for ( int x : a ) std::cout << x << ' ';
std::cout << std::endl;
}
La sortie est
102:$$330:#3133:76531:451:000:$12:44412
102:330:3133:76531:451:000:12:44412
102 330 3133 76531 451 0 12 44412
#include <string.h>
int main ()
{
char str[] ="102:330:3133:76531:451:000:12:44412";
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;
}
Une autre solution utilisant les fonctionnalités d’expression régulière de C++ 11.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
int main()
{
const std::string s = "102:330:3133:76531:451:000:12:44412";
// Replace each colon with a single space
const std::regex pattern(":");
const std::string r = std::regex_replace(s, pattern, " ");
std::istringstream ist(r);
std::vector<int> numbers;
std::copy(std::istream_iterator<int>(ist), std::istream_iterator<int>(),
std::back_inserter(numbers));
// We now have a vector of numbers
// Print it out
for (auto n : numbers)
{
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}