Est-ce que le commentaire est toujours à la position 27 ? non
sizeof n'est absolument pas la bonne méthode ici
méthode plus générale pour le commentaire: lire la taille du bloc commentaire (ce qui vaut pour les autres blocs aussi)
Je réitère la remarque que j'ai fait plusieurs fois, rien n'indique que l'ordre des blocs est toujours le même, le seul truc qui ne bouge pas, c'est le 1er bloc de 8 caractères indiquant le format 'Mini-PNG'
Tu as déjà toutes les réponses, chaque type de bloc a son 1er octet qui donne le type de bloc, donc le type d'info qu'il contient, et dans les 4 octets suivants la longueur des données du blocs. donc pour lire de manière générique:
lecture des octets du type de fichier ('Mini-PNG'), si OK , on peut poursuivre
lecture de l'octet suivant:
si 'H' alors boc Header qui va être de longueur 9 et dont on va lire les infos hauteur image, largeur image, et codage couleur (type de pixel)
si 'C' alors c'est un bloc commentaire, on récupère la longueur du bloc, et on lit ne nombre de caractères
si 'D' alors bloc 'Data', on lit la longueur et ce nombre de data
et on boucle pour lire le type du bloc suivant.
Tu l'appelles buffer si tu veux, mais les mots clés sont surtout "zone allouée dynamiquement" (sous-entendu, utilisation de malloc)
Rien à voir avec ta question, mais tu ne crois pas que traiter_magic_number() devrait renvoyer une information au main() ? Car si le format du fichier n'est pas correct, tu le traites de toute façon. Donc, telle qu'elle est là, cete fonction ne sert strictement à rien.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Aussi vu que je suis pas forcement un expert, merci de me dire si le code est assez bien sécurisé, pas de bug si j'ai des fichiers corrompus, pas de crash etc
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int largeur=0;
int hauteur=0;
void traiter_magic_number(FILE *fd)
{
char chaine[8 + 1];
fread(&chaine,8,1,fd);
chaine[8] = '\0';
printf("Magic number:\t%s ", chaine);
if((chaine[0]!='M')||(chaine[1]!='i')||(chaine[2]!='n')||(chaine[3]!='i')||(chaine[4]!='-')||(chaine[5]!='P')||(chaine[6]!='N')||(chaine[7]!='G'))
{
printf("erreur de format du fichier\n");
}
else
{
printf("le fichier est de format mp\n");
}
}
void afficher_commentaire(const char *data, int taille)
{
printf("- Commentaire: ");
fwrite(data, taille, 1, stdout);
printf("\n");
}
int valeur_entier(const char octets[], int taille)
{
int valeur = 0;
for (int i=0; i < taille; i++) {
valeur = (valeur << 8) | octets[i];
}
if(valeur<0)
{
valeur=256+valeur;
}
return valeur;
}
void afficher_caracteristiques(const char *data)
{
static const char *type_pixels[] = {
"0 - noir et blanc",
"1 - niveaux de gris",
"2 - palette",
"3 - couleurs 14 bits"
};
printf("largeur de l'image : %d\n",valeur_entier(data + 0, 4));
largeur=valeur_entier(data + 0, 4);
printf("hauteur de l'image : %d\n",valeur_entier(data + 4, 4));
hauteur=valeur_entier(data + 4, 4);
printf("type de pixels : %s\n",type_pixels[(int) data[8]]);
}
void afficher_image(const char *data,int lar,int hau)
{
for(int i=0; i<hau; i++)
{
int e=valeur_entier(data + i, 1);
int b[lar]={0};
for(int j=0; j<lar; j++)
{
b[lar-j-1]=e%2;
e=e/2;
if(b[lar-j-1]==1)
{
printf(" ");
}
else if(b[lar-j-1]==0)
{
printf("X");
}
}
printf("\n");
}
}
struct entete_bloc {
char type;
int taille_contenu;
};
bool traiter_entete_bloc(FILE *fd, struct entete_bloc *h)
{
char data[1 + 4];
int n=fread(&data,5,1,fd);
if (n <= 0) return false; // y en a plus
h->type = data[0];
h->taille_contenu = valeur_entier(data + 1, 4);
return true; // y en a
}
void traiter_contenu_bloc(FILE *fd, const struct entete_bloc g)
{
char data[g.taille_contenu];
fread(&data,g.taille_contenu,1,fd);
// traitement à détailler selon le type
switch (g.type) {
case 'H' :
afficher_caracteristiques(data);
break;
case 'C' :
afficher_commentaire(data, g.taille_contenu);
break;
case 'D' :
afficher_image(data,largeur,hauteur);
default:
break;
}
}
void traiter_blocs(FILE *fd)
{
while (true) {
struct entete_bloc h;
if (! traiter_entete_bloc(fd, &h)) break;
printf("bloc type %c taiile %d\n\n", h.type,h.taille_contenu);
traiter_contenu_bloc(fd, h);
}
}
void traiter_fichier(const char *chemin)
{
FILE *fd = fopen(chemin, "r");
if (fd < 0) {
perror("ouverture fichier");
exit (EXIT_FAILURE);
}
traiter_magic_number(fd);
traiter_blocs(fd);
fclose(fd);
}
int main()
{
traiter_fichier("A.mp");
return EXIT_SUCCESS;
}
- Edité par vamskhalil 17 novembre 2022 à 19:55:30
edgarjacobs bah expliques alors peut etre que je ne vois pas forcement de quoi tu parles. sinon j'ai rajouté un if else dans la fonction qui traite le magic number mais peut etre que ca ne resoud pas la problematique que tu evoques
void traiter_magic_number(FILE *fd)
{
char chaine[8 + 1];
fread(&chaine,8,1,fd);
chaine[8] = '\0';
printf("Magic number:\t%s ", chaine);
if((chaine[0]!='M')||(chaine[1]!='i')||(chaine[2]!='n')||(chaine[3]!='i')||(chaine[4]!='-')||(chaine[5]!='P')||(chaine[6]!='N')||(chaine[7]!='G'))
{
printf("erreur de format du fichier\n");
}
else
{
printf("le fichier est de format mp\n");
}
Je vous envoies la dernière version de mon code, mais j'ai quelques préoccupation sur concernant les tests de sécurité
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int largeur=0;
int hauteur=0;
bool traiter_magic_number(FILE *fd)
{
char chaine[8 + 1];
fread(&chaine,8,1,fd);
chaine[8] = '\0';
if(strcmp(chaine,"Mini-PNG")!=0)
{
return false;
}
else
{
return true;
}
}
void afficher_commentaire(const char *data, int taille)
{
printf("Commentaire: ");
fwrite(data, taille, 1, stdout);
printf("\n");
}
int valeur_entier(const char octets[], int taille)
{
int valeur = 0;
for (int i=0; i < taille; i++) {
valeur = (valeur << 8) | octets[i];
}
if(valeur<0)
{
valeur=256+valeur;
}
return valeur;
}
void afficher_caracteristiques(const char *data)
{
static const char *type_pixels[] = {
"0 - noir et blanc",
"1 - niveaux de gris",
"2 - palette",
"3 - couleurs 14 bits"
};
printf("largeur de l'image : %d\n",valeur_entier(data + 0, 4));
largeur=valeur_entier(data + 0, 4);
printf("hauteur de l'image : %d\n",valeur_entier(data + 4, 4));
hauteur=valeur_entier(data + 4, 4);
printf("type de pixels : %s\n",type_pixels[(int) data[8]]);
}
void afficher_image(const char *data,int lar,int hau)
{
for(int i=0; i<hau; i++)
{
int e=valeur_entier(data + i, 1);
int b[lar]={0};
for(int j=0; j<lar; j++)
{
b[lar-j-1]=e%2;
e=e/2;
if(b[lar-j-1]==1)
{
printf(" ");
}
else if(b[lar-j-1]==0)
{
printf("X");
}
}
printf("\n");
}
}
struct entete_bloc {
char type;
int taille_contenu;
};
bool traiter_entete_bloc(FILE *fd, struct entete_bloc *h)
{
char data[1 + 4];
int n=fread(&data,5,1,fd);
if (n <= 0) return false; // y en a plus
h->type = data[0];
h->taille_contenu = valeur_entier(data + 1, 4);
return true; // y en a
}
void traiter_contenu_bloc(FILE *fd, const struct entete_bloc g)
{
char data[g.taille_contenu];
fread(&data,g.taille_contenu,1,fd);
// traitement à détailler selon le type
switch (g.type) {
case 'H' :
afficher_caracteristiques(data);
break;
case 'C' :
afficher_commentaire(data, g.taille_contenu);
break;
case 'D' :
afficher_image(data,largeur,hauteur);
default:
break;
}
}
void traiter_blocs(FILE *fd)
{
while (true) {
struct entete_bloc h;
if (! traiter_entete_bloc(fd, &h)) break;
printf("bloc type %c taiile %d\n\n", h.type,h.taille_contenu);
traiter_contenu_bloc(fd, h);
}
}
void traiter_fichier(const char *chemin)
{
FILE *fd = fopen(chemin, "r");
if (fd < 0) {
perror("ouverture fichier");
exit (EXIT_FAILURE);
}
if(traiter_magic_number(fd))
{
traiter_blocs(fd);
}
fclose(fd);
}
int main()
{
char nomFichier[50];
printf("entrer un fichier:" );
scanf("%c",&nomFichier);
traiter_fichier("A.mp");
return EXIT_SUCCESS;
}
que je peux rajouter au code pour le rendre plus fiable ( bloquer par exemple des fichier corrompus) et mon sujet au bug. dans la doc il et dit qu'il ne doit y avoir qu'un seul bloc H, il peut y avoir 0, un ou plusieurs bloc C et un ou plusieurs blocs D. alors comment faire ces vérifications de bloc et arrêter l’exécution du programme lorsque ces conditions ne sont pas vérifiées.
Dans un premier temps, nous allons décrire les blocs nécessaires à la description d’images en noir et blanc : — un bloc d’en-tête H (header) ; — zéro, un ou plusieurs blocs de commentaires C (comment) ; — un ou plusieurs blocs de données D (data).
comment faire ces verifications de telles sortes que si le fichier soumis au programme n'a pas de bloc H il ne passe pas a l'etape suivantes, pareil pour le bloc D
- Edité par vamskhalil 26 novembre 2022 à 16:12:58
Dans un premier temps, nous allons décrire les blocs nécessaires à la description d’images en noir et blanc : — un bloc d’en-tête H (header) ; — zéro, un ou plusieurs blocs de commentaires C (comment) ; — un ou plusieurs blocs de données D (data).
comment faire ces verifications de telles sortes que si le fichier soumis au programme n'a pas de bloc H il ne passe pas a l'etape suivantes, pareil pour le bloc D
- Edité par vamskhalil il y a environ 1 heure
Solution classique
1. les fonctions traiter_xxxx retournent un code d'erreur ou un booléan qui dit si ça c'est bien passé
2. après les appels, on regarde si 0 (= OK), et sinon on propage l'erreur
C'était fait pour le magic number.
Alternative
- traitement d'erreurs par setjmp / longjmp (lire page de manuel)
- Edité par michelbillaud 26 novembre 2022 à 17:17:20
cc.c:10:1: error: unknown type name 'bool'
bool traiter_magic_number(FILE *fd)
^~~~
cc.c: In function 'traiter_magic_number':
cc.c:17:16: error: 'false' undeclared (first use in this function)
return false;
^~~~~
cc.c:17:16: note: each undeclared identifier is reported only once for each function it appears in
cc.c:21:16: error: 'true' undeclared (first use in this function)
return true;
^~~~
cc.c: In function 'afficher_image':
cc.c:67:9: error: variable-sized object may not be initialized
int b[lar]={0};
^~~
cc.c:67:21: warning: excess elements in array initializer
int b[lar]={0};
^
cc.c:67:21: note: (near initialization for 'b')
cc.c: At top level:
cc.c:91:1: error: unknown type name 'bool'
bool traiter_entete_bloc(FILE *fd, struct entete_bloc *h)
^~~~
cc.c: In function 'traiter_entete_bloc':
cc.c:95:24: error: 'false' undeclared (first use in this function)
if (n <= 0) return false; // y en a plus
^~~~~
cc.c:99:12: error: 'true' undeclared (first use in this function)
return true; // y en a
^~~~
cc.c: In function 'traiter_blocs':
cc.c:124:12: error: 'true' undeclared (first use in this function)
while (true) {
^~~~
cc.c: In function 'traiter_fichier':
cc.c:135:12: warning: ordered comparison of pointer with integer zero [-Wextra]
if (fd < 0) {
^
cc.c: In function 'main':
cc.c:151:13: warning: format '%c' expects argument of type 'char *', but argument 2 has type 'char (*)[50]' [-Wformat=]
scanf("%c",&nomFichier);
^
cc.c: In function 'traiter_magic_number':
cc.c:24:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
cc.c: In function 'traiter_entete_bloc':
cc.c:100:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Et même si on ajoute stdbool.h, il reste l'erreur de la ligne 67.
Les lignes 13, 94 et 105 ne sont pas correctes.... voir le manuel de fread()
Alors, de là à dire que le code fonctionne bien....
Edit: si ce n'est déjà fait, ajoute les options -Wall -Wextra pour le compilation (avec gcc)
- Edité par edgarjacobs 26 novembre 2022 à 18:00:26
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
De façon systématique, on peut mettre des compteurs de blocs de chaque type. A regrouper dans une structure "contexte" qui peut être passée en paramètre ou globale.
Avec vérifications : quand on rencontre le bloc H, tous les compteurs doivent être à 0. Quand on rencontre autre chose, le compteur de h doit etre a 1. A la fin, au moins un bloc d
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent