Partage
  • Partager sur Facebook
  • Partager sur Twitter

Ecriture dans les fichiers

Hors de la boucle il écrit, à l'intérieur non

    26 janvier 2021 à 15:46:08

    Bonjour à toutes et à tous,

    Certains me reconnaitront surement ahah

    J'en suis toujours au même code. Mais en parallèle de julia, je continue un peu sur le C.

    J'ai bien compris que faire le code avec le multi-threading serait hors de ma portée pour le moment, c'est pour quoi j'ai décidé de le faire de manière séquentiel.

    Alors oui, j'ai déjà un problème, même avec un code si simple, ce qui n'est guerre étaonnant car l'un d'entre vous m'avait préalablement prévenu.

    Le code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <windows.h>
    
    int maxi;
    char a[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    FILE* dico = NULL;
    
    int dictionnaire(way_of_file, mode, maxi)
    {
        printf("okok\n");
        int i = 0;
        int ii = 0;
        int len = strlen(a);
        int p = pow(len, maxi);
        char m[maxi + 2];
        m[maxi] = '\n';
        m[maxi + 1] = '\0';
        int h = 0;
    
    
        dico = fopen(way_of_file, mode);
    
        for (i = 0 ; i < p ; i++)
        {
            printf("boucle");
    
            for (ii = 0; ii < maxi; ii++)
            {
                h = rand() % strlen(a);
                m[ii] = a[h];
    
    
    
            }
            fprintf(dico, m);
        }
        fclose(dico);
    
        return 0;
    }
    
    int main()
    {
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico1.txt", "w", 3);
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico2.txt", "w", 4);
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico3.txt", "w", 5);
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico4.txt", "w", 6);
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico5.txt", "w", 7);
    
    
        return 0;
    }
    

    Voila le code en entier.

    Il y a probablement beaucoup d'erreur... Je m'en excuse d'avance :honte:

    En ce qui concerne mon soucis, c'est sur la partie de code ci-dessous :

    int main()
    {
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico1.txt", "w", 3);
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico2.txt", "w", 4);
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico3.txt", "w", 5);
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico4.txt", "w", 6);
        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico5.txt", "w", 7);
    
    
    
        return 0;
    }

    Ma fonction execute 5 fois la fonction dictionnaire, à qui j'envoie des valeurs en paramètre.

    Les 3 premières fois s'éxécutent sans accroche. Mais pour dico4 et dico5, le fichier est bien créé, mais rien est écrit dedans.

        dico = fopen(way_of_file, mode);
    
        for (i = 0 ; i < p ; i++)
        {
            printf("boucle");
    
            for (ii = 0; ii < maxi; ii++)
            {
                h = rand() % strlen(a);
                m[ii] = a[h];
    
    
    
            }
            fprintf(dico, m);
        }
        fclose(dico);

    Ce code étant celui me permettant d'écrire dans mon fichier, j'ai donc essayé de déplacer le "fprintf" en dehors de la boucle for, donc juste après l'ouverture du fichier

        dico = fopen(way_of_file, mode);
        fprintf(dico, "salut");
    
        for (i = 0 ; i < p ; i++)
        {
    
            for (ii = 0; ii < maxi; ii++)
            {
                h = rand() % strlen(a);
                m[ii] = a[h];
    
    
    
            }
            fprintf(dico, m);
        }
        fclose(dico);

    Eh bien la, dico4 et dico5 sont bien crée, et "salut" est bien écrit dedans.

    Je me doutes donc que le problème se situe dans la boucle for. Mais comment la boucle peut fonctionner pour dico1,2,3 et pas pour 4 et 5 ?

    J'ai vérifié les initialisation ds variables, mais il ne me semble pas qu'il y ait de problème de ce coté, je vous demande donc votre aide pour régler ce problème.

    Pour les paramètres de la fonction dictionnaire je n'ai pas mis les type de variable, car cela me créer une erreur... Erreur idiote probablement...

    Encore merci de votre aide constante,

    Passez une bonne journée,

    Flavien


    • Partager sur Facebook
    • Partager sur Twitter
      26 janvier 2021 à 15:52:40

      Toujours pas de type dans les paramètres de ta fonction ?

      int dictionnaire(way_of_file, mode, maxi);

      Il y a des règles de base pour faire du C ! En C les variables sont typées !

      • Partager sur Facebook
      • Partager sur Twitter
        26 janvier 2021 à 16:25:20

        rouloude a écrit:

        Toujours pas de type dans les paramètres de ta fonction ?

        int dictionnaire(way_of_file, mode, maxi);

        Il y a des règles de base pour faire du C ! En C les variables sont typées !


        yes, je l'avais dis dans mon message, et je comprends même pas pourquoi ca marche pas ! (enfin si, j'ai du faire une erreur dans le char)

        Sans les types : les fichiers sont bien tous ouverts et créé

        Avec les types : aucun fichier n'est créé !

        int dictionnaire(char way_of_file, char mode, int maxi)

        Une idée ?

        • Partager sur Facebook
        • Partager sur Twitter
          26 janvier 2021 à 16:26:56

          FunlY-Fla a écrit:

          [...]

          Voila le code en entier.

          Il y a probablement beaucoup d'erreur... Je m'en excuse d'avance :honte:

          [...]

          Bonjour,

          il ne faut pas s'excuser pour avoir fait des erreurs dans un code, tu peux t'excuser pour ne pas avoir écouté ^_^

          rouloude a écrit:

          Toujours pas de type dans les paramètres de ta fonction ?

          int dictionnaire(way_of_file, mode, maxi);

          Il y a des règles de base pour faire du C ! En C les variables sont typées !

          Rouloude te l'a dit à plusieurs reprises, le compilateur certainement aussi →

          $ gcc -Wall -Wextra -o vd vd.c -lm
          vd.c: In function ‘dictionnaire’:
          vd.c:11:5: warning: type of ‘way_of_file’ defaults to ‘int’ [-Wimplicit-int]
           int dictionnaire(way_of_file, mode, maxi)
               ^~~~~~~~~~~~
          vd.c:11:5: warning: type of ‘mode’ defaults to ‘int’ [-Wimplicit-int]
          vd.c:11:5: warning: type of ‘maxi’ defaults to ‘int’ [-Wimplicit-int]
          vd.c:23:18: warning: passing argument 1 of ‘fopen’ makes pointer from integer without a cast [-Wint-conversion]
               dico = fopen(way_of_file, mode);
                            ^~~~~~~~~~~
          In file included from vd.c:2:
          /usr/include/stdio.h:246:14: note: expected ‘const char * restrict’ but argument is of type ‘int’
           extern FILE *fopen (const char *__restrict __filename,
                        ^~~~~
          vd.c:23:31: warning: passing argument 2 of ‘fopen’ makes pointer from integer without a cast [-Wint-conversion]
               dico = fopen(way_of_file, mode);
                                         ^~~~
          In file included from vd.c:2:
          /usr/include/stdio.h:246:14: note: expected ‘const char * restrict’ but argument is of type ‘int’
           extern FILE *fopen (const char *__restrict __filename,
                        ^~~~~
          

          Quand tu as des warnings de ce genre (et c'est normal quand tu es un grand débutant qui s'attaque à la résolution d'un problème un peu ardu pour son niveau) il faut les résoudre.

          Maintenant grande question :

          pour créer des chaînes aléatoires en si grand nombre dans un premier lieu ! Parce que tu en demandes un sacré paquet !

          Pour info, un int est souvent codé sur 32 bits, comme il est signé le plus grand entier représentable est 2.147.483.647, or 52⁶=19.770.609.664 ⇒ il y a comme un petit problème …

          Que veux tu faire exactement ?

          Créer un fichier avec tous les tuples possibles ? En créer juste un certain nombre ?




          -
          Edité par White Crow 26 janvier 2021 à 16:29:41

          • Partager sur Facebook
          • Partager sur Twitter
            26 janvier 2021 à 16:37:47

            Hey whilte crow,

            Du coup, pour les types dans les para de dictionnaire j'ai expliqué au dessus, ùais ca marche pas, c'est pour ca que j'ai pas mis (on s'arrange comme on peut :lol:)

            En effet, pour la taille du int j'avais pas fait attention, un unsigned long ? et encore, je suis pas sur que la taille suffise.

            En effet, le but est de faire le maximum de combinaison possible, or, avec 52 lettres et des mots de 6 lettres, 52 exposant 6 = 20 milliards comme tu l'as dis...

            • Partager sur Facebook
            • Partager sur Twitter
              26 janvier 2021 à 16:48:21

              FunlY-Fla a écrit:

              Hey whilte crow,

              Du coup, pour les types dans les para de dictionnaire j'ai expliqué au dessus, ùais ca marche pas, c'est pour ca que j'ai pas mis (on s'arrange comme on peut :lol:)

              Tu n'as pas expliqué, tu nous as juste dit que … Tu ne nous as jamais montré ce que tu avais fait …

              FunlY-Fla a écrit:

              [...]
              En effet, le but est de faire le maximum de combinaison possible, or, avec 52 lettres et des mots de 6 lettres, 52 exposant 6 = 20 milliards comme tu l'as dis...

              Le maximum c'est tous les tuples …

              Combien t'en faut-il ? Attention un fichier texte avec tous les tuples de longueur 6 sur un alphabet de 52 caractères ça fait tout de même dans les 130 Go …

              Il faut commencer par mieux définir tes besoins.



              • Partager sur Facebook
              • Partager sur Twitter
                26 janvier 2021 à 17:22:41

                Je

                ne sais pas quoi vous montrer du coup, puisque rien ne se produit :(

                Avec les types : aucun créé ->

                	
                int dictionnaire(char way_of_file, char mode, int maxi)

                Process returned -1073741819 (0xC0000005)   execution time : 1.265 s

                Sans les types : tous créé ->

                	
                int dictionnaire(way_of_file, mode, maxi)

                Process returned 0 (0x0)   execution time : 113.050 s

                Niveau taille j'ai de quoi stocker. Mon but étant de faire après cela,  une fonction qui lira les mots dans les fichiers, et supprimera ceux qui sont en doubles (car avec des combinaisons aléatoire il y en a forcement)

                -
                Edité par Bunnntyyy 26 janvier 2021 à 17:23:02

                • Partager sur Facebook
                • Partager sur Twitter
                  26 janvier 2021 à 17:28:37

                  Parce que tu ne mets pas les bons types ! Je te les donne ça ne t'avancera pas dans la compréhension mais bon !

                  int dictionnaire(char *way_of_file, char *mode, int maxi);


                  Je me demande bien ce que tu veux faire avec ces fichiers gigantesques ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    26 janvier 2021 à 17:37:53

                    Je pense que la fonction 'dictionnaire' devrait être déclarée de type 'void', puisqu'elle est utilisée sans utilisation de son retour. D'ailleurs elle n'a rien à retourner (le « return 0 » sert juste à être compatible avec son type, mais son type n'est pas bien choisi).

                    -
                    Edité par robun 26 janvier 2021 à 17:50:44

                    • Partager sur Facebook
                    • Partager sur Twitter
                      26 janvier 2021 à 17:40:14

                      FunlY-Fla a écrit:

                      Je

                      ne sais pas quoi vous montrer du coup, puisque rien ne se produit :(

                      Avec les types : aucun créé ->

                      	
                      int dictionnaire(char way_of_file, char mode, int maxi)

                      Process returned -1073741819 (0xC0000005)   execution time : 1.265 s

                      Sans les types : tous créé ->

                      	
                      int dictionnaire(way_of_file, mode, maxi)

                      Process returned 0 (0x0)   execution time : 113.050 s

                      maintenant que tu nous a montré le code qui ne fonctionnait pas nous pouvons te dire que :

                      • une chaîne (pour faire hyper simple) dans la libc c'est char * et non pas char ;

                        int dictionnaire(char *way_of_file, char *mode, int maxi)
                        devrait mieux fonctionner …

                      • plus classiquement on utilise filepath que way_of_file comme nom de paramètre dans ce cas ; on n'utilise jamais un truc qui s'appelle way_of_file ;

                      • ton code est tombé accidentellement en marche car la taille d'un char * doit être la même qu'un int , ce qui me laisse penser que tu es sur un OS 32 bits.

                      FunlY-Fla a écrit:

                      Niveau taille j'ai de quoi stocker. Mon but étant de faire après cela,  une fonction qui lira les mots dans les fichiers, et supprimera ceux qui sont en doubles (car avec des combinaisons aléatoire il y en a forcement)

                      -
                      Edité par FunlY-Fla il y a moins de 30s

                       Si tu trouves que 150s c'est long alors je pense que tu trouveras qu'éliminer les doublons dans un fichier de 130+ Go sera très, voire extrêmement, long.

                      Si je devais produire un grand nombre de tuples je m'y prendrais d'une toute autre manière, que ce soit en C ou en python d'ailleurs.  Du coup je chercherais :

                      • une structure de donnée compacte permettant de savoir avec une grande confiance si une clé a déjà été rencontrée et qui ne donnerai au pire que de faux positifs ;
                      • je choisirais aléatoirement des nombres k entre 0 et 52ⁿ ;
                      • si la clé k n'a pas encore été rencontrée alors je la signalerai comme déjà vue sinon j'en choisi une autre ;
                      • je déterminerai l'écriture en base n de k (avec pour chiffres "abcde…WXYZ" et je l'écrirai dans le fichier.
                      et voilà voilà …


                      • Partager sur Facebook
                      • Partager sur Twitter
                        26 janvier 2021 à 17:59:20

                        dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico5.txt", "w", 7);

                        J'espère que tu as un gros disque dur ? Le fichier dico5.txt devrait faire environ 8 To si je ne me suis pas trompé !

                        • Partager sur Facebook
                        • Partager sur Twitter
                          26 janvier 2021 à 18:03:29

                          rouloude a écrit:

                          dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico5.txt", "w", 7);

                          J'espère que tu as un gros disque dur ? Le fichier dico5.txt devrait faire environ 8 To si je ne me suis pas trompé !


                          Pour Dico5 avec un tuple par ligne en mode texte : 52⁵*6/1024³ = 2.13 GiB.
                          Pour Dico7, 52⁷*8/1024⁴ = 7.48 TiB.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            26 janvier 2021 à 18:13:32

                            rouloude a écrit:

                            Parce que tu ne mets pas les bons types ! Je te les donne ça ne t'avancera pas dans la compréhension mais bon !

                            int dictionnaire(char *way_of_file, char *mode, int maxi);


                            Je me demande bien ce que tu veux faire avec ces fichiers gigantesques ?


                            Oh mais oui je suis bête !

                            fopen (const char*, const char*);

                            Il faut des pointeurs forcément !

                            -
                            Edité par Bunnntyyy 29 janvier 2021 à 18:59:14

                            • Partager sur Facebook
                            • Partager sur Twitter
                              29 janvier 2021 à 18:59:19

                              White Crow a écrit:

                              maintenant que tu nous a montré le code qui ne fonctionnait pas nous pouvons te dire que :

                              • une chaîne (pour faire hyper simple) dans la libc c'est char * et non pas char ;

                                1
                                int dictionnaire(char *way_of_file, char *mode, int maxi)
                                devrait mieux fonctionner …

                              • plus classiquement on utilise filepath que way_of_file comme nom de paramètre dans ce cas ; on n'utilise jamais un truc qui s'appelle way_of_file ;

                              • ton code est tombé accidentellement en marche car la taille d'un char * doit être la même qu'un int , ce qui me laisse penser que tu es sur un OS 32 bits

                              Pour l'histoire des pointeur j'ai compris ! J'aurais du vérifier le prototype dans stdlib...

                              Je vais de ce pas modifier mon nom de variable du chemin relatif de suite.

                              White Crow a écrit:

                               Si tu trouves que 150s c'est long alors je pense que tu trouveras qu'éliminer les doublons dans un fichier de 130+ Go sera très, voire extrêmement, long.

                              Si je devais produire un grand nombre de tuples je m'y prendrais d'une toute autre manière, que ce soit en C ou en python d'ailleurs.  Du coup je chercherais :

                              • une structure de donnée compacte permettant de savoir avec une grande confiance si une clé a déjà été rencontrée et qui ne donnerai au pire que de faux positifs ;
                              • je choisirais aléatoirement des nombres k entre 0 et 52ⁿ ;
                              • si la clé k n'a pas encore été rencontrée alors je la signalerai comme déjà vue sinon j'en choisi une autre ;
                              • je déterminerai l'écriture en base n de k (avec pour chiffres "abcde…WXYZ" et je l'écrirai dans le fichier.
                              et voilà voilà …




                              150sec me parait très rapide, contrairement aux 15 minutes sous python !

                              Tant que j'y suis, pourquoi utilises-tu le mot tuples ?

                              Ensuite :

                              Qu'entends tu par clé ? Une variable qui retient les combinaisons déjà faites, et ci elle est deja faite, alors on passe à une autre ?

                              Pour les nombres entre 0 et  52 c'est déjà fait du coup !

                              Enfait le réel problème avec mon code, est la taille des combinaisons possibles qui dépasse le possible ?

                              • Partager sur Facebook
                              • Partager sur Twitter
                                29 janvier 2021 à 19:24:41

                                C'est drôle, j'ai l'impression d'avoir vu ce message hier ou avant hier ? Alors que tu l'as posté il y a seulement 22 mn ?
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  29 janvier 2021 à 19:56:49

                                  FunlY-Fla a écrit:

                                  White Crow a écrit:

                                   Si tu trouves que 150s c'est long alors je pense que tu trouveras qu'éliminer les doublons dans un fichier de 130+ Go sera très, voire extrêmement, long.

                                  [...]

                                  150sec me parait très rapide, contrairement aux 15 minutes sous python !

                                  Si tu as 130+ Go de nombres (impossible à charger en mémoire actuellement), il va falloir, pour éliminer les doublons, énormément de temps … à mon avis bien plus que 150s, bien plus que 15 minutes … le plus simple étant un tri suivi d'un filtrage.

                                  Donc le plus simple serait de créer une liste sans doublons dès le départ. Ce qui est réalisable malgré le grand nombre de données que tu comptes générer.

                                  FunlY-Fla a écrit:

                                  Tant que j'y suis, pourquoi utilises-tu le mot tuples ?

                                  [...]

                                  Parce qu'on peut voir ces combinaisons de différentes façons. Par exemple tu peux les voir comme des mots, mais aussi comme des nombres. En considérant chacun des caractères comme un chiffre avec 'a'=0 (en décimal), 'b'=1, …, z='25', A='26', B='27', … Z='51' d'une écriture en base 52 ⇒ 'aamcA' = A+c*52+m*52²+a*52³+a*52⁴ = 26 + 2*52 + 12*52² + 0*52³ + 0*52⁴ = 32578.

                                  Je parle de tuple simplement dans le sens que la combinaison 'aamcA' correspond au tuple (A,c,m,a,a,a,a,a,a,a…). Avec un algorithme type odomètre tu les génères facilement tous.

                                  Le fait d'en faire un nombre permet par la suite d'utiliser ce nombre comme une clé que l'on peut utiliser pour marquer cette combinaison comme déjà générée.

                                  FunlY-Fla a écrit:

                                  Ensuite :

                                  Qu'entends tu par clé ? Une variable qui retient les combinaisons déjà faites, et ci elle est deja faite, alors on passe à une autre ?

                                  Pour les nombres entre 0 et  52 c'est déjà fait du coup !

                                  Enfait le réel problème avec mon code, est la taille des combinaisons possibles qui dépasse le possible ?

                                  Oui. Il y a une quantité presque déraisonnable de données. On ne peut pas simplement avoir un énorme tableau qui décrit si une combinaison a été ou non générée. Par exemple pour les 130 Go dont nous parlions au-dessus, un tableau de bits prendrait dans les 15Go …

                                  Heureusement il y a ce qu'on appelle les filtres de Bloom. Il s'agit d'une sdd très compacte qui permet avec assurance de ne pas générer du doublon, mais la contrepartie est que parfois certaines combinaisons seront considérées comme déjà générées alors qu'elles ne l'auront pas été. C'est une sdd probabiliste avec de faux positifs.

                                  Franchement c'est bien plus simple de générer toutes les combinaisons → algo de l'odomètre et basta.



                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    31 janvier 2021 à 10:50:06

                                    White Crow a écrit:


                                    Oui. Il y a une quantité presque déraisonnable de données. On ne peut pas simplement avoir un énorme tableau qui décrit si une combinaison a été ou non générée. Par exemple pour les 130 Go dont nous parlions au-dessus, un tableau de bits prendrait dans les 15Go …

                                    Heureusement il y a ce qu'on appelle les filtres de Bloom. Il s'agit d'une sdd très compacte qui permet avec assurance de ne pas générer du doublon, mais la contrepartie est que parfois certaines combinaisons seront considérées comme déjà générées alors qu'elles ne l'auront pas été. C'est une sdd probabiliste avec de faux positifs.

                                    Franchement c'est bien plus simple de générer toutes les combinaisons → algo de l'odomètre et basta.



                                    J'ai bien recherché les filtres de Bloom et l'algo de l’odomètre. Pour le premier j'ai trouvé, mais peut tu me dire si le site est intéressant ?

                                    https://www.partow.net/programming/bloomfilter/index.html

                                    Pour l'algo de l'odomètre, j'ai seulement trouvé des compteurs kilométrique... T'aurais une référence de site internet ?

                                    Encore merci,

                                    Bonne journée à toi !

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      31 janvier 2021 à 11:09:32

                                      White Crow a écrit:


                                      Si tu as 130+ Go de nombres (impossible à charger en mémoire actuellement), il va falloir, pour éliminer les doublons, énormément de temps … à mon avis bien plus que 150s, bien plus que 15 minutes … le plus simple étant un tri suivi d'un filtrage.



                                      Avec ce genre de volume de données, on cherche pas le plus simple, mais un truc qui a des chances de marcher (en commençant par rentrer en mémoire !).



                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        31 janvier 2021 à 11:44:35

                                        michelbillaud a écrit:

                                        White Crow a écrit:

                                        Si tu as 130+ Go de nombres (impossible à charger en mémoire actuellement), il va falloir, pour éliminer les doublons, énormément de temps … à mon avis bien plus que 150s, bien plus que 15 minutes … le plus simple étant un tri suivi d'un filtrage.



                                        Avec ce genre de volume de données, on cherche pas le plus simple, mais un truc qui a des chances de marcher (en commençant par rentrer en mémoire !).

                                        Avec ce volume de données il faut se rabattre sur des outils comme sort et uniq qui gèrent  bien ça normalement en le faisant directement sur les mémoires de masse. Ptêt une base sql ?

                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        Ecriture dans les fichiers

                                        × 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.
                                        • Editeur
                                        • Markdown