1

Bonjour!
J'ai une fonction que je souhaiterai simplifier mais j'avoue que je ne sais pas comment procéder (et si cela est possible)

mafonction()
{
...
if (format == normal)
{
FILE* fichier; // on enregistre normalement
....[1]
fclose(fichier);
}

if (format == compressé)
{
gzFile fichier; // On enregistre au format GZIP
....[1] //Exactement la même chose que précédemment
fclose(fichier);
}
}



Le code "....[1]" est rigoureusement identique. Comment faire pour éviter de le répéter?

2

heu c'est du C++ ? (parceque si c'est du C et que le code est rigoureusement identique, à moins d'avoir aucun appel de fonction dans "..." je ne vois pas trop comment ça peut fonctionner (proprement) si FILE* et gzFile sont des types différents ?)
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

3

Et encore, le fclose() ne marcherait pas non plus sur le gzFile, surtout qu'aucun des deux n'est initialisé...
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

4

on sait jamais, si il a un fclose surchargé pour les gzFile; mais bon ça reste curieux comme code
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

5

Il peut y avoir une relation d'héritage entre gzFile et FILE*
Et puis même si c'est en C, le code "..." cast peut être gzFile et/ou FILE*

spomky> Tu peux utiliser un #define

6

Généralement on peut faire une macro (pratique, mais crade) ou une fonction pour ça (plus propre, mais moins pratique...)...
Mais là il y a un autre problème... Le code est mal fichu...
Déjà on ne fait pas if (a == b) { } if (a == c) { } mais on fait if (a == b) { } else if (a == c) { } dans ce cas précis...
Ensuite if (a == b) { } else if (a == c) { } dans ce cas précis ça se code même en switch (a) { case b: break; case c: break; } c'est tout au moins plus lisible et éventuellement (si tu avais plus de deux cas disons) plus optimisé.
A partir de là selon la tronche de ton code, tu peux éventuellement gicler une ou deux des occurences de ton "...", mais ça dépend du "..." ...
Enfin je vais être plus explicite, si ton code est rigoureusement identique (*doute*) alors tu fous simplement le code après le if/switch...
Sinon on suppose que t'as une fonction fopen, fwrite (ou similaire) et fclose pour chaque type de fichier... Alors tu fais un truc du genre
[code]FOPEN_FUNCTION pfopen;
FWRITE_FUNCTION pfwrite;
FCLOSE_FUNCTION pfclose;

switch (format)
{
case normal:
pfopen = fopen;
pfwrite = fwrite;
pfclose = fclose;
break;
case compressé:
pfopen = fopen_cmp;
pfwrite = fwrite_cmp;
pfclose = fclose_cmp;
break;
}

ma_sous_fonction(pfopen, pfwrite, pfclose);[/code]
Plus généralement encore ça c'est l'équivalent C de ce qu'on ferait en C++ avec des classes... Et là ça peut se coder encore mieux que ça... Mais comme je sais pas si ton code est C ou C++ ...
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

7

GoldenCrystal :
Déjà on ne fait pas if (a == b) { } if (a == c) { } mais on fait if (a == b) { } else if (a == c) { } dans ce cas précis...


Et si "...." modifie la variable a ?
ton code => poubelle

8

il ne le modifie pas dans ce cas précis comme je l'ai écrit... Réfléchit 30s avant de dire ça... Il a dit que c'était exactement le même code, ok il c'est certainement trompé, mais il est ptet pas con non plus... si "..." modifie a alors il le modifie encore dans le deuxième if ? Mais c'est quoi l'intérêt tu m'explique ?
Ton post => poubelle
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

9

Jyaif
:
GoldenCrystal :
Déjà on ne fait pas if (a == b) { } if (a == c) { } mais on fait if (a == b) { } else if (a == c) { } dans ce cas précis...


Et si "...." modifie la variable a ?

C'est justement l'intérêt, faire comme le dit GC permet de montrer du premier coup d'oeil que les deux blocs ne seront pas tous les deux exécutés, et que le 'a' qu'on compare à b est le même que celui qu'on compare à c smile

(PS : t'aurais pu faire encore un peu plus agressif, là ça manquait un peu de punch...)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

10

Bah son code est tres certainement en C (utiliser FILE en C++ c'est assez moisi)

11

GoldenCrystal :
Mais c'est quoi l'intérêt tu m'explique ?
Je t'explique que on peut pas dire grand chose sur son code tant qu'on ne connait pas ce qu'il y a à la place des "..."
Pollux :
(PS : t'aurais pu faire encore un peu plus agressif, là ça manquait un peu de punch...)
Bah moi je trouve qu'il a été lui même agressif en répondant à spomky (pas autant que moi par contre, ça c'est clair wink)

12

spomky :
Le code "....[1]" est rigoureusement identique.

Si tu comprends pas ça...
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

13

Bah en toute rigueur c'est pas parce qu'il est identique qu'il ne modifie pas format, hein tongue

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

14

Et toi, tu comprends pas que "...[1]" peut inclure "format = compressé;" ?
cross...

15

GC, occupe toi de ca http://goldencrystal.free.fr/projects/ plutot que trainer sur des forums..
Tout ce qui passe pas par le port 80, c'est de la triche.

16

./13 > En toute rigueur oui, mais logiquement non...
./14 > Il *pourrait* mais il ne peut pas, c'est une question de logique.
Bon je croyais avoir posté quelque part que [dans une logique normale de programmation sur PC] faire if (a == b) { a = c; } if (a == c) { a = c; } c'est complètement con, mais apparement non, donc maintenant c'est fait...
Même en faisant du copier coller, personne n'ira jamais mettre cette ligne qui ne lui servira à rien, et qui vraissemblablement vu le type d'information qu'elle contiendrait, se trouverait au début ou a la fin du bloc de code, donc très simple à éliminer... Donc si il y avait une telle différence elle aurait été mentionnée par spomky.
Bref en fait ça me saoule d'aller plus loin dans l'explication, mais pour tous les cas farfelus que vous pourriez inventer répondez avant à la question "A quoi servirait-il de faire ... ?" et ensuite "Est-ce que la structure du code donnée correspond vraiment à [réponse de la quetsion précédente] ?" à laquelle vous répondrez certainement par non, alors réfléchissez à "Comment modifier la forme du code pour que ça corresponde à [réponse de la question 1] ?" et vous tomberez sur quelque chose de différent...

./15 > onur, H de Hawaï, ...
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

17

le H de chat aussi, paske cat c'est pareil
avatar

18

C'est utilisé dans une classe en C++          return false;      }Voici le code dont je parle :      if ( format == PATH_SDDBPF && version == getVersion(0,1) )      {           FILE *file = NULL;           if ( (file = fopen(filename,"wb")) != NULL)           {                strcpy(this->object_header.file_format,"SDD-BPF");                this->object_header.version[0] = 0;                this->object_header.version[1] = 1;                writeIntoFile(file,&this->object_header,sizeof(CPath_Node::PATH_MAP_NODES_HEADER));                                for ( unsigned long cptr = 0 ; cptr < this->object_header.nb_object ; cptr++ )                     writeIntoFile(file,this->object_list[cptr],sizeof(CPath_Node::PATH_OBJECT));                                unsigned long temp = 0;                if ( this->object_header.nb_object != 0 )                {                     for ( unsigned long cptr = 0 ; cptr < this->object_header.nb_object ; cptr++ )                     {                          writeIntoFile(file,&temp,sizeof(unsigned long));                          temp = temp + 1 + this->object_links[cptr]->nb;                     }                     for ( unsigned long cptr = 0 ; cptr < this->object_header.nb_object ; cptr++ )                     {                          if ( this->object_links[cptr] != NULL)                          {                               writeIntoFile(file,&this->object_links[cptr]->nb,sizeof(unsigned long));                               for ( unsigned long cptr2 = 0 ; cptr2 < this->object_links[cptr]->nb ; cptr2++ )                                    writeIntoFile(file,&this->object_links[cptr]->object[cptr2],sizeof(unsigned long));                          }                     }                }                                fclose( file );                return true;           }           return false;      }            if (format == PATH_SDDBPFc && version == getVersion(0,1) )      {           gzFile file = NULL;           if ( (file = gzopen(filename,"wb-1")) != NULL)           {                strcpy(this->object_header.file_format,"SDD-BPFc");                this->object_header.version[0] = 0;                this->object_header.version[1] = 1;                writeIntoFile(file,&this->object_header,sizeof(CPath_Node::PATH_MAP_NODES_HEADER));                                for ( unsigned long cptr = 0 ; cptr < this->object_header.nb_object ; cptr++ )                     writeIntoFile(file,this->object_list[cptr],sizeof(CPath_Node::PATH_OBJECT));                                unsigned long temp = 0;                if ( this->object_header.nb_object != 0 )                {                     for ( unsigned long cptr = 0 ; cptr < this->object_header.nb_object ; cptr++ )                     {                          writeIntoFile(file,&temp,sizeof(unsigned long));                          temp = temp + 1 + this->object_links[cptr]->nb;                     }                     for ( unsigned long cptr = 0 ; cptr < this->object_header.nb_object ; cptr++ )                     {                          if ( this->object_links[cptr] != NULL)                          {                               writeIntoFile(file,&this->object_links[cptr]->nb,sizeof(unsigned long));                               for ( unsigned long cptr2 = 0 ; cptr2 < this->object_links[cptr]->nb ; cptr2++ )                                    writeIntoFile(file,&this->object_links[cptr]->object[cptr2],sizeof(unsigned long));                          }                     }                }                                gzclose( file );                return true;           }  
Dans ce code les fonctions writeIntoFile on ces prototypes :
- void CPath_Node_Map_Creator::writeIntoFile( FILE* file, const void* buffer, unsigned long length )
- void CPath_Node_Map_Creator::writeIntoFile( gzFile file, const void* buffer, unsigned long length )


En fait ce qui diffère c'est seulement au début et à la fin :
- dans un cas on a
		FILE *file = NULL;
		if ( (file = fopen(filename,"wb")) != NULL)
		{
			strcpy(this->object_header.file_format,"SDD-BPF");
			...
			fclose( file );
			return true;
		}
		return false;

- dans l'autre
		gzFile file = NULL;
		if ( (file = gzopen(filename,"wb-1")) != NULL)
		{
			strcpy(this->object_header.file_format,"SDD-BPFc");
			...
			gzclose( file );
			return true;
		}
		return false;

19

Le plus propre serait sans doute de passer par une classe File qui aurait deux classes dérivées, PlainFile et GzFile, et qui encapsulerait tes ouvertures/écritures de fichiers ^^ (et accessoirement ça te permettrait d'avoir le *close() fait automatiquement dans le destructeur, ce qui est nettement plus propre)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

20

oui sauf que comme c'est peut-être pas lui qui a défini gzFile et FILE, pour les faire hériter d'une classe commune bah... ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

21

gni ? je parle de faire une classe qui contiendrait le gzFile (ou le FILE *) en tant que membre, pas de faire un truc qui hériterait de gzFile (surtout que pour faire hériter une classe de FILE *, ça risquerait d'être dur fou2)

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

22

hmm nan en fait j'étais parti du principe qu'il était impossible de les encapsuler, puisque FILE et gzFile n'ont aucune parenté et que donc la classe mère qui serait créée de cette façon ne pourrait contenir ni l'un ni l'autre (et que donc dans la partie du code qui deviendrait génerique, il serait impossible d'acceder au champ "file"); mais bon, methodes virtuelles toussa, on va dire que je viens de me lever tongue
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

23

euh, mais même les méthodes virtuelles et le fait d'hériter d'une classe commune ne sont pas indispensables, il suffit que mafonction() soit templaté ^^

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

24

j'ai pas dit que c'était indispensable, juste qu'en postant le #19 je n'avais pas vu de solution ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

25

j'ai pas dit que t'avais dit que c'était indispensable happy c'était juste une remarque comme ça ^^

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)

26

OK donc il vaut mieux créer une nouvelle classe qui gère les entrées et sorties. Effectivement c'est peut-être plus simple.
Des constructeurs du genre MaClass( FILE* fichier , const char* mode) et MaClass( gzFile fichier , const char* mode) , une fonction lire( unsigned long offset , unsigned long taille , void* buffer ) et ecrire(const void* buffer , unsigned long taille )

Je vais voir ça.
Merci bien, A+

27

C'est bon j'ai fait la classe en question et ça marche super!merci pour l'idée.
Je vous file les sources (même s'il n'y a rien d'extraordinaire) #ifndef FILEIO_H      #define FILEIO_H            #include <stdlib.h>      #include <stdio.h>      #include <zlib.h>      //#include <iostream>            enum FILEIO_MODE {FILEIO_unset = -1, FILEIO_normal, FILEIO_gzip};      class FileIO      {           public:                FileIO(){this->mode=FILEIO_unset,this->file=NULL;};                FileIO( const char* , const char* , FILEIO_MODE = FILEIO_normal );                ~FileIO();                                void openFile( const char* , const char* , FILEIO_MODE = FILEIO_normal );                bool isFileOpened( void ){return this->file!=NULL;};                FILEIO_MODE getMode( void ){return this->mode;};                                          void write( const void* , unsigned long );                void read( unsigned long , void * , unsigned long );                                void closeFile( void );           private:                void* file;                FILEIO_MODE mode;      }; #endif #include "FileIO.h" FileIO::FileIO( const char* filename , const char* option , FILEIO_MODE openmode ) {      this->openFile(filename,option,openmode); } FileIO::~FileIO() {      this->closeFile( ); } void FileIO::openFile( const char* filename , const char* option , FILEIO_MODE openmode ) {      if ( this->isFileOpened() || openmode == FILEIO_unset)           return;            if ( openmode == FILEIO_normal )           file = (FILE*)fopen(filename,option);      if ( openmode == FILEIO_gzip )           file = (gzFile)gzopen(filename,option);            if ( file != NULL )           this->mode = openmode; } void FileIO::write( const void* buffer, unsigned long length ) {      //cout << "\tTentative d'écriture de données" << endl;      if ( this->isFileOpened() && this->mode == FILEIO_normal)           fwrite(buffer,length,1,(FILE*)file);      if ( this->isFileOpened() && this->mode == FILEIO_gzip)           gzwrite((gzFile)file,buffer,length );            //cout << "\t\tdonnées écrites" << endl; } void FileIO::read( unsigned long position , void *buffer , unsigned long length ) {      if ( this->isFileOpened() && this->mode == FILEIO_normal)      {            }      if ( this->isFileOpened() && this->mode == FILEIO_gzip)      {            } } void FileIO::closeFile( void ) {      if ( this->isFileOpened() && this->mode == FILEIO_normal)           fclose((FILE*)file);      if ( this->isFileOpened() && this->mode == FILEIO_gzip)           gzclose((gzFile)file);            this->file = NULL; }
Nota : il manque la fonction read, je ne l'ai pas encore faite (ceci dit c'est juste des fread ou gzread)

28

Juste pour info :

Tu t'embètes pour rien. Il suffit de faire gzopen("foo", "wb0"); et zlib ne compresse pas les données, émulant le comportement de fread et fwrite.

strcpy(buf, options);
if (format == normal) strcat(buf, "0");

gzFile fichier = gzopen(nom, buf);
......

29

ah bon?!!?? là tu m'en apprends une bien bonne, je ne savais pas.
Je vais m'y pencher de plus près.

Est-ce que quelqu'un sait se servir de libtar? (la bibliothèque qui permet de faire des archives tar)
Je n'ai pas trouvé grand chose sur google et le peut d'exemple (me les man:/tar_open et co) ne sont pas d'une grande aide.

30

bon finalement passer une compression de 0 émule bien fwrite et fread mais le fichier est toujours contenu dans un fichier gzip, l'en-tête le montre.
Je suis resté sur ma façon de faire, d'autant plus que j'ai ajouté la compression BZIP2 sans trop de foulage du cerveau (sauf les équivalents aux fonctions fseek et ftell qui n'existent pas dans la lib et sur lesquels je bloque un peu).
Je veux faire une classe simple à l'utilisation, là je trouve ça pas mal!
FileIO *fichier = new FileIO("mon fichier","rb",FILEIO_gzip); //On ouvre un fichier GZIP en lecture seule
fichier->seek(100); //On se place au 100ième octet
fichier->read(mon_buffer,200); //On lit 200 octets que l'on place dans mon_buffer (mon_buffer doit être déjà initialisé et de taille suffisante)
delete fichier; // On supprime l'objet (cela ferme le fichier ouvert avant par la même occasion, on peut utiliser fichier->close() si on veut)