[C] Problème avec sscanf
Résolu
Bakux
Messages postés
1195
Date d'inscription
Statut
Membre
Dernière intervention
-
Bakux Messages postés 1195 Date d'inscription Statut Membre Dernière intervention -
Bakux Messages postés 1195 Date d'inscription Statut Membre Dernière intervention -
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 :
Je le récupère avec mon programme par :
Je lis à l'intérieur :
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 ! :
Une solution ?
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
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.
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.
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 ?
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 ?
Le fichier est OK, et je déclare les variables comme ceci :
long ix = 0, iy = 0; int iz = 0; char chaine[] = "";
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>
#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; }
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.
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.
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
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.
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.
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
Ensuite le printf est en commentaire, donc useless aussi, et les entêtes sont bien en C, ce que je souhaite faire.
OS : Windows
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.
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.
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.