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 :

Fonction de tirage au sort aléatoire.


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut Fonction de tirage au sort aléatoire.
    Salut les C,
    toujours dans l'optique du projet de mon mini-serveur HTTP qui choisie une image au (pseudo) hasard dans 5 dossiers différents j'ai un petit soucis dans ma fonction de tirage au sort de l'image qui soit pour 5 itérations soit:
    -me produit uneErreur de segmentation (core dumped).
    -ou tire une image au sort puis me produit une Erreur de segmentation (core dumped).
    dont voici le code:
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <time.h>
    #include <fcntl.h>
     
    int get_file_length(int fd) ;
     
    unsigned int rand_max(int seed, int maxi) ;
     
    struct Img_Data {
        char *final_img_dir ;
        char *final_img_file ; 
        char *tmp_img_dirname ;
      } *img_data ;
     
    void select_random_file(struct Img_Data *img_data ) ;
     
    int main(int argc, char *argv[]) {
     
      int c ;
     
      for (c = 0 ; c < 5 ;  c++)  {
     
          img_data=malloc(sizeof(struct Img_Data *))       ;
     
          img_data->final_img_dir=malloc(sizeof(char *))   ;
          img_data->final_img_file=malloc(sizeof(char *))  ;
          img_data->tmp_img_dirname=malloc(sizeof(char *)) ;
     
          select_random_file(img_data)    ;
     
          free(img_data->final_img_dir)   ; //Peut-être inutile voir ci-dessous
          free(img_data->final_img_file)  ; //Peut-être inutile voir ci-dessous
          free(img_data->tmp_img_dirname) ; //Peut-être inutile voir ci-dessous
          free(img_data) ; // Je ne sais si cet simple appel suffit               
          // Essayez avec un appel a 
          // sleep(1) ;      
        }
      return 0 ;
    }
     
     
    unsigned int rand_max(int seed, int maxi) {
      srand(seed) ;
     
      return ( ( (int) (rand()) )/ ((int) (RAND_MAX/maxi) ) ) ;
    } 
     
    void select_random_file(struct Img_Data *img_data ) {
     
      struct dirent *img_dir ;
     
      char root_dirname[NAME_MAX]="/home/mon_nom/C" ;
      char *dirname_0="/style_0/" ; // Sous-dossier de /home/mon_nom/C
      char *dirname_1="/style_1/" ; // Sous-dossier de /home/mon_nom/C
      char *dirname_2="/style_2/" ; // Sous-dossier de /home/mon_nom/C
      char *dirname_3="/style_3/" ; // Sous-dossier de /home/mon_nom/C
      char *dirname_4="/style_4/" ; // Sous-dossier de /home/mon_nom/C
     
      DIR  *root_img_dirname ;
     
      char *dirnames[5]={dirname_0,dirname_1,dirname_2,dirname_3,dirname_4} ;
     
      char *rand_filenames[]={}  ;
     
      time_t randseed ;
      randseed=time(NULL) ;
     
      img_data->final_img_dir=dirnames[rand_max(randseed,4)] ; // Tirage au sort d'un dossier
      img_data->tmp_img_dirname=strcat(root_dirname,img_data->final_img_dir) ; // Concatenation en chemin absolus
     
     
      int c=0 ;
      int file_counter=0 ;
     
      root_img_dirname=opendir(img_data->tmp_img_dirname) ;  // Ouverture dossier pour itération sur les fichiers contenus
     
      while ((img_dir=readdir(root_img_dirname)) != NULL) {
        // Parcours du repertoire selectionner au hasard
        if  ( (char) img_dir->d_name[0] != '.' )  {
          // Sauvegarde des noms de fichiers ( != '.' && != "..")
          // Pour tirage au sort
          rand_filenames[file_counter]=img_dir->d_name ;
          //printf("DEBUG: %s\n",img_dir->d_name) ;
          file_counter++ ;
        }
        c++ ;
        }
     
      randseed=time(NULL) ; 
      img_data->final_img_file=rand_filenames[rand_max(randseed,--file_counter)] ; // Tirage au sort du fichier.
     
      closedir(root_img_dirname) ;
      printf("Server relativ directory: %s\n",img_data->final_img_dir)  ; // Nom de dossier tirer au sort
      printf("Image file path         : %s\n",img_data->final_img_file) ; // Nom de fichier tirer au sort
     
     
    }
    PS: J'ai déjà produit le même algorithme avec au lieu d'une structure pour récupérer les données sur le fichier tirer au sort de simples pointeurs dans la même portée (scope) qui marchait mieux que le code montrer ci-dessus car il itérait les 5 fois mais ne supportait pas un appel a sleep(1). Et comme je pensais que le problème venait des variables pointeurs : j'ai implémenter une structure dans le but de la passer comme référence...

    J'attends vos réponses éclairées avec impatience, car je suis a cours d'argument pour savoir ce qui ne va pas avec mon code.

    PS: La compilation avec l'option -Wall est une bonne pratique que je vient de découvrir qui donne une sortie plus verbose du compilateur bien utile pour apprendre les bonnes manières de programmer en C.

  2. #2
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Bonjour,

    en lisant en diagonal ton code je m'arrête de suite sur tes allocations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct Img_Data {
        char *final_img_dir ;
        char *final_img_file ; 
        char *tmp_img_dirname ;
      } *img_data ;
    ...
          img_data=malloc(sizeof(struct Img_Data *))       ;
     
          img_data->final_img_dir=malloc(sizeof(char *))   ;
          img_data->final_img_file=malloc(sizeof(char *))  ;
          img_data->tmp_img_dirname=malloc(sizeof(char *)) ;
    img_data est un pointeur sur struct Img_Data ton premier malloc devrait plutôt ressembler à img_data=malloc(sizeof (struct Img_Data) ); car tu dois allouer de la place sur ce qui est pointé. Tu peux également écrire img_data=malloc(sizeof *img_data); (ce qui se lit comme «alloue de la mémoire pour ce vers quoi je veux pointer»).
    Les trois autres malloc sont également incorrects, pour allouer une chaine de longueur N (n caractères utiles) tu dois utiliser malloc ainsi : img_data->final_img_dir=malloc( (N+1) * sizeof (char) ); car tu veux pointer sur un endroit où il y aura assez de place pour stocker (N+1) char. J'ai écrit N+1 et non pas N car il faut penser qu'une chaine se termine toujours par un caractère nul qui marque la fin de la chaine : si tu veux stocker N caractères il faudra de la place pour ces N caractères plus le 0 terminal, d'où le +1. Tu peux te passer du sizeof (char) car il renverra toujours 1, mais en l'écrivant le code est plus clair sur ton intention (et ça ne mange pas de pain).
    Là où tu dois faire attention est que suivant le système tu n'as pas forcément l'équivalent 1 caractère affiché = 1 char (par exemple avec un encodage UTF8 le symbole/caractère 'é' utilise 2 char/byte).
    sizeof n'est pas une fonction mais un opérateur c'est pourquoi je me permets de l'écrire sans parenthèses quand le paramètre n'est pas un type (même si elles non plus ne mangent pas de pain , mais je suppose que tu n'écris jamais ++(a) sauf si c'est nécessaire)

    Très important : pour chaque malloc tu dois avoir un free et un seul. Tu le fais bien en sens inverse des allocations ().
    Je n'ai pas regardé ton code plus en avant.

    Remarque : -Wall c'est bien ! mais -Wall -Wextra c'est encore mieux

  3. #3
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    OUIAAAAAAS,
    J'y suis arriver a créer mon serveur d'affichage d'images aléatoire....
    MAIS je crois que je doit me mettre dans le coin avec le bonnet d'âne:
    j'explique en implémentant un serveur HTTP (statique) qui liste les répertoires concernées j'ai remarquer que le dossier supposer s'appeler style_0
    se nommait style _0
    et que les dossier style_3 et style_4
    était écrit en Style_3 et Style_4
    donc je pouvais me demander longtemps pourquoi le programme ne pouvait accéder a un espace mémoire (page) non définis (je ne sais si c'est le bonne formulation) et générai une erreur de segment mémoire.
    Brefs la bonne écriture se fait sans allocation de la structure et des membres:
    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
     
    while (1) {
          // img_data=malloc(sizeof(struct Img_Data *))              ; inutile !!!
     
          // img_data->final_img_dir=malloc(sizeof(char *))         ;  inutile !!!    
          // img_data->final_img_file=malloc(sizeof(char *))         ;  inutile !!!
          // img_data->tmp_img_dirname=malloc(sizeof(char *)) ;  inutile !!!
     
          select_random_file(img_data)    ;
     
          // free(img_data->final_img_dir)          ;   inutile !!! 
          // free(img_data->final_img_file)          ;  inutile !!!
          // free(img_data->tmp_img_dirname)  ;   inutile !!!
          // free(img_data) ;  inutile !!!  
    }
    Cela fonctionne parfaitement et le serveur ne quitte pas après plusieurs requêtes.

    Je ne reste pas sans méditer sur la réponse de kwariz car en débutant le C j'ai omis de jouer avec les allocation mémoires: Toutes variable dont l'espace mémoire non automatiquement allouer doit l'être avec un appel a malloc() et compagnie.

    Pour allouer de l'espace a un pointeur devant contenir un chemin de fichier|dossier faut-t-il écrire:

    char *pathname=malloc(NAME_MAX) ;
    ou
    char *pathname=malloc(sizeof(char *)) ;

    Car un pointeur stocke une adresse sur 32 bits (même sur des processeurs 64 bits, mais ça dépend toujours de quel système on programme) si j'ai bien compris ...???
    Si j'ai bien compris ce qu'a dit kwariz la première écriture est juste ce que j'ai du mal a comprendre (stockage d'adresse ???).

    Je regarderai plus attentivement plus tard la réponse de kwariz car ça fait des semaines que j'essaie d'implémenter ce serveur alors je profite de ma joie pour l'instant (avec mon bonnet d'âne bien sur).

    Pour résumer après avoir réussi je saute de partout dans la maison avec mon bonnet d'âne en criant ian ian de joie...

    PS: Merci pour le tuyau -Wall -Wextra

  4. #4
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Attention ... si tu n'alloues pas du tout c'est un coup de bol que ça fonctionne. Tôt ou tard ça va planter ...

    Pour mieux comprendre les pointeurs, il y a le cours sur dvp : les pointeurs du C.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2013] Fonction ALEA pour tirage au sort
    Par lesurfeurdargent dans le forum Excel
    Réponses: 2
    Dernier message: 17/10/2013, 15h34
  2. [XL-2003] Tirage au sort aléatoire
    Par PAUL87 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 11/10/2011, 12h03
  3. [XL-2003] Formule pour tirage au sort aléatoire
    Par MattLeBlanc dans le forum Excel
    Réponses: 5
    Dernier message: 16/07/2011, 12h20
  4. [MySQL] Tirage au sort aléatoire particulier
    Par marinms dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 07/12/2010, 17h30
  5. Quelle fonction pour faire un tirage au sort de noms
    Par Sofie109 dans le forum VBA Access
    Réponses: 6
    Dernier message: 01/06/2007, 14h52

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