Menu

[C] Problème avec sscanf [Résolu/Fermé]

Messages postés
1197
Date d'inscription
jeudi 19 février 2009
Statut
Membre
Dernière intervention
5 juillet 2015
- - Dernière réponse : Bakux
Messages postés
1197
Date d'inscription
jeudi 19 février 2009
Statut
Membre
Dernière intervention
5 juillet 2015
- 3 juin 2012 à 18:10
Bonjour,

J'ai un petit problème avec la fonction sscanf. Il ne m'attribue pas la bonne valeur.

Je m'explique :

J'ai un fichier externe contenant :

0,0,1
1,0,1
2,0,1
3,0,1
4,0,0
5,0,0
6,0,0
7,0,0
8,0,1
9,0,1
10,0,1
11,0,1


Je le récupère avec mon programme par :

 FILE* fichier = NULL;
fichier = fopen("file.ju", "r");


Je lis à l'intérieur :

while (fgets(chaine, 200, fichier) != NULL) // On lit le fichier tant qu'on ne reçoit pas d'erreur (NULL)
        {
sscanf(chaine, "%d, %d, %d",&ix, &iy, &iz);
printf("ix : %d iy : %d iz : %d \n",ix, iy, iz);

Et je récupère grâce à sscanf les 3 valeurs que j'attribue à ix, iy, iz.

Mais ce qui apparaît dans le printf n'est pas du tout mon fichier ! :
ix : 0 iy : 0 iz : 1 
ix : 1 iy : 0 iz : 1 
ix : 2 iy : 0 iz : 1 
ix : 3 iy : 0 iz : 1 
ix : 4 iy : 0 iz : 0 
ix : 5 iy : 0 iz : 0 
ix : 6 iy : 0 iz : 0 
ix : 7 iy : 0 iz : 0 
ix : 8 iy : 0 iz : 1 
ix : 9 iy : 0 iz : 1 
ix : 10 iy : 0 iz : 741354544 
ix : 11 iy : 0 iz : 741354545 


Une solution ?
Afficher la suite 

9 réponses

Meilleure réponse
1
Merci
char chaine[] = "";
Grosse erreur... Ceci ne réserve qu'un octet pour ta chaine, (le 0 final).
Chaque fois que tu fais fgets et que tu écris dans 'chaine', ça déborde sur d'autres variables... Ça explique bien des choses.
Puisque tu autorises ton fgets à lire jusqu'à 200 caractères, il faut en réserver au moins 200 :
char chaine[201] = ""; (je compte 1 de plus parce que je ne sais jamais si le 0 final est compté ou pas dans les 200 du fgets.
De plus, pour scanner des ix et iy qui sont des long, il me semble qu'il faut utiliser %ld et non pas simplement %d.

Dire « Merci » 1

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 46924 internautes nous ont dit merci ce mois-ci

fiddy
Messages postés
11137
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
18 octobre 2016
1584 -
je compte 1 de plus parce que je ne sais jamais si le 0 final est compté ou pas dans les 200 du fgets.
Oui il est compté dedans. fgets lira 199 caractères et mettre en 200ème position le '\0' (si les caractères EOF ou '\n' n'ont pas été lus avant bien sûr).
De plus, pour scanner des ix et iy qui sont des long, il me semble qu'il faut utiliser %ld et non pas simplement %d.
Je confirme.
Utilisateur anonyme -
Merci de ces précisions, je pratique rarement le C.
0
Merci
Bonjour

C'est marrant, le codage en mémoire de 741354544 est le même que ',0,0' et celui de 741354545 le même que ',0,1' - en big endian.
Tu as bien vérifié le contenu de ton fichier de départ ?
Comment sont déclarées tes variables ix,iy,iz et chaine ?
Messages postés
1197
Date d'inscription
jeudi 19 février 2009
Statut
Membre
Dernière intervention
5 juillet 2015
146
0
Merci
Le fichier est OK, et je déclare les variables comme ceci :

    long  ix = 0,  iy = 0;
    int iz = 0;
    char chaine[] = "";
Messages postés
1197
Date d'inscription
jeudi 19 février 2009
Statut
Membre
Dernière intervention
5 juillet 2015
146
0
Merci
En effet, le problème venait du chaîne, mais maintenant le programme se referme immédiatement dès son ouverture :

Process returned 3 <0x3>
fiddy
Messages postés
11137
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
18 octobre 2016
1584 -
Faudrait que tu repostes ton code en tenant compte de nos remarque car là on est un peu aveugle.
As-tu bien mis un "system("pause");" (si t'es sous windows) avant ton return 0; final ?
Bakux
Messages postés
1197
Date d'inscription
jeudi 19 février 2009
Statut
Membre
Dernière intervention
5 juillet 2015
146 -
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <SDL.h>
#include <SDL_image.h> /* Inclusion du header de SDL_image (adapter le dossier au besoin) */

#define TAILLE_BLOC         34 // Taille d'un bloc (carré) en pixels
#define NB_BLOCS_LARGEUR    12
#define NB_BLOCS_HAUTEUR    12
#define LARGEUR_FENETRE     TAILLE_BLOC * NB_BLOCS_LARGEUR
#define HAUTEUR_FENETRE     TAILLE_BLOC * NB_BLOCS_HAUTEUR


int main(int argc, char *argv[])
{
    SDL_Surface *screen = NULL, *mario = NULL, *back = NULL, *surf = NULL, *objet = NULL;
    SDL_Rect positionMario, positionBloc;
    SDL_Event event;
    int quit = 1;
    int o = 0;
    long  ix = 0,  iy = 0;
    int iz = 0;
    char chaine[21] = "";
    char bloc[1000][1000];

    SDL_Init(SDL_INIT_VIDEO);

    positionMario.x = 34;
    positionMario.y = 34;

    screen = SDL_SetVideoMode(LARGEUR_FENETRE, HAUTEUR_FENETRE, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
    SDL_WM_SetCaption("Mario Sokoban", NULL);

    SDL_EnableKeyRepeat(100,100);

    SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));

    mario = IMG_Load("mario_bas.gif");

        FILE* fichier = NULL;

    fichier = fopen("niveau2.lvl", "r");

    while (fgets(chaine, 20, fichier) != NULL) // On lit le fichier tant qu'on ne reçoit pas d'erreur (NULL)
        {



   sscanf(chaine, "%ld, %ld, %d",&ix, &iy, &iz);
//printf("ix : %d iy : %d iz : %d \n",ix, iy, iz);
            ix *= TAILLE_BLOC;
            iy *= TAILLE_BLOC;

//printf("ix : %d, iy : %d, iz : %d \n",ix, iy, iz);

if(iz>=0 && iz<=3){
            switch(iz){
                case 0:
                    surf = IMG_Load("sol.jpg");
                    bloc[ix][iy]= 0;
                break;

                case 1:
                    surf = IMG_Load("mur.jpg");
                  bloc[ix][iy]= 1;
                break;

                case 2:
                    surf = IMG_Load("caisse.jpg");
                    bloc[ix][iy]= 2;
                break;

                case 3:
                    o = 1;
                    surf = IMG_Load("sol.jpg");
                    bloc[ix][iy]= 3;
                break;

            }

            }else{

          //  perror("iz : %d", iz);

}


            positionBloc.x = ix;
            positionBloc.y = iy;


            SDL_BlitSurface(surf, NULL, screen, &positionBloc);

          if(o){
            objet = IMG_Load("objectif.png");
            SDL_SetColorKey(objet, SDL_SRCCOLORKEY, SDL_MapRGB(screen->format, 255,255,255));
            SDL_BlitSurface(objet, NULL, screen, &positionBloc);

            }


          SDL_Flip(screen);



            o = 0;
        }

        fclose(fichier);

    while(quit){

    SDL_WaitEvent(&event);

        switch(event.type){



            case SDL_QUIT:
                quit = 0;
            break;

            case SDL_KEYDOWN:

            back = IMG_Load("sol.jpg");
            SDL_BlitSurface(back, NULL, screen, &positionMario);
            SDL_Flip(screen);

                switch(event.key.keysym.sym){

                    case SDLK_DOWN:
                        if(positionMario.y < (HAUTEUR_FENETRE - TAILLE_BLOC) && bloc[positionMario.x][positionMario.y+TAILLE_BLOC] != 1){
                        positionMario.y += TAILLE_BLOC;
                         mario = IMG_Load("mario_bas.gif");
                        }
                    break;


                    case SDLK_UP:
                         if(positionMario.y >= TAILLE_BLOC && bloc[positionMario.x][positionMario.y-TAILLE_BLOC] != 1){
                             positionMario.y -= TAILLE_BLOC;
                         mario = IMG_Load("mario_haut.gif");
                        }
                    break;

                    case SDLK_LEFT:
                        if(positionMario.x >= (TAILLE_BLOC) && bloc[positionMario.x-TAILLE_BLOC][positionMario.y] != 1){
                        positionMario.x -= TAILLE_BLOC;
                         mario = IMG_Load("mario_gauche.gif");
                        }
                    break;

                    case SDLK_RIGHT:
                        if(positionMario.x < (LARGEUR_FENETRE - TAILLE_BLOC) && bloc[positionMario.x+TAILLE_BLOC][positionMario.y] != 1){
                        positionMario.x += TAILLE_BLOC;
                         mario = IMG_Load("mario_droite.gif");
                        }
                    break;

                    case SDLK_ESCAPE:
                        quit = 0;
                    break;

                }
            break;
        }
    printf("Etat Mario : %d \n", bloc[positionMario.x][positionMario.y]);
    //SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
    SDL_BlitSurface(mario, NULL, screen, &positionMario);
    SDL_Flip(screen);

    }

    SDL_Quit();


    return 0;
}
0
Merci
Dans le bout de programme que tu nous as montré, il n'y a rien pour le faire attendre. Il a fini son travail, il s'arrête, où est le problème ?
Quant au Process returned 3 , c'est sans doute que tu n'as mis aucune instruction return à la fin de ton main. Ajoute un return 0; avant de quitter le main.
0
Merci
Personnellement, je jette l'éponge. Il s'agit probablement d'un problème d'utilisation de la bibliothèque SDL, que je ne connais pas du tout. Bonne chance
Messages postés
11137
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
18 octobre 2016
1584
0
Merci
Pourquoi mélanger les entêtes C++ et de C ?
Au final c'est du C ou du C++ que tu souhaites faire ?
sscanf(chaine, "%ld, %ld, %d",&ix, &iy, &iz);
Ok pour le sscanf, mais il faut faire pareil pour le printf.

Tu n'as pas tenu compte de ma remarque : system("pause"); avant le return 0; final (si t'es sous windows) sinon indique nous ton OS.
Messages postés
1197
Date d'inscription
jeudi 19 février 2009
Statut
Membre
Dernière intervention
5 juillet 2015
146
0
Merci
Le system("pause"); ne sert à rien, j'ai une boucle infini avec quit, qui sort de la boucle dès l'appui sur Echap.

Ensuite le printf est en commentaire, donc useless aussi, et les entêtes sont bien en C, ce que je souhaite faire.

OS : Windows
fiddy
Messages postés
11137
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
18 octobre 2016
1584 -
Le system("pause"); ne sert à rien, j'ai une boucle infini avec quit, qui sort de la boucle dès l'appui sur Echap.
Beh justement, là la fenêtre ne se refermera pas après avoir appuyé sur Echap...
Ou alors, précise ce que tu souhaites faire en détail. Car à part "ça boucle en infini et la fenêtre se referme en appuyant sur Echap", on ne sait pas grand chose d'autre.

Ensuite le printf est en commentaire, donc useless aussi,
Certes. Je te disais ça car c'est mieux qu'un commentaire soit juste. Le jour où tu enlèveras le commentaire, ça sera bon. En plus ça coûte rien de rajouter un %ld. Enfin c'est toi qui vois.

et les entêtes sont bien en C, ce que je souhaite faire.
Non...
iostream c'est C++, string c'est C++ (à ne pas confondre avec string.h). Le mélange d'entête est à proscrire. C'est loin d'être useless.

En plus ton code est dur à comprendre. Il n'y a pas de fonctions. Les fonctions sont justement là pour faciliter la lecture d'un code.
Messages postés
1197
Date d'inscription
jeudi 19 février 2009
Statut
Membre
Dernière intervention
5 juillet 2015
146
0
Merci
Le problème venait d'un array qui n'était pas assez grand, et merci pour les conseils ;)
fiddy
Messages postés
11137
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
18 octobre 2016
1584 -
Ok. Il n'empêche que tu as également des problèmes là où je t'ai signalé ;-)))).
Bakux
Messages postés
1197
Date d'inscription
jeudi 19 février 2009
Statut
Membre
Dernière intervention
5 juillet 2015
146 -
Ouaip, j'ai tout mis en plusieurs fonctions, rétablis le %ld au lieu des %d, vérifier les entêtes ;)