IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

probl�me avec std::string:find()


Sujet :

SL & STL C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre confirm�
    Homme Profil pro
    D�veloppeur de jeux vid�o
    Inscrit en
    Juin 2006
    Messages
    122
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 41
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur de jeux vid�o

    Informations forums :
    Inscription : Juin 2006
    Messages : 122
    Par d�faut probl�me avec std::string:find()
    Hoy!

    Un probl�me plus ou moins simple que je n'arrive pas vraiment � r�soudre.

    J'ai �cris une s�rie de fonction afin de pouvoir r�cup�rer des param�tres d'une chaine format�e. Ces param�tre peuvent �tre des float, des bool, des string, etc. Les chaines sont stock�es dans un fichier et s�par�es par un saut de ligne. Je sais quel est le type de tel param�tre � telle endroit.

    J'ai �cris quelques fonction pour r�cup�rer ses param�tres, que voici :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    	// J'ouvre le fichier qui contient
    	std::stringstream URL;
    	URL << "game/stage" << stage_number;  // Stage number est int, d'où l'utilisation du stringstream
    	std::ifstream file(URL.str().c_str());
     
    	std::string data; // Le string qui va me servir à stocker ma chaine
     
    	// Je récupère la chaine d'un fichier que je parcours avec std::getline
    	while(std::getline(file, data))
    	{
    		std::string label;
    		int pos = 0; // Le curseur qui va me permettre de parcourir ma chaine
    		pos = data.find(":"); // On recupère le premier paramètre, séparé par un ":"
    		label = data.substr(0, data.find(":")); // stockage du premier parametre
    		// En réalité, je fais un switch avec le label récupéré, via un std::map, et pour chaque label, je traite la ligne différement. Je met ici les lignes où il y a un bug
     
    		std::string ennemy_name;
    		float time, x, y, angle;
    		ennemy_name = GetParameter(pos, data);  // On récupère le parametre
    		NextParameter(pos, data);  // On passe au suivant
    		time = static_cast<float>(std::atof(GetParameter(pos, data).c_str()));  // On récpère le parametre
    		NextParameter(pos, data); // On passe au suivant, etc...
    		x = static_cast<float>(std::atof(GetParameter(pos, data).c_str()));
    		NextParameter(pos, data);
    		y = static_cast<float>(std::atof(GetParameter(pos, data).c_str()));
    		NextParameter(pos, data);
    		angle = static_cast<float>(std::atof(GetLastParameter(pos, data).c_str())); // On récupère le dernier paramètre, délimité par le caractère "saut de ligne"
     
    		std::cout << "Ennemy loaded, pos = " << pos <<", ennemy_name = " << ennemy_name << ", temps = " << time << ", x = " << x << ", y = " << y << ", angle = " << angle << std::endl; // Affichage du résultat
    	}
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
     
    //  Fonction pour placer le curseur sur le paramètre suivant
    void Stage::NextParameter(int &pos, std::string &data)
    {
    	int temp = pos + 1;
    	pos = data.find('|', temp);
    	std::cout << "pos = " << pos << std::endl;
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    // Fonction pour lire le paramètre actuel, délimité par un "|"
    std::string Stage::GetParameter(int pos, std::string &data)
    {
    	return data.substr(pos+1, data.find('|') - pos - 1);
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
     
    // Fonction pour lire le dernier paramètre, délimité par un "saut de ligne"
    std::string Stage::GetLastParameter(int pos, std::string &data)
    {
    	return data.substr(pos+1, data.find('\n') - pos - 1);
    }
    Voila, � partir de ce code, je lis donc mon fichier. Dans mon fichier, j'ai ceci :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
     
    ENNEMY:megathron|7.0|250.0|-200.0|270.0
    ENNEMY:megathron|8.0|100.0|-200.0|270.0
    ENNEMY:megathron|9.0|500.0|-200.0|270.0
    Et mes std::cout m'affiche ceci :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    pos = 16
    pos = 20
    pos = 26
    pos = -1   // Problème ! La position devrait être à 30 et des poussières
    Ennemy loaded, pos = -1, ennemy_name = megathron, temps = 7, x = 250, y = -200, angle = 0
    pos = 16
    pos = 20
    pos = 26
    pos = -1   // Pareil
    Ennemy loaded, pos = -1, ennemy_name = megathron, temps = 8, x = 100, y = -200, angle = 0
    pos = 16
    pos = 20
    pos = 26
    pos = -1  // Pareil
    Ennemy loaded, pos = -1, ennemy_name = megathron, temps = 9, x = 500, y = -200, angle = 0
    Le bug viens sur les derniers parametres, qui se retrouve avec une position -1. Si jme souviens bien, c'est la valeur de retour lorsque le std::string::find() ne trouve pas le caract�re souhait�, pourtant, � cette position, le caract�re est pr�sent dans les lignes qui suivent.

    Si vous avez une id�e, je suis preneur.

    (Au passage, si vous avez une proposition � me faire pour am�liorer ma r�cup�ration de param�tre, par un autre objet de la biblioth�que standard ou quoi, je suis aussi preneur. :p)

  2. #2
    Membre confirm�
    Homme Profil pro
    D�veloppeur de jeux vid�o
    Inscrit en
    Juin 2006
    Messages
    122
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 41
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur de jeux vid�o

    Informations forums :
    Inscription : Juin 2006
    Messages : 122
    Par d�faut
    Bon en fait j'ai foir� le formatage de mon fichier lorsque je l'ai �cris, j'ai corrig� �a remarche..

    Donc ya plus de probl�me.

    Par contre, si quelqu'un connais toujours une solutions plus �l�gante que ce que j'ai fait, je suis toujours preneur.

  3. #3
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    J'ai, quelque part, l'impression que tu cherches midi � quatorze heures...

    en effet, si une ligne est d'office compos�e sous la forme de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    string<pipe>float<pipe>float<pipe>float<pipe>float
    tu peux te "contenter" de r�cup�rer le tout depuis un stringstream presque d'une seule traite, sous la forme de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    while(std::getline(file,data)) /* la boucle de lecture */
    {
        /*zou, travaillons avec un stringstream */
        std::stringstream ss(data);
        /* il nous faut:
               - une chaine (premiers parametre)
               - 4 réels (4 dernier parametre)
               - un caractère(le séparateur)
         */
        std::string name;
        float p1;
        float p2;
        float p3;
        float p4;
        char c;
        /* la chaine nous embête, récupérons la en premier */
        if(!std::getline(ss,name,'|') )
            throw BadFormat("string");
        /* puis, récupérons les réels (vérification inside)*/
        if(! (ss>>p1>>c>>p2>>p3>>p4) )
            throw BadFormat("v1|v2|v3|v4");
        /* suite du traitement (sans doute la création d'un objet et l'ajout
         * dans la structure qui les gère)
         */
     
    }
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  4. #4
    Membre confirm�
    Homme Profil pro
    D�veloppeur de jeux vid�o
    Inscrit en
    Juin 2006
    Messages
    122
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 41
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur de jeux vid�o

    Informations forums :
    Inscription : Juin 2006
    Messages : 122
    Par d�faut
    Je me suis tat� � utiliser le stringstream avec getline() car le premier caract�re s�parateur de ma chaine est volontairement un : pour que, via le switch, je sache de quel genre d'objet et donc de quel genre de param�tres j'ai � faire. :/

    Donc c'est plus sous la forme
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    string<pipe1>float<pipe2>float<pipe2>float<pipe2>float
    Avec un algo du genre :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    - création du stringstream data;
    while(std::getline(file, data))
    {
        - récupération du premier paramètre limité par ":"
        switch(premier parametre)
        {
            case 1:
                - création des variables de stockage;
                - récupération des paramètre en ignorant le premier;
                - création de l'objet;
                - break;
            case 2:
                - rebelotte avec d'autres paramètres
                - break;
        }
    }
    Je vois mal comment demander au getline d'ignorer le premier param�tre une fois r�cup�r�. :\

  5. #5
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Citation Envoy� par Spidyy Voir le message
    Je vois mal comment demander au getline d'ignorer le premier param�tre une fois r�cup�r�. :\
    Exactement comme je l'ai indiqu�: en le passant en troisi�me param�tre de la commande getline

    Fais attention au fait qu'une chaine de caract�res ne peut pas servir comme valeur pour un test � choix multiple (switch... case): seule les valeurs num�riques enti�res peuvent servir

    De plus, les chaines de caract�res ne sont r�ellement pas ce qui se fait de plus efficace en terme de temps de comparaison: la comparaison se fait "caract�re par caract�re" jusqu'� en trouver un qui varie d'une chaine � l'autre.

    Cela signifie que, sur une chaine commen�ant par A et l'autre par z, cela peut �tre rapide, mais, si deux chaines sont � ce point semblables que seul le dernier caract�re est diff�rent, la comparaison prendra �norm�ment de temps

    L' *id�al* dans ce cas est peut �tre de travailler avec une �num�ration qui aplanira toutes ces difficult�s:
    Tu peux envisager une �num�ration proche de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    enum eMyTypeSelect
    {
        tsMonPremierType = 1,
        tsMonDeuxiemeType,
        tsMonTroisiemeType,
        tsMonQuatriemeType
        /* , ... */
    };
    /* et, du coup, passer sous une forme proche de */
    while(std::getline(file,data) );
    {
        std::stringstream ss(data);
        eMyTypeSelect select;
        char c;
        while( (ss>>select>>c) )
        {
             swith(select)
                 case tsMonPremierType:
                      /* blabla */
                      break;
                 case tsMonDeuxiemeType:
                      /* blabla */
                      break;
                 case tsMonTroisiemeType:
                      /* blabla */
                      break
                 /*...*/
                 default:
                     throw BadFormat("TypeInconnu")
        }
    }
    o� "blabla" pourrait facilement �tre envisag� sous la forme de fonctions proches de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    TypeDeBase* createTypeReel(std::istream &ss)
    {
        type valeur_1;
        type valeur_2;
        type valeur_3;
        /*...*/
        type valeur_n;
        char c;
        if(!(ss>>valeur_1>>c>>valeur_2>>c>>valeur_3>>/*...*/>>valeur_n))
            throw BadFormat("v1|v2|v3/*...|*/vn");
        return new TypeReel(valeur_1,valeur_2,valeur_3/*,...*/,valeur_n);
    }
    (en consid�rant ici que les types r�els h�ritent tous d'un type de base commun et que tu les g�re de mani�re statique comme s'ils �taient de ce type commun)

    Bien sur, tu en viendrais � cr�er une fonction par type r�el qu'il te faut cr�er
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  6. #6
    Membre confirm�
    Homme Profil pro
    D�veloppeur de jeux vid�o
    Inscrit en
    Juin 2006
    Messages
    122
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 41
    Localisation : France

    Informations professionnelles :
    Activit� : D�veloppeur de jeux vid�o

    Informations forums :
    Inscription : Juin 2006
    Messages : 122
    Par d�faut
    Le fait de faire ss>>select>>c va retirer du flux le select et le c?

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Probl�me avec std::string
    Par Gobelins dans le forum D�buter
    R�ponses: 8
    Dernier message: 03/01/2011, 08h57
  2. probl�me avec std::string
    Par haraelendil dans le forum Langage
    R�ponses: 10
    Dernier message: 25/06/2010, 18h56
  3. Probl�me avec std::string
    Par Laughing Man dans le forum C++
    R�ponses: 18
    Dernier message: 07/02/2008, 19h04
  4. Sale probl�me avec les strings et les fichiers
    Par acieroid dans le forum C++
    R�ponses: 18
    Dernier message: 26/04/2006, 09h47
  5. Probl�me avec std::Vector
    Par mister3957 dans le forum SL & STL
    R�ponses: 8
    Dernier message: 16/02/2006, 10h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo