web-dev-qa-db-fra.com

Analyser la chaîne contenant des nombres dans un tableau d'entiers

Une chaîne est donnée comme une entrée qui se compose de nombres et je veux la convertir en tableaux entiers en C++.

#include <string>
#include <iostream>
#include <sstream>

using std::string;
using std::stringstream;
using std::cout;
using std::endl;

int main(int argc,char** argv) {

    string num="-24 2 90 24 50 76";

    stringstream stream(num);

    while(stream){
        int n;
        stream>>n;
        cout<<n<<endl;
    }

    return 0;
}

Sortie (GCC):

-24 2 90 24 50 76 76

Pourquoi est-ce que j'obtiens une valeur supplémentaire et quelle est l'efficacité pour les convertir en tableau entier?

METTRE À JOUR:

Que faire si le flux de chaînes contient un délimiteur autre que de l'espace, comment analyser cela? Par exemple: string num="-24,2,90,24,50,76";

16
djadmin

La condition de fin de fichier est pas définie sur une analyse réussie, vous devez vérifier l'état du flux après l'analyse.

La deuxième 76 est simplement un pur hasard. Une analyse infructueuse laisse intact l'opérande cible, et comme vous n'avez pas initialisé n, cela peut être n'importe quoi.

Un quickfix:

stream>>n;
if (stream)
    cout<<n<<endl;

Une solution plus propre:

int n;
while(stream >> n){
    cout<<n<<endl;
}

Pour stocker ces entiers, la méthode canonique consiste à utiliser std::vector si le nombre d'éléments est inconnu. Un exemple d'utilisation:

std::vector<int> values;
int n;
while(stream >> n){
    ...do something with n...
    values.Push_back(n);
}

Cependant, vous pouvez utiliser des itérateurs sur des flux et utiliser les éléments suivants:

// Use std::vector's range constructor
std::vector<int> values(
     (std::istream_iterator<int>(stream)), // begin
     (std::istream_iterator<int>()));      // end
21
Sebastian Mach

Un autre moyen de traiter une liste d'entiers séparés par des caractères à l'aide d'un vecteur, qui est peut-être même un peu plus simpliste, ressemble davantage à ceci:

string str = "50,2,25,38,9,16";
vector<int> ints;
stringstream ss(str);
int n;
char ch;

while(ss >> n) {
    if(ss >> ch)
        ints.Push_back(n);
    else
        ints.Push_back(n);
}

de cette façon, vous pouvez d'abord dépasser les séparations de caractères (si elles existent), puis revenir par défaut à la capture des entiers et à leur ajout à la liste s'ils ne le font pas (AKA à la fin de la liste)

3
Thacious

je ne sais pas si vous trouvez la réponse à votre question mise à jour ou non. si vous ne le faites pas, vous pouvez facilement le faire par le code

for (string::iterator it = num.begin(); it != num.end(); ++it) {
    if (*it == ',') {
        *it = ' ';
    }
    else continue;
}

ce code supprime tous vos deux-points et les remplace par l'espace. alors vous pouvez le faire normalement

2
Duc Nguyen