IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Compression de fichier texte


Sujet :

C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 69
    Points : 25
    Points
    25
    Par défaut Compression de fichier texte
    bonjour,

    j'ai un projet en C à écrire de compression de fichier texte par la méthode RLE (Run Length Encoding) à savoir, à partir d'un fichier de type : "aaaabbbcccccbb", on doit obtenir: "aa2bb1cc3bb0"

    J'ai écrit un partie du code cependant je ne sais pas comment écrire le caractère lu dans mon fichier résultat (qui s'appelle "compresser").

    Voici mon code: (avec comme fichier texte initial dans Acompresser : "aaaabbbcccccbb")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    int main (int argc,char**argv) { 
    file*Acompresser;
    Acompresser=fopen(argv[2],"rt");
    compresser=fopen(argv[3],"w");
    }
     
    void compresser(Acompresser, compresser) {
    /*lire le premier caractère et le copier dans une variable char1*/
    	a==char1;
    /*copier char1 dans le fichier "compresser"*/
    	char1==(argv[3],"w");
    /*lire le second caractère et le copier dans une variable char2*/
    	a==char2;
    /*initialiser la somme à 0*/
    	sum=0;
    /*vérifier que:*/
    	if(char1==char2) {
    /*tant que le caractère est le même que le suivant*/
    		while(char2=(suivant)!)char2)
    /*on fait la somme des caractères suivants le second*/
    		sum=sum+1;
    	}
    /*si les 2premiers caractères ne sont pas identiques*/
    	else ???
    }
    Je vous remercie beaucoup.
    Victoria

    PS: je suis débutante, voire très débutante, je pratique le C que depuis 3mois.

  2. #2
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut
    Citation Envoyé par Victoria007 Voir le message
    PS: je suis débutante, voire très débutante, je pratique le C que depuis 3mois.
    Tes progrès en 3 mois ne sont pas très impressionnants. Il va falloir s'y mettre plus sérieusement. Il est inutile d'essayer de voir si ton algorithme répond à ton problème, puisque ton code est outrageusement faux.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int main (int argc,char**argv) { 
    file*Acompresser;
    Le C est sensible à la casse. Ce n'est pas file mais FILE. Il faut inclure stdio.h.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Acompresser=fopen(argv[2],"rt");
    Il faut tester la valeur de argc pour s'assurer qu'on a reçu le bon nombre de paramètres afin de ne pas envoyer n'importe quoi à fopen(). Il faut inclure stdio.h pour fopen(). "rt" n'est pas un mode d'ouverture standard, c'est "r". Il faut tester que fopen() a réussi (Acompresser n'est pas NULL).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    compresser=fopen(argv[3],"w");
    La variable compresser n'est pas déclarée, et son nom est le même que celui de la fonction qui suit.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void compresser(Acompresser, compresser) {
    Le type des arguments doit être donné explicitement. La fonction n'est jamais appelée dans main(). Si main() doit appeler la fonction, alors il faut en donner le prototype avant l'appel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /*lire le premier caractère et le copier dans une variable char1*/
    	a==char1;
    a et char1 ne sont pas déclarées. == est l'opérateur de comparaison pour l'égalité. L'opérateur d'assignation, c'est =. De plus, à aucun moment tu ne lis un caractère. Voir fgetc() pour faire cela, par exemple.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /*copier char1 dans le fichier "compresser"*/
    	char1==(argv[3],"w");
    Mêmes commentaires qu'au dessus, plus argv n'est pas déclaré dans cette fonction. Cette ligne ne fait pas du tout ce que tu crois. Pour écrire dans un caractère dans un fichier, utiliser fputc().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /*lire le second caractère et le copier dans une variable char2*/
    	a==char2;
    char2 n'est pas déclarée. == n'est pas =. A aucun moment tu ne fais une lecture.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /*initialiser la somme à 0*/
    	sum=0;
    sum n'est pas déclarée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /*tant que le caractère est le même que le suivant*/
    		while(char2=(suivant)!)char2)
    Cette ligne n'a aucun sens. Les compilateurs C ne comprennent pas le français.

    Y'a du boulot, bon courage.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 69
    Points : 25
    Points
    25
    Par défaut
    Merci DaZumba.

    J'ai corrigé mes erreurs en fonction de ce que tu m'avais dit et fait des recherches sur internet sur certaines fonctions.

    Voilà ce que j'obtiens comme code maintenant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
     
    void compression (char *test,char *resultat1) {
    	FILE * Acompresser, * compresser;
     
    /*lire le fichier à compresser*/
    	Acompresser=fopen(test,"r");
     
    /*tester que fopen() a réussi*/
    	if (fopen==NULL)
    		printf("Erreur d'ouverture de fichier\n");
     
    /*créer un fichier pour écrire le résultat de la compression*/
    	compresser=fopen(resultat1,"w");
     
    /*déclarations des variables*/
    	int char1, char2, sum;
     
    /*lire le premier caractère et le copie dans une variable char1*/
    	char1 = fgetc (Acompresser);
     
    /*copier char1 dans le fichier "compresser"*/
    	fputc (char1, compresser);
     
    /*lire le second caractère et le copier dans une variable char2*/
    	char2 = fgetc (Acompresser);
     
    /*copier char2 dans le fichier "compresser"*/
    	fputc (char2, compresser);
     
    	sum = 0;
     
    /*vérifier que:*/
    		if (char1==char2) {
     
    /*tant que le caractère est le même que le suivant*/
    			while (char2==(char2)+1);
     
    /*on fait la somme des caractères suivants le second*/
    			sum = sum+1;
     
    /*exécuter la lecture jusqu'à la fin du fichier*/
    			while (fgetc (Acompresser) != EOF);
     
    		}
     
    /*afficher le résultat de la compression dans le fichier résultat*/
    	fprintf(compresser,"resultat1 %d", sum);
     
    /*fermer les fichiers ouverts*/
    	fclose (Acompresser);
    	fclose (compresser);
     
    	}
    }
     
     
     
    int main (int argc,char**argv) {
     
    	compression(argv[2], argv[3]);
     
    	return 0;
     
    }

    En compilant avec gcc -Wall nomdufichier.c, je n'ai aucune erreur.
    Par contre, en le testant avec ./a.out, il me dit:
    "Erreur de segmentation".

    Et j'avoue ne pas savoir pourquoi, ni d'ou vient cette erreur.

    Si quelqu'un pouvait m'éclairer?


    Je vous remercie.

    Victoria.

  4. #4
    Membre averti Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Points : 441
    Points
    441
    Par défaut
    Les commentaires c'est bien mais faut pas en mettre trop, ton code est assez dur à lire ...

    Sinon, voici ce que fait la fonction compression :
    1) lecture du premier caractère
    2) lecture du second caractère
    3) rien !!!!

    essaie d'écrire l'algo en français avant d'écrire le code C, cela t'aidera à voir ce que tu ne fais pas.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2007
    Messages : 115
    Points : 110
    Points
    110
    Par défaut
    /*lire le fichier à compresser*/
    Acompresser=fopen(test,"r");

    /*tester que fopen() a réussi*/
    if (fopen==NULL)
    printf("Erreur d'ouverture de fichier\n");
    fopen est le nom de la fonction, cette fonction tu l'utilises à la ligne `Acompresser=fopen(test,"r");``, verifier le retour de la fonction, c'est alors verifier la valeur de Acompresser. En effet, si (Acompresser == NULL), tu affiches une erreur, mais il faut également sortir de ton programme (return (1); ?)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /*créer un fichier pour écrire le résultat de la compression*/
    	compresser=fopen(resultat1,"w");
    Ici aussi tu dois verifier le retour de fopen (si compresser est NULL, et quitter la fonction en cas d'erreur).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /*déclarations des variables*/
    	int char1, char2, sum;
    Normalement les declarations de variable se font en debut de bloc (en haut de ta fonction).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /*copier char1 dans le fichier "compresser"*/
    	fputc (char1, compresser);
    Tu peux controler le retour de cette fonction aussi (si (fputc(...) == EOF) alors, afficher une erreur puis sortir du programme)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /*tant que le caractère est le même que le suivant*/
    			while (char2==(char2)+1);
    char2+1 n'est pas le caractere suivant dans le fichier, pour avoir le suivant, il faut que tu refasses un getc. En effet par exemple si char2 est un A (valeur ascii : 65), alors char2+1 sera un B, car la valeur ascii de B est 66.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /*exécuter la lecture jusqu'à la fin du fichier*/
    			while (fgetc (Acompresser) != EOF);
    Ici tu perds toute la suite de ton fichier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    /*fermer les fichiers ouverts*/
    	fclose (Acompresser);
    	fclose (compresser);
    Tu peux egalement verifier le retour des fonctions fclose. (EOF en cas d'erreur).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main (int argc,char**argv) {
     
    	compression(argv[2], argv[3]);
     
    	return 0;
     
    }
    Ici si tu executes ton programme de la sorte :
    $> ./a.out
    Et bien le message que tu verras sera le suivant : Segmentation fault (Erreur de segmentation), en effet, les index 2 et 3 de ton tableau de char*, argv sont inaccessibles. De plus, je pense que la syntaxe de ton programme est la suivante :
    $> ./a.out fichier1 fichier2
    argv[0] serait alors "./a.out"
    argv[1] serait alors "fichier1"
    argv[2] serait alors "fichier2"
    En effet, dans un tableau, les index commencent à 0.

    Tu peux faire quelque chose comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int   main(int argc, char **argv)
    {
      if (argc == 3 && argv[1] && argv[2])
         return (compression(argv[1], argv[2]));
      else
        return (1);
    }

    En compilant avec gcc -Wall nomdufichier.c, je n'ai aucune erreur.
    -Wall ne suffit pas pour avoir tous les warnings.

    Par contre, en le testant avec ./a.out, il me dit:
    "Erreur de segmentation".
    Normal, voir plus haut.

    Je vous remercie.

    Victoria.
    Cordialement.

  6. #6
    Membre averti Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Points : 441
    Points
    441
    Par défaut
    Je te propose un code pour ton algorithme. Plusieurs points à noter :
    1) le nom des fichiers est fixé dans la fonction main(), pour plus de commodités
    2) je construit le fichier d'entrée dans la fonction main()
    3) le résultat obtenu n'est pas exactement ce que tu donnais dans ton premier post mais je pense que cela correspond mieux à l'algorithme RLE

    Lit bien ce code et pose des questions sur ce que tu ne comprends pas. Portes ton attention sur la fonction compression().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
     
    int compression (char *ficin,char *ficout) {
        int char_old, char_cur, cpt=1;
        FILE *in=NULL, *out=NULL;
     
        in = fopen(ficin,"r");
        if ( in == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficin);
            return 0;
        }
     
        out = fopen(ficout,"w");
        if ( out == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficout);
            fclose(in);
            return 0;
        }
     
        char_old = fgetc(in);
        do {
            char_cur = fgetc(in);
            if ( char_cur == char_old ) {
                cpt++;
            } else {
                fputc(char_old,out);
                fprintf(out,"%d",cpt);
                cpt=1;
            }
            char_old = char_cur;
        } while (char_cur != EOF);
     
        fclose(in);
        fclose(out);
     
        return 1;
    }
     
    int main (void) {
        char ficin[] = "ficin.txt";
        char ficout[] = "ficout.txt";
        char message[] = "aaaabbbcccccbb";
        char ligne[100];
        FILE *tmp=NULL;
     
        tmp = fopen(ficin,"w");
        if ( tmp == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficin);
            exit(EXIT_FAILURE);
        }
        fprintf(tmp,"%s",message);
        fclose(tmp);
     
        if ( !compression(ficin,ficout) ) {
            fprintf(stderr,"erreur lors de la compression\n");
        }
     
        tmp = fopen(ficout,"r");
        if ( tmp == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficout);
            exit(EXIT_FAILURE);
        }
        fgets(ligne,100,tmp);
        fclose(tmp);
     
        printf("message en clair : %s\n",message);
        printf("message code : %s\n",ligne);
     
        return 1;
    }

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 69
    Points : 25
    Points
    25
    Par défaut
    Tusbar --> Merci beaucoup. Je n'ai pas encore regardé et corrigé en fonction de tes commentaires, je vais m'y mettre de suite



    Corentin --> Merci beaucoup. J'ai compilé et fait tourner ton programme et pour "aaaabbbcccccbb", j'obtiens "a4b3c5b2".
    Seulement, le code que j'essaye de faire est pour un projet de C donné par un prof dont les instructions sont strictes à savoir :
    - pour un fichier de type "aaaabbbcccccbb", le code doit rendre : "aa2bb1cc3bb0"; c'est-à-dire chaque nouveau caractère écrit 2 fois suivit d'un chiffre représentant la somme du nombre de fois que ce caractère est répété après les 2premières fois. (c'est surement pour ne pas prendre des codes de RLE tout fait sur internet)
    - on doit créer des fichiers, notemment 2, celui a compresser et obtenir celui compresser avec le résultat de la compression écrit dedans. Il n'est pas spécifié de ne pas qu'il apparaisse dans le shell, mais il doit dans tous les cas créer un fichier compresser avec le résultat de la compression.

    Du coup, je pense ne pas pouvoir prendre ton code, ou le modifier pour obtenir ce que je recherche, mais il y a pas mal de truc que je savais pas faire et que je ne comprends pas forcément dans la façon dont tu les a codé.

  8. #8
    Membre averti Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Points : 441
    Points
    441
    Par défaut
    Citation Envoyé par Victoria007 Voir le message
    pour un fichier de type "aaaabbbcccccbb", le code doit rendre : "aa2bb1cc3bb0"; c'est-à-dire chaque nouveau caractère écrit 2 fois suivit d'un chiffre représentant la somme du nombre de fois que ce caractère est répété après les 2premières fois. (c'est surement pour ne pas prendre des codes de RLE tout fait sur internet)
    ben il suffit d'écrire deux fois le caractère et de mettre comme nombre "cpt-2" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    fputc(char_old,out);
    fputc(char_old,out);
    fprintf(out,"%d",cpt-2);
    Citation Envoyé par Victoria007 Voir le message
    on doit créer des fichiers, notamment 2, celui a compresser et obtenir celui compresser avec le résultat de la compression écrit dedans. Il n'est pas spécifié de ne pas qu'il apparaisse dans le shell, mais il doit dans tous les cas créer un fichier compresser avec le résultat de la compression.
    dans le code que je t'ai donné, la fonction main() crée un fichier "ficin.txt" et copie dedans le message à compresser. La fonction compression() est alors appelée : elle lit le fichier "ficin.txt", compresse le message et écrit le message compressé dans "ficout.txt". Enfin, la fonction main() lit le fichier "ficout.txt" pour afficher le message compressé.

    Citation Envoyé par Victoria007 Voir le message
    Du coup, je pense ne pas pouvoir prendre ton code, ou le modifier pour obtenir ce que je recherche, mais il y a pas mal de truc que je savais pas faire et que je ne comprends pas forcément dans la façon dont tu les a codé.
    En fait, je n'ai pas fait le code pour que tu le prennes tel quel mais plutôt pour que tu comprennes la syntaxe des différentes commandes, que tu essaies de le rendre conforme aux prescriptions de l'énoncé et surtout pour que tu puisses poser des questions sur ce que tu ne comprends pas !!!

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 69
    Points : 25
    Points
    25
    Par défaut
    Alors voilà le nouveau code :

    J'ai changé en fonction des conseils de Tusbar et j'ai tout mis dans un main pour l'instant, c'était plus facile à compiler, je remetterais en void après.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
     
    int main (int argc, char**argv) {
              int char1, char2, sum;
              FILE *Acompresser, *compresser;
              Acompresser=fopen(argv[2],"r");
              if(Acompresser==NULL)
                        printf("Erreur lors de l'ouverture du fichier1\n");
              compresser=fopen(argv[3],"w");
              if(compresser==NULL)
                        printf("Erreur lors de l'ouverture du fichier2\n");
              char1=fgetc(Acompresser);
              char2=fgetc(Acompresser);
              while (char1!=EOF) {
                       fputc(char1,compresser);
                       if(char1==char2) {
                                sum=0;
                                fputc(char2,compresser);
                                while(char2==char1) {
                                         sum=sum+1;
                                         char2=fgetc(Acompresser);
                                }
                       fprintf(compresser,"%d",sum-1);
                       }
                       char1=char2
              }
              fclose(compresser);
              fclose(Acompresser);
              return 0;
    }

    J'ai ensuite compilé avec gcc -Wall ...... (je n'e connais pas d'autres).
    Et : ./a.out CR Acompresser compresser

    Avec un fichier Acompresser contenant: "aaaabbbcccccbb", j'obtiens dans compresser: "aa2bb2cc4bb1".
    Alors que je devrais obtenir: "aa2bb1cc3bb0".

    Je l'ai fait tourner sur papier pour voir ce que j'obtenais, et je n'arrive pas à trouver l'erreur.

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 69
    Points : 25
    Points
    25
    Par défaut
    Je vais te poser des questions sur le code que tu as écris sur les choses que je n'ai pas comprises :

    Citation Envoyé par corentin59 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int compression (char *ficin,char *ficout) {
        int char_old, char_cur, cpt=1;
        FILE *in=NULL, *out=NULL;
    Pourquoi déclares tu des fichiers = NULL d'origine?

    Citation Envoyé par corentin59 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        in = fopen(ficin,"r");
        if ( in == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficin);
            return 0;
        }
     
        out = fopen(ficout,"w");
        if ( out == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficout);
            fclose(in);
            return 0;
        }
    stderr, je ne connais pas.
    Je connais la structure de fprintf, mais je ne sais pas ce qu'est stderr.

    Citation Envoyé par corentin59 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
        char_old = fgetc(in);
        do {
            char_cur = fgetc(in);
            if ( char_cur == char_old ) {
                cpt++;
            } else {
                fputc(char_old,out);
                fprintf(out,"%d",cpt);
                cpt=1;
            }
            char_old = char_cur;
        } while (char_cur != EOF);
     
        fclose(in);
        fclose(out);
     
        return 1;
    }
    J'ai compris le sens du code et ce qu'il fait, mais pourquoi: return 1?
    Et je ne connais pas cette façon d'écrire : nomdelafontion =, on utilise pas: void () ou int () ?

    Citation Envoyé par corentin59 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    int main (void) {
        char ficin[] = "ficin.txt";
        char ficout[] = "ficout.txt";
        char message[] = "aaaabbbcccccbb";
        char ligne[100];
        FILE *tmp=NULL;
     
        tmp = fopen(ficin,"w");
        if ( tmp == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficin);
            exit(EXIT_FAILURE);
        }
        fprintf(tmp,"%s",message);
        fclose(tmp);
     
        if ( !compression(ficin,ficout) ) {
            fprintf(stderr,"erreur lors de la compression\n");
        }
     
        tmp = fopen(ficout,"r");
        if ( tmp == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficout);
            exit(EXIT_FAILURE);
        }
        fgets(ligne,100,tmp);
        fclose(tmp);
     
        printf("message en clair : %s\n",message);
        printf("message code : %s\n",ligne);
     
        return 1;
    }
    Je n'arrive pas bien à comprendre à quoi correspondent message et ligne ?
    Et même question qu'au dessus, pourquoi return 1?


    Merci

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2007
    Messages : 115
    Points : 110
    Points
    110
    Par défaut
    Bonsoir,

    • FILE *in=NULL, *out=NULL; c'est pour initialiser les pointeurs sur FILE à NULL, c'est a dire qu'ils ne pointent sur rien, au debut de la fonction.

    • stderr c'est la sortie d'erreur, en temps normal tu écris sur stdout (la sortie standard), en géneral on affiche les messages d'erreur sur stderr.

    • return (1) est generalement utilisé pour quitter un programme (ou quelques fois une fonction) en cas d'erreur, il y a des defines dans stdlib.h : EXIT_SUCCESS (qui est egal a 0) et EXIT_FAILURE (égal à 1, en tout cas, sur mon archi. c'est le cas).


    Et je ne connais pas cette façon d'écrire : nomdelafontion =, on utilise pas: void () ou int () ?
    Par contre ceci je n'ai pas compris ?


    Sinon, comme je te disais plus haut, quand l'ouverture (ou la création) d'un fichier echoue, il ne faut pas que tu continues dans ton programme, en l'occurence dans ta fonction, imagine, si tu n'arrives pas à ouvrir ton fichier, tout simplement si, par exemple, il n'existait pas, tu essayerais de lire un fichier qui n'existe pas ?
    Donc en cas d'erreur, on sort de la fonction ca s'effectue en regle generale a l'aide d'un return (d'une valeur differente de celle retournée par la fonction en cas de succes, afin de differencier l'echec du succes dans la fonction en amont).

    Cordialement.

  12. #12
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Tusbar Voir le message
    EXIT_SUCCESS (qui est egal a 0)
    Pas necessairement.

    Thierry

  13. #13
    Membre averti Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Points : 441
    Points
    441
    Par défaut
    Voilà une étude détaillée de mon code.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
     
    int compression (char *ficin,char *ficout) {
    cette ligne dit qu'on va définir une fonction dont le nom est "compression". Cette fonction retournera un entier (d'où le "int" du début) et prend en entrée deux paramètres qui sont des pointeurs vers des chaines de caractères.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        int char_old, char_cur, cpt=1;
        FILE *in=NULL, *out=NULL;
    ici, on déclare les variables : 3 entiers dont un est initialisé à 1 et deux pointeurs sur FILE, qui sont initialisés sur NULL, ce qui veut dire qu'on précise explicitement ici que pour l'instant ces pointeurs ne pointent sur rien.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        in = fopen(ficin,"r");
        if ( in == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficin);
            return 0;
        }
    on ouvre le fichier dont le nom est contenu dans la chaine de caractère pointée par "ficin". Si l'ouverture échoue, c'est-à-dire si "in" vaut toujours NULL après l'appelle à fopen(), on affiche un message d'erreur sur stderr (canal d'erreur) et on quitte la fonction avec le "return 0". Ca ne sert à rien de continuer si on n'a pas pu ouvrir le fichier. On a vu que la fonction compression devait renvoyer un entier, ici on renvoie 0 pour dire qu'il y a eu un problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        out = fopen(ficout,"w");
        if ( out == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficout);
            fclose(in);
            return 0;
        }
    même commentaire que précédemment. Si ce n'est qu'avant de quitter, on ferme tout ce qu'on a ouvert, d'où le fclose(in)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        char_old = fgetc(in);
        do {
            char_cur = fgetc(in);
            if ( char_cur == char_old ) {
                cpt++;
            } else {
                fputc(char_old,out);
                fputc(char_old,out);
                fprintf(out,"%d",cpt-2);
                cpt=1;
            }
            char_old = char_cur;
        } while (char_cur != EOF);
    On lit un caractère qu'on stocke dans char_old. Puis, on lit tous les caractères suivants et on les mets dans char_cur. A chaque lecture, on a deux possibilités : soit char_old est égale à char_cur et dans ce cas on incrémente le compteur, soit ils ne sont pas égaux, dans ce cas, on écrit deux fois char_old dans le fichier de sortie, on écrit le compteur-2 et on réinitialise le compteur à 1 pour qu'il commence à compter les nouveaux caractères. Enfin, à chaque fois, on n'oublie pas de mettre char_cur dans char_old.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        fclose(in);
        fclose(out);
     
        return 1;
    }
    une fois qu'on a fini, on ferme les fichiers ouverts. Si on arrive ici, c'est que tout s'est bien passé, alors on renvoie comme entier 1, qui signifie "la compression s'est bien faite"

    ici, on déclare la fonction main(). C'est comme pour la fonction compression(). Cependant, il faut préciser qu'on a un peu moins de liberté avec cette fonction, qui doit toujours être présente dans un code C : elle renvoie toujours un entier (d'où le int) et prend comme paramètres soit "void" (ce qui veut dire rien) soit ce que tu mettais, pour faire appel aux paramètres passés en ligne de commande.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        char ficin[] = "ficin.txt";
        char ficout[] = "ficout.txt";
        char message[] = "aaaabbbcccccbb";
        char ligne[100];
        FILE *tmp=NULL;
    toujours pareil, on commence par la déclaration des variables : "ficin" et "ficout" sont des pointeurs vers des chaines de caractères qui contiennent les fichiers d'entrée (ficin) et de sortie (ficout). idem pour "message" qui contient le texte à compresser. "ligne" est un pointeur vers une chaine de 100 caractères.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        tmp = fopen(ficin,"w");
        if ( tmp == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficin);
            exit(EXIT_FAILURE);
        }
        fprintf(tmp,"%s",message);
        fclose(tmp);
    ici, je crée le fichier contenant le texte à compresser, c'est-à-dire ficin. Toi tu t'es déjà créé ce fichier. Au passage, tu retrouves la même gestion des erreurs. Si l'ouverture echoue, la fonction main() s'arrête et renvoie EXIT_FAILURE qui est le nom d'un entier définit dans stdlib et qui signifie "il y a eu une erreur"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        if ( !compression(ficin,ficout) ) {
            fprintf(stderr,"erreur lors de la compression\n");
        }
    Ici, je fais appelle à la fonction compression(). il est évident qu'on fait appelle à une fonction par son nom (le faire par int ou void ou je ne sais pas quoi d'autre n'a strictement aucun sens). La fonction renvoie un entier donc pour comprendre l'instruction if, remplace l'appelle à la fonction par l'entier qu'elle retournera et du coup ça devient : si l'exécution de la fonction compression() se passe mal (elle renvoie 0), alors afficher un message d'erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        tmp = fopen(ficout,"r");
        if ( tmp == NULL ) {
            fprintf(stderr,"erreur lors de l'ouverture du fichier %s\n",ficout);
            exit(EXIT_FAILURE);
        }
        fgets(ligne,100,tmp);
        fclose(tmp);
    ici, j'ouvre le fichier ficout et j'extraie sa première ligne avec la fonction fgets() qui va la stocker dans la chaine de caractère pointée par "ligne".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        printf("message en clair : %s\n",message);
        printf("message code : %s\n",ligne);
    j'affiche quel était le texte à compresser et le texte compressé, que j'ai lu dans ficout.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        return EXIT_SUCCES;
    }
    La fonction main() renvoie l'entier EXIT_SUCCES définit dans stdlib et qui signifie "tout s'est bien passé".

    OUF !!!

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    115
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2007
    Messages : 115
    Points : 110
    Points
    110
    Par défaut
    Citation Envoyé par Thierry Chappuis Voir le message
    Pas necessairement.

    Thierry
    sur mon archi. c'est le cas

  15. #15
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 580
    Points
    41 580
    Par défaut
    Même EXIT_SUCCES peut être différent de zéro, Il me semble que la norme exige que retourner 0 signifie également "Succès", non ?

  16. #16
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Même EXIT_SUCCES peut être différent de zéro, Il me semble que la norme exige que retourner 0 signifie également "Succès", non ?
    Oui

    Thierry

  17. #17
    Membre averti Avatar de corentin59
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 462
    Points : 441
    Points
    441
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Même EXIT_SUCCES peut être différent de zéro, Il me semble que la norme exige que retourner 0 signifie également "Succès", non ?
    je ne le savais pas, je vais donc changer tous mes 0 en 1 et mes 1 en 0 dans mes codes

  18. #18
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 580
    Points
    41 580
    Par défaut
    Attention, la norme ne précise que 0, EXIT_SUCCESS et EXIT_FAILURE.
    Elle ne dit absolument rien au sujet de 1...

  19. #19
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 69
    Points : 25
    Points
    25
    Par défaut
    J'ai pris en compte tous vos commentaires et voici le dernier programme que j'ai réussi à écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    # include <stdio.h>
    # include <stdlib.h>
    # include <string.h>
     
    void compression (char*test, char*resultat1) {
        int char1,char2,sum;
        FILE *Acompresser, *compresser;
        char1=fgetc(Acompresser);
        char2=fgetc(Acompresser);
        while (char1!=EOF) {
    	fputc (char1,compresser);
    	if (char1==char2) {
    	    sum=0;
    	    fputc(char2,compresser);
    	    while(char2==char1) {
    		sum=sum+1;
    		char2=fgetc(Acompresser);
    	    }
    	    fprintf(compresser,"%d",sum-1);
    	}
    	char1=char2;
        }
    }
     
    int main (int argc, char**argv) {
        FILE *Acompresser, *compresser;
        Acompresser=fopen(argv[2],"r");
        if(Acompresser==NULL) {
    	printf("Erreur d'ouverture fichier1\n");
    	exit(1);
        }
        compresser=fopen(argv[3],"w");
        if(compresser==NULL) {
    	printf("Erreur d'ouverture fichier2\n");
    	exit(1);
        }
        if (strcmp(argv[1], "cr")==0)
    	compression(Acompresser, compresser);
        fclose(compresser);
        fclose(Acompresser);
        return 0;
    }
    Seulement, il reste deux problèmes à régler, et dont je ne trouve pas la solution
    Que je mette compression(Acompresser, compresser);
    ou compression(argv[2], argv[3]); dans le main, il me met comme erreurs :
    warning: passing argument 1 of 'compression' from incompatible pointer type
    warning: passing argument 2 of 'compression' from incompatible pointer type
    pour cette ligne.
    Pourquoi?
    Que dois je changer pour que ça compile?

    Et dernière chose, je pensais que mon algo était bon, je l'ai testé sur papier et je trouvais les bons résultats seulement, lorsque je compile et que je regarde les résultats, pour un texte à compresser du type:
    aaaabbbcccccbb
    il me le compresse et donne :
    aa2bb2cc4bb1

    Alors que je devrais obtenir: aa2bb1cc3bb0
    Qu'est ce qui ne va pas?


    Merci beaucoup.

  20. #20
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void compression (FILE *Acompresser, FILE*compresser) {
        int char1,char2,sum;   
        char1=fgetc(Acompresser);
    ...

Discussions similaires

  1. Compresser un gros fichier texte?!
    Par swiber dans le forum C#
    Réponses: 2
    Dernier message: 29/04/2014, 19h02
  2. Lecture du contenu d'un fichier compressé en mode texte ?
    Par meles dans le forum Général Python
    Réponses: 8
    Dernier message: 17/10/2012, 19h30
  3. Compresser un fichier texte généré en PHP
    Par seb92500 dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 25/02/2008, 21h37
  4. Compression petits fichiers texte
    Par SCalc dans le forum Algorithmes et structures de données
    Réponses: 9
    Dernier message: 18/01/2007, 14h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo