7
votes

Ne pas lire une chaîne correctement

Je pratique la manipulation des entrées de l'utilisateur. Mon objectif est de faire entrer l'utilisateur une ligne d'entiers séparés par l'espace (""), de les lire comme des entiers, de les stocker et de les travailler plus tard. J'ai trébuché sur un problème intéressant (au moins dans mon adpinion) comme je le fais, il semble que cela ne lisait toujours pas le dernier chiffre entré par l'utilisateur. Je posterai tout le programme ici (puisqu'il y a des bibliothèques supplémentaires incluses). J'ai laissé des commentaires dans le programme

#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>

using namespace std;

int main()
{
    //this vector will store the integers
    vector<int> a;
    // this will store the user input
    string inp;
    getline(cin, inp);
    // this string will temporarily store the digits
    string tmp;
    //be sure that the reading part is okay
    cout << inp << endl;
     //until you meet something different than a digit, read char by char and add to string
     for(int i = 0; i < inp.length(); i++)
    {
        if(isdigit(inp[i]))
        {
            tmp +=inp[i];
        }
        else
        {
            // when it is not a character, turn to integer, empty string
            int value = atoi(tmp.c_str());
            a.push_back(value);
            tmp = "";
        }
    }
    // paste the entire vector of integers
    for(int i = 0; i < a.size(); i++)
    {
        cout << a[i] << endl;
    }
    return 0;
}


5 commentaires

Pour un exemple d'entrée, quelle est votre production attendue et que voyez-vous réellement?


Si j'entraîne "25 30 46", je obtiendrai 25 et 30 dans le vecteur, mais la chaîne contiendra "25 30 46"


Ahh, je pensais que tu voulais dire juste un chiffre manquant.


Je m'attends à ce qu'il y ait une erreur dans la logique, car je l'ai écrit à l'origine avec les classes de Qt (qstring, qvector, ect ..) et je le retournais en simplicité C ++ avant de poster ici -> avait toujours le même problème.


Outre le besoin actuel d'un espace supplémentaire d'espace ou d'après-boucle de TMP, vous avez le problème que les espaces consécutifs pousseront 0 valeurs dans le vecteur - je suppose que vous ne voulez pas vraiment que cela. Un moyen facile de le faire en C ++ consiste à placer la ligne dans une boucle ISTRingStream puis à la boucle (ISS> Myint). Si vous voulez vraiment vous coller à votre style de code actuel, vous pouvez tester TMP n'est pas vide avant d'utiliser ATOI dessus.


9 Réponses :


3
votes

Si la fin de la ligne est un chiffre, vous ne frappez pas le sinon code> sur la dernière itération, et que le dernier numéro n'est jamais poussé dans le vecteur code> code> . La solution la plus simple serait de reproduire la logique non chiffrée après la boucle:

int tmp;
while (ss >> tmp)
{
    ints.push_back(tmp);
}


1 commentaires

C'est correct. Une solution consiste simplement à ajouter un '' mécaniquement à la fin de la ligne avant de l'ajouter. Je vais marquer cela comme une réponse quand la minuterie me laissa moi. Merci!



1
votes

Votre programme Besoin d'une chaîne terminée par un caractère non chiffre pour fonctionner correctement. Essayez cette chaîne "1 12 14587 15" Parce que dans votre algorithme lorsque vous avez oublié le dernier espace, votre programme stocke le numéro dans la chaîne TMP mais ne l'enregistrez pas dans le vecteur. Pour corriger que vous devez ajouter un dernier push_back juste après votre première boucle.


0 commentaires

1
votes

Vous mettez à jour A code> avec une nouvelle valeur uniquement lorsque le non chiffre est trouvé. Ainsi, si vous avez la fin de la chaîne avec des chiffres, TMP code> contiendra une chaîne numérique mais vous n'allez jamais au bien-auquel devrait effectuer le push_back. Vous pouvez résoudre ce problème en ajoutant le code suivant après la boucle

if(!tmp.empty()){
    // when it is not a character, turn to integer, empty string
    int value = atoi(tmp.c_str());
    a.push_back(value);
    tmp = "";
}


0 commentaires

0
votes

Vous ne repoussez jamais votre dernière valeur. Par exemple, considérez cette entrée xxx

alors pendant que vous lisez, vous repoussez dans le premier espace. Mais vous ne poussez jamais 36 car il n'y a plus de caractères.

après la fin de votre pour () boucle Vous pouvez essayer ceci: xxx


0 commentaires

1
votes

Avant de démarrer la boucle, ajoutez un espace à la chaîne pour vous assurer de repousser le dernier numéro: inp.push_back ('')


0 commentaires

1
votes

Votre boucle est terminée après que le dernier chiffre est lu, le dernier chiffre n'est jamais tourné vers Integer. Ajoutez simplement du code après l'original pour la boucle.

for(int i = 0; i < inp.length(); i++)
{
    /* ...... */
}
// add this to read the last digit
if(tmp.length() > 0){
    int value = atoi(tmp.c_str());
    a.push_back(value);
    tmp = "";
}


0 commentaires

6
votes

Remplacez cette ligne

pour (int i = 0; i p>

par p>

for(int i = 0; i <= inp.length(); i++)


5 commentaires

HMM +1, une astuce intéressante, jamais envisagée à l'aide de l'extrémité '\ 0' comme sentinelle. Et c'est aussi parfaitement conforme. Mais cela pourrait être une bonne idée de fournir un commentaire dans le code.


@unkUnunkulu: Il est conforme à C ++ 11, cependant, en C ++ 03, je doute que c'était légal (il n'y avait aucune garantie que la chaîne était terminée). Pour être entièrement conformes, vous pouvez utiliser l'indice du résultat de l'appel C_STR .


@Matthieum., Je ne l'ai pas trouvé dans les brouillons (je le naviguai plutôt mal), mais les informations que j'ai trouvées ailleurs (CPPreference) implique que s [s.size ()] == '\ 0' < / code> est garanti. Il ne garantit pas que & s [0] ou s.data () est terminé par NULL.


@Matthieum., OK SO Selon N1577, s [S.Size ()] == '\ 0' pour const version de opérateur [] , sinon il est indéfini.


@unkUnunkulu: en C ++ 11 (§21.4.5 basic_string l'accès des éléments), s [s.size ()] est garanti d'être '\ 0 ' et ne doit pas être affecté à, il n'a pas été attribué de manière contiguë au reste des données, soit plus tard au §21.4.7.1 BASIC_String ACCESSORS Il est dit que C_STR et data doit renvoyer une plage indexable par [0, taille ()]] en temps constant ...; Je semble vous rappeler que, en C ++ 03 seulement, c_str était garanti pour terminer la nul, et je ne sais pas s'il y avait la réserve spéciale pour [] (quel à n'a pas, à la manière ... damné!)



0
votes

Lorsque le dernier chiffre du dernier numéro est stocké dans TMP, une fois que la boucle se termine parce que vous avez lu le dernier caractère de la chaîne entière. Lorsque la boucle met fin à TMP contient toujours le dernier numéro.

1) Vous pouvez convertir et ajouter le dernier numéro au vecteur après la boucle. Le dernier numéro encore disponible en TMP.

2) ou vous pouvez explicitement ajouter un caractère non chiffre à la fin de la chaîne avant la boucle.


0 commentaires

0
votes

Vous omettez l'entrée. Changez votre code pour refléter ceci:

for(int i = 0; i <= inp.length(); i++)


0 commentaires