[C] Problème avec sscanf

Résolu/Fermé
Bakux Messages postés 1195 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 5 juillet 2015 - 2 juin 2012 à 19:55
Bakux Messages postés 1195 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 ?

9 réponses

Utilisateur anonyme
2 juin 2012 à 22:08
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.
1
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
2 juin 2012 à 22:17
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.
0
Utilisateur anonyme
2 juin 2012 à 22:23
Merci de ces précisions, je pratique rarement le C.
0
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 ?
0
Bakux Messages postés 1195 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 5 juillet 2015 187
2 juin 2012 à 21:40
Le fichier est OK, et je déclare les variables comme ceci :

    long  ix = 0,  iy = 0;
    int iz = 0;
    char chaine[] = "";
0
Bakux Messages postés 1195 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 5 juillet 2015 187
2 juin 2012 à 22:25
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>
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
Modifié par fiddy le 2/06/2012 à 22:26
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 ?
0
Bakux Messages postés 1195 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 5 juillet 2015 187
2 juin 2012 à 22:30
#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

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
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
Utilisateur anonyme
2 juin 2012 à 22:34
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
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
2 juin 2012 à 23:19
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.
0
Bakux Messages postés 1195 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 5 juillet 2015 187
2 juin 2012 à 23:28
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
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
2 juin 2012 à 23:52
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.
0
Bakux Messages postés 1195 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 5 juillet 2015 187
3 juin 2012 à 08:37
Le problème venait d'un array qui n'était pas assez grand, et merci pour les conseils ;)
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 juin 2012 à 18:05
Ok. Il n'empêche que tu as également des problèmes là où je t'ai signalé ;-)))).
0
Bakux Messages postés 1195 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 5 juillet 2015 187
3 juin 2012 à 18:10
Ouaip, j'ai tout mis en plusieurs fonctions, rétablis le %ld au lieu des %d, vérifier les entêtes ;)
0