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

Langage C++ Discussion :

Gros souci de getline


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 5
    Points : 10
    Points
    10
    Par défaut Gros souci de getline
    Sujet racoleur, je vous l'accorde !

    Bon voilà, je me demandais tout simplement ce qu'il se passait avec une section de mon code. Il s'agit d'une ébauche (surtout un moyen d'apprendre) de moteur de jeu 2D, en C++, avec SFML.

    La partie qui pose problème concerne le stockage du schéma de la tilemap en mémoire.
    J'avais jusque maintenant suivi [ame="http://www.youtube.com/watch?v=NdOY8kuk4Ds&feature=player_embedded"]ce[/ame] très bon tuto de tile mapping, et tout fonctionnait parfaitement ; puis j'ai cherché à ajouter quelques fonctionnalités (booléen de collision, infos sur la taille des tiles et du niveau, ...) à mon programme, en m'inspirant d'un autre.

    C'était pour le contexte.

    J'ai un problème que je ne comprends pas tout à fait puisqu'à un moment donné, tout fonctionnait pas trop mal et d'un coup, pouet.
    Tout d'abord, le code. Un peu d'indulgence, je suis débutant... Par contre je suis friand de bons conseils !

    Le fichier .cpp en question :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    #include "Map.h"
     
     
    Map::Map() : m_tiles(), m_map(), m_tileSet() {
     
    }
     
     
    void Map::init(const char* fichierNiveau)
    {
        m_map.tmpMap.clear();
        m_map.mapSchema.clear();
        std::ifstream niveau(fichierNiveau);
     
        if (!niveau.is_open())
            std::cout << "Le fichier n'a pu s'ouvrir";
        else
        {
            char tmp[50] = {'\0'};
     
            do
            {
                niveau >> tmp;
     
                if (strcmp(tmp, "#tileset") == 0)
                    loadTileSet(niveau, tmp);
     
                else if (strcmp(tmp, "#map") == 0)
                {
                    niveau >> m_map.nbTiles.x >> m_map.nbTiles.y;
                    std::cout << m_map.nbTiles.x << " " << m_map.nbTiles.y << std::endl;
                    std::string strTmp, value;
                    std::getline(niveau, strTmp);
                    std::cout << "!" << strTmp << "!" << std::endl;
                    std::stringstream stream(strTmp);
     
                    while (std::getline(stream, value, ' '))
                    {
                        if (value.length() > 0)
                        {
                            std::cout << "!!" << value << "!!" << std::endl;
                            std::string xx = value.substr(0, value.find(','));
                            std::string yy = value.substr(value.find(',') + 1);
     
     
                            int x, y, i, j;
     
                            for (i = 0; i < xx.length(); i++)
                            {
                                if (!isdigit(xx[i]))
                                    break;
                            }
     
                            for (j = 0; j < yy.length(); j++)
                            {
                                if (!isdigit(yy[j]))
                                    break;
                            }
     
                            x = (i == xx.length() ? atoi(xx.c_str()) : -1);
                            y = (j == yy.length() ? atoi(yy.c_str()) : -1);
     
                            m_map.tmpMap.push_back(sf::Vector2i(x, y));
                        }
                    }
     
                    m_map.mapSchema.push_back(m_map.tmpMap);
                    m_map.tmpMap.clear();
                }
     
            } while (!strcmp(tmp, "#end") == 0);
        }
     
    }
     
    void Map::afficher(sf::RenderWindow* fenetre)
    {
        for (int i = 0; i < m_map.mapSchema.size(); i++) {
            for (int j = 0; j < m_map.mapSchema[i].size(); j++) {
                if (m_map.mapSchema[i][j].x != -1 && m_map.mapSchema[i][j].y != -1) { // Si la ligne n'est pas vide
                    m_tiles.setPosition(j * 32, i * 32); // On place le curseur au pixel en question
                    m_tiles.setTextureRect(sf::IntRect(m_map.mapSchema[i][j].x * 32, m_map.mapSchema[i][j].y * 32, 32, 32)); // On récupère le  tile
                    fenetre->draw(m_tiles);
                }
            }
        }
    }
     
    void Map::loadTileSet(std::ifstream& niveau, char* tmp)
    {
        std::cout << "init " << tmp << std::endl;
        niveau >> m_tileSet.location;
        std::cout << "Chargement de ./" << m_tileSet.location << std::endl;
        m_tileSet.tileSetTexture.loadFromFile(m_tileSet.location);
        m_tiles.setTexture(m_tileSet.tileSetTexture);
     
        niveau >> m_tileSet.nbTiles.x >> m_tileSet.nbTiles.y;
        std::cout << "Il y a " << m_tileSet.nbTiles.x << "x" << m_tileSet.nbTiles.y << " tiles" << std::endl;
     
        for (int i = 0; i < m_tileSet.nbTiles.x * m_tileSet.nbTiles.y; i++)
        {
            niveau >> tmp >> tmp;
            if (strcmp(tmp, "collision") == 0)
            {
                m_tileSet.collision.push_back(true);
                std::cout << "Tile " << i+1 << " collisionne." << std::endl;
            }
            else
            {
                m_tileSet.collision.push_back(false);
                std::cout << "Tile " << i+1 << " ne collisionne pas." << std::endl;
            }
        }
    }
     
    void Map::loadMapSchema(std::ifstream& niveau, char* tmp)
    {
     
    }
     
    Map::~Map()
    {
    }
    Le fichier level.txt
    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
    #tileset
    TileSetCouleurs.bmp
    2 2
    tile0: collision
    tile1: vide
    tile2: vide
    tile3: collision
    #map
    15 13
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1
    0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0
    #end
    Le problème se situe après le strcmp qui recherche la balise "#map". Comme vous pouvez le voir, il y a beaucoup de cout puisque j'ai mis un moment à identifier d'où venait le souci.
    Bref, en théorie, dans strTmp (que j'identifie dans le cout entre deux points d'exclamation) se retrouve stockée une ligne de mon fichier (donc "0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1 0,1"), et dans "value" (identifiée par des doubles points d'exclamation) les coordonnées du tile à charger, or, en sortie console, voilà ce que j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    init #tileset
    Chargement de ./TileSetCouleurs.bmp
    Il y a 2x2 tiles
    Tile 1 collisionne.
    Tile 2 ne collisionne pas.
    Tile 3 ne collisionne pas.
    Tile 4 collisionne.
    15 13
    !
    !
    !!
    !!
    Avec les breakpoints, j'apprends que les valeurs stockées dans strTmp et value correspondent au caractère '\r'.

    En ajoutant niveau.ignore(2), j'arrive à choper une ligne, qui s'affiche d'ailleurs à l'écran (je prends ça comme un signe que je suis pas trop loin du truc), mais rien de plus, pis, je le sens bien que c'est ultra bancal ahaha.

    Quelqu'un a une idée de quoi faire pour charger en mémoire ce fichu schéma ?

    Merci d'avance !

    Artexflow, en espérant que ce post n'est pas trop interminable, ou... juste minable.

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    pourquoi mélanger char* et std::string?
    Tu aurais moins de soucis à choisir une seule api.

    par exemple, getline(fichier, ligne) pour lire une ligne, puis getline(stream, value, ' ') pour lire les valeurs
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 5
    Points : 10
    Points
    10
    Par défaut
    Merci pour cette rapide réponse

    Alors, lorsque je passe de char tmp[50] = {'\0'} à std::string tmp, j'ai tous mes strcmp qui se mettent à hurler, m'indiquant "No matching function for call to 'strcmp'" ("int strcmp(const char *, const char *);" candidate function not viable: no blabla conversion from std::string to const char* for 1st argument).

    C'est modifiable ? J'avoue que je préfèrerais moi-même utiliser des strings !

    Tu veux dire quoi par utiliser une seule api ?

    Et pour le getline, tu verrais ? (désolé du tutoiement si ça passe pas )

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Le tutoiement est de mise, tu remarqueras que j'avais commencé

    Pour strcmp, consulte donc une référence du langage. Entre autre, il y a operator< et operator== qui marcheront bien

    pour les getline, j'imagine:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    … lire_donnees(){
    	ifstream fs("fichier.txt");
    	string line;
    	while(getline(fs, line)) {
    		istringstream iss(line);
    		string token
    		while(getline(iss, token, ' ')) {
    			//ce que tu veux
    		}
    	}
    	return}
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Le soucis est que tu enchaines >> puis un getline et il reste au moins un '\n', voire un '\r\n' après la chose tu tu as extraite avec >>.
    Il faut faire un ignore pour finir la purge.

    Je copie-colle un point de FAQ en attente d'intégration dans la FAQ qui traite le sujet:

    Citation Envoyé par Luc Hermitte Voir le message
    Pourquoi std::getline ne lit rien, et qu'il faille l'exécuter deux fois pour que la ligne soit lue?
    Si vous constatez ce problème, il est fort probable que vous venez d'appeler "std::getline(std::cin)" juste après une lecture sur le flux avec l'opérateur d'extraction: "std::cin >>". (c'est parfaitement valable avec les flux fichiers également)

    Ce que vous observez est normal. L'opérateur d'extraction (>>) consomme ce qui vient sur le flux, mais il s’arrête juste avant le premier espace blanc (pas sûr du vocabulaire) ou saut de ligne -- voire encore avant selon le type de la donnée à extraire et de ce qui se trouve véritablement sur le flux (ex: l'extraction d'un int depuis "125douze").

    De fait, l'operator>> va s’arrêter avant le saut de ligne, et quand std::getline va vouloir extraire la ligne qui suit, en fait il va récupérer les caractères entre la position courante et la fin de la ligne avant de passer à la ligne suivante. Dans le cas d'une interaction avec l'utilisateur, une chaine vide sera obtenue, et le flux sera positionné à la ligne suivante. C'est pour cela qu'un double appel à std::getline fonctionne.

    " - Donc si je comprends bien il faut appeler deux fois std::getline()?"
    Seulement si vous voulez récupérer les miettes qui trainent après la dernière chose lue avec >>.
    En pratique on a le choix entre :
    - un simple std::cin.get() qui marchera uniquement si ce qui suit est un saut de ligne
    - ou purger le buffer clavier (cf entrée correspondante: http://cpp.developpez.com/faq/cpp/?p...e#SL_cin_clear) qui fonctionnera également si des miettes trainent et que l'on préfère les ignorer.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

Discussions similaires

  1. [XPATH] Gros soucis de template...
    Par luta dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 16/02/2006, 12h48
  2. interface à concevoir toute simple et gros soucis
    Par skystef dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 02/02/2006, 16h31
  3. [Visual Studio 2003] J'ai un très gros souci !
    Par bart64 dans le forum EDI/Outils
    Réponses: 2
    Dernier message: 18/11/2005, 15h01
  4. [C#][Visual C# Express] Gros souci avec Excel
    Par poullos dans le forum EDI/Outils
    Réponses: 7
    Dernier message: 18/11/2005, 13h15
  5. Gros soucis avec pgaccess et postgresql
    Par Missvan dans le forum PostgreSQL
    Réponses: 9
    Dernier message: 13/04/2004, 16h16

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