6
votes

Analyser uniquement des nombres d'Istream en C ++

J'ai un tas de fichiers d'entrée qui ressemblent aux éléments suivants: xxx

Je dois écrire une fonction qui analyse un chiffre un chiffre à la fois. J'ai donc besoin de pouvoir être capable de Séparez l'entrée par chiffres, par exemple: 8, puis 7, puis 15, puis 0, une autre 0, ainsi de suite.

La seule façon dont j'ai pensé jusqu'à présent est d'utiliser Istream.get () Ce qui renvoie le code ASCII du caractère suivant, que je peux reconvertir en son format de caractère en le jettant en caractères. Ensuite, je vérifiais si le personnage était un nombre ou non (les supports sont ignorés) mais de cette façon, tous les numéros de chiffres doubles (ou triple) ne sont que des chiffres à la fois.

Qu'est-ce que Soyez le meilleur moyen d'y parvenir?

Au fait, je dois utiliser Istream. Cela fait partie de la spécification que je ne suis pas autorisé à changer

merci


4 commentaires

Y a-t-il quelque chose de mal à lire des chiffres doubles ou triple chiffres un personnage à la fois? Tout ce que vous avez à faire est de multiplier le nombre lu jusqu'à présent de 10, puis ajoutez la valeur du chiffre suivant. Mettez cela dans une boucle et vous avez terminé.


Merci John, c'est fondamentalement la façon manuelle de le faire, j'espérais qu'il existerait quelque part dans STL quelque chose qui m'aiderait à faire cela beaucoup plus agréable!


Eh bien, vous pourriez gâcher Aruond avec Istream :: Unget qui retourne le dernier caractère de lecture à la chaîne. De cette façon, vous pourriez contester le premier chiffre, puis utiliser >>. Mais franchement, la manière manuelle est la bonne voie.


Ou, puisque votre entrée semble assez régulière, vous pouvez lire le punicateur en variables factices. Quelque chose comme in >> lparen >> Num1 >> virgule1 >> Num2 >> virgule2 >> Num3 >> Rparen; Où LPAREN, etc. sont déclarés Char. Mais ce code est assez fragile, je le ferais de la manière manuelle.


5 Réponses :


3
votes

Voici quelques codes, vous pouvez vous adapter pour répondre à vos besoins précis

for (;;)
{
  int ch = in.get();
  if (ch == EOF)
    break;
  if (isdigit(ch))
  {
    int val = ch - '0';
    for (;;)
    {
      ch = in.get();
      if (!isdigit(ch))
        break;
      val *= 10;
      val += ch - '0';
    }
    // do something with val
  }
}


2 commentaires

Merci John! Ce code a l'air un peu plus gentil que la solution Nawaz ', je pense que j'aime ça un peu plus, mais je vais devoir tester les deux versions pour me décider


En fait, je pense qu'ils sont très similaires. Ils ignorent tous les deux la ponctuation. La décision que vous devez faire est de savoir si vous allez essayer de lire et de valider la ponctuation. C'est évidemment plus complexe. J'ai posté le code ci-dessus parce que je pensais que vous ne saviez pas comment calculer une valeur entière en lisant un personnage à la fois. Mais je peux voir maintenant que j'avais tort dans ça.



2
votes

Essayez de lire un numéro. Si cela échoue, Effacer l'état d'erreur et essayez de lire un char (et ignorez-le). Répétez ces deux étapes jusqu'à ce que la lecture d'un caractère échoue, auquel cas vous êtes chez EOF ou une défaillance réelle.

Il pourrait être optimisé en reconnaissant ')' puis de lire jusqu'à '('.

Mais je ne pense pas que ça vaut la peine.

acclamations et hth.,


0 commentaires

7
votes

Ceci est une solution: xxx pré>

entrée: p> xxx pré>

sortie: p> xxx pré>

Démo en ligne: http://ideone.com/lwx9y p>

dans le ci-dessus, vous devez remplacer std :: Cin code> avec le flux de fichier après avoir ouvert le fichier avec succès, comme suit: p> xxx pré>

ici, VINTS code> est un vecteur qui contient tous les entiers. Vous souhaitez travailler avec VINTS code> pour faire quelque chose d'utile. En outre, vous pouvez l'utiliser où int * code> est attendu comme suit: p>

void f(int *integers, size_t count) {}

f(&vints[0], vints.size()); //call a function which expects `int*`.


9 commentaires

Ce code modifie le flux de sorte qu'il considère tous les non-chiffres comme espaces! Je ne sais pas si je suis impressionné ou non. Semble un peu rapide et sale pour moi.


Merci pour cela! va le tester bientôt. BTW, le fichier est lu comme entrée standard, donc pas besoin d'ouvrir le fichier :)


En fait, je pense que je suis d'accord avec John à ce sujet, je ne sais pas si j'aime l'idée de modifier le flux, et de devoir déclarer une structure juste pour atteindre cette tâche relativement simple, semble un peu survenue par rapport à la méthode de John!


@Arvin: Quel est le problème avec la fourniture de votre propre local au flux? Pourquoi la fonction IMBUE () existe en premier lieu si cela ne permet pas de changer les programmeurs de changer les paramètres régionaux? En outre, je me demande si le problème était si simple tâche , alors pourquoi l'avez-vous demandé en premier lieu? : - /


@Nawaz: une question rapide. Vous pouvez adapter le code ci-dessus pour gérer les numéros signés? Vraisemblablement, vous ajouteriez '+' et '-' à votre table comme ctype_base :: punct. Ou le code Istream gère-t-il automatiquement la signature?


Remarque: Sur certains systèmes Si vous immettez un flux de fichiers après avoir été ouvert, Import est ignoré. Ainsi, vous devez imprégner le flux avant de l'ouvrir.


@John: Cette solution a bien sûr une certaine limitation, qu'elle ne fonctionnera qu'avec des entiers non négatifs.


@Martin: Oui. Je savais que, mais je n'ai pas mentionné dans ma réponse pour rendre la solution simple, et parce que je n'ai vu aucun système pour le moment où cela échouerait.


Hmm oui tu as raison, je suppose qu'il n'y a rien de mal à cela que mon être mal à l'aise en utilisant des locaux depuis que je ne les connais pas avec eux. La raison pour laquelle je pose une question était parce que je suis une novice C ++, donc je ne suis pas encore en mesure de gérer des tâches simples comme celles-ci (c'est simple à mes fins car je n'ai rien à valider). Je vais regarder dans les locaux et Import () bientôt pour voir s'ils sont assez faciles à comprendre!



2
votes

Une autre solution: xxx


0 commentaires

1
votes
void main()

{
    ifstream ifile("C:\\iStream.txt");
    string strLine;
    vector<double> vecValue;    //store the datas
    while(getline(ifile,strLine)){
        if(strLine.size()==0)
            continue;
        int iPos=0;
        while((iPos=getFirstPos(strLine))!=string::npos)
            strLine[iPos]=' ';
        istringstream iStream(strLine);
        double dValue=0;
        while(iStream>>dValue)
            vecValue.push_back(dValue);
    }
    //output the result!
    vector<double>::iterator it;
    for (it=vecValue.begin(); it!=vecValue.end()  ; ++it){
        cout<<setprecision(3)<<*it<<endl;
    }
}

0 commentaires