Parc d'attraction en C

Parc d'attraction en C - C - Programmation

Marsh Posté le 04-01-2014 à 15:02:04    

Bonjour,  
 
 J'ai un programme à faire pour la rentrée seulement là je suis complètement bloqué.  
 
 Voici l'énoncé :  
 
Citation: Nous considérons dans cet exercice, qu'un parc d'attraction comporte deux types d'attractions :  
 Les attractions dites "libres" auxquelles les visiteurs peuvent accéder librement, sans faire la queue et où ils peuvent rester le temps qu'ils souhaitent. Ces attractions peuvent être, par exemple, des animations. Nous considérons, dans cete exercice, que ce type d'attractions ne possède pas de limite au niveau du nombre de ses visiteurs.  
 Les attractions dites "contrôlées" pour lesquelles les visiteurs doivent faire la queue et payer un droit d'entrée. Pour simplifier l'exercice, nous considérons que les clients ne peuvent plus sortir de la queue une fois qu'ils y sont. Par ailleurs, ils en sortent dans le même ordre qu'ils y sont entrés. Bien sûr, une attraction de ce type ne peut admettre qu'un nombre limité de visiteurs. Contrairement aux attractions "libres",une fois entrés dans une attraction "contrôlée", les visiteurs sont contraints d'y rester le temps qu'elle dure celle-ci.  
 
 Dès lors qu'un visiteur quitte une attraction, il est libre d'y rester le temps qu'il souhaite dans les allées du parc avant de retourner dans une autre attraction ou même de quitter le parc.  
 Ecrivez un programme qui simule une journée de fonctionnement d'un tel parc d'attraction.  
 
Voilà de là j'en ai déduit qu'il fallait un thread pour chaque attraction, la même chose pour chaque visiteur. Il faut également un tableau de sémaphores pour gérer les attractions "controlée". A cela j'ai ajouté quelques fonctionnalités comme la gestion du porte monnaie des visiteurs par rapport au coût des attractions contrôlées et je donne aussi l'attraction la plus visité en fonction de son type.  
 
 
Seulement j'ai une erreur de segmentation --'
 
 
le fichier : http://cjoint.com/?0AepbiGK8TN
PS : L'application doit être developpée sur un Linux .  
 
 Merci d'avance  
 
 Cordialement  
 
 Winflow
 

Reply

Marsh Posté le 04-01-2014 à 15:02:04   

Reply

Marsh Posté le 10-01-2014 à 13:05:04    

Bonjour,
je suis entrain de lire ton code. Avant de pouvoir mes corrections, je te suggère d'utiliser valgrind pour trouver les problèmes d'allocations de mémoire. Il me semble que l'erreur de segmentation viennent de tes pointeurs. Si tu trouve l'erreur fait moi savoir.
 
 
Cordialement,


Message édité par akdjib le 10-01-2014 à 13:05:32
Reply

Marsh Posté le 10-01-2014 à 16:57:17    

Hmm, j'arrive sans doute après la guerre, mais juste histoire d'avoir une réponse :
 

  • La ligne 134 ne me paraît pas bonne. Tu passes NULL comme argument au démarrage de ton thread, thread qui s'attend à avoir un pointeur (valide) sur une structure PERSONNE => SEG FAULT.
  • Petite faute de frappe ligne 125. Tu as écrit tabAttrac_P[i].visite = 0; tu voulais sans doute écrire tabAttrac_F[i].visite = 0;
  • Ta logique du gestion du parc me semble fausse. Lorsqu'une personne choisi une attraction, elle appelle directement la fonction du thread. La personne devrait se mettre dans un file d'attente, mettre à jour une sémaphore lié au thread et laisser le thread de l'attraction gérer ça. Tu vas devoir changer pas mal le code à ce niveau.


Pour référence, le code était (edit: arf, j'ai changé 2 ou 3 trois dans les prototypes pour faire tourner le code sous Windows, pas sûr d'avoir tout remis dans l'ordre) :

Code :
  1. // Includes
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include <pthread.h>
  6. #include <semaphore.h>
  7.  
  8. // Constantes
  9. #define NB_PERS_MAX 100
  10. #define NB_ATTRACTION 5
  11. #define TIME_ATTRAC_MAX 12
  12. #define PERS_MAX_ATTRAC 10
  13. #define TPS_OUVERTURE_PARC 120
  14. #define ARGENT_MAX 50
  15. #define COUT_MAX 2
  16.  
  17. // Definition du type state correspondant
  18. // aux états qu'une personne peut avoir
  19. typedef enum
  20. {
  21.     ARR = 0, FREE, PAY, QUIT
  22. }STATE;
  23.  
  24. // Définition de la structure personne
  25. typedef struct
  26. {
  27.     int id;
  28.     STATE etat;
  29.     int temps; // temps passé dans le parc d'attractions
  30.     int money; // Optionnel
  31. }PERSONNE;
  32. // Définition de la structure Attraction gratuite
  33. typedef struct
  34. {
  35.     int id;
  36.     int visite;
  37. }ATTRACTION_FREE;
  38. // Définition de la structure attraction payante
  39. typedef struct
  40. {
  41.     int id;
  42.     int capacite; // Capacité de l'attraction
  43.     int temps; // Durée de l'attraction
  44.     int visite;
  45.     int cout; // Optionnel
  46. }ATTRACTION_PAY;
  47. // Structure permmettant de stocker l'id et le nombre de visite de l'attraction la plus visitée
  48. typedef struct
  49. {
  50.     int max;
  51.     int id;
  52. }SEARCHMAX;
  53.  
  54.  
  55. // Variables globales
  56. // Tableau de sémaphore
  57. sem_t* sem;
  58.  
  59. ATTRACTION_PAY* tabAttrac_P;
  60. ATTRACTION_FREE* tabAttrac_F;
  61. int nbAttrac_P;
  62. int nbAttrac_F;
  63. int temps;
  64. // Prototypes des handlers
  65. void * handlerAttrac (void*);
  66. void * handlerPers (void*);
  67. int timer (void);
  68.  
  69. int main (void)
  70. {
  71.     /// Déclarations
  72.  
  73.     int nbPers;
  74.  
  75.     int i;
  76.     SEARCHMAX maxAP;
  77.     SEARCHMAX maxAF;
  78.     int somme = 0;
  79.     PERSONNE* tabPers;
  80.     pthread_t* tabThreadP; // Une personne correspond à un thread
  81.  
  82.     // Une attraction payante correspond à un thread
  83.     pthread_t* tabThreadAttrac_P;
  84.  
  85.  
  86.     // Définition des nombres aléatoires
  87.  
  88.     // Génère un nombre aléatoire de personnes entre 1 et 100
  89.     nbPers = rand()%NB_PERS_MAX+1;
  90.     // Génère un nombre aléatoire d'attraction payante entre 1 et 4
  91.     nbAttrac_P = (rand()%(NB_ATTRACTION-1)) + 1;
  92.     // Les attractions qui restent sont donc gratuites
  93.     nbAttrac_F = NB_ATTRACTION - nbAttrac_P;
  94.     // Allocation dynamique pour les personnes
  95.     tabPers = (PERSONNE*) malloc (nbPers*sizeof (PERSONNE));
  96.     tabThreadP = (pthread_t*) malloc (nbPers*sizeof (pthread_t));
  97.     // Allocation dynamique pour les attractions payantes
  98.     tabAttrac_P = (ATTRACTION_PAY*) malloc (nbAttrac_P*sizeof (ATTRACTION_PAY));
  99.     tabThreadAttrac_P = (pthread_t*) malloc (nbAttrac_P*sizeof (pthread_t));
  100.     // Allocation dynamique pour les attractions gratuites
  101.     tabAttrac_F = (ATTRACTION_FREE*) malloc (nbAttrac_F*sizeof (ATTRACTION_FREE));
  102.     // Allocation dynamique du tableau de semaphore
  103.     sem = (sem_t*) malloc (nbAttrac_P*sizeof (sem_t));
  104.     // Initialisation des structures personnes
  105.     for (i = 0; i < nbPers; i++)
  106.     {
  107.         tabPers[i].id = i;
  108.         tabPers[i].etat = ARR;        // Toutes les personnes arrivent
  109.         tabPers[i].temps = 0;    // Gestion du temps passé dans le parc
  110.         tabPers[i].money = rand ()%ARGENT_MAX;
  111.     }
  112.     // Initialisation des structures attractions payantes et des semaphores
  113.     for (i = 0; i < nbAttrac_P; i++)
  114.     {
  115.         tabAttrac_P[i].id = i;
  116.         tabAttrac_P[i].temps = rand()%TIME_ATTRAC_MAX+1;
  117.         tabAttrac_P[i].capacite = rand()%PERS_MAX_ATTRAC+1;
  118.         tabAttrac_P[i].visite = 0;
  119.         tabAttrac_P[i].cout = rand()%COUT_MAX+1 ;
  120.         sem_init (&sem[i], 0, rand()%PERS_MAX_ATTRAC+1);
  121.     }
  122.     // Initialisation des structures attractions gratuites
  123.     for (i = 0; i < nbAttrac_F; i++)
  124.     {
  125.         tabAttrac_F[i].id = i;
  126.         tabAttrac_F[i].visite = 0;
  127.     }
  128.     puts ("Bienvenue à DigiWorld ! : OUVERTURE DES PORTES DU PARC" );
  129.  
  130.     // Création des threads pour les personnes
  131.     for (i = 0; i < nbPers; i++)
  132.         pthread_create (&tabThreadP[i], NULL, handlerPers, &tabPers[i]);
  133.     // Création des threads pour les attractions payantes
  134.     for (i = 0; i < nbAttrac_P; i++)
  135.         pthread_create (&tabThreadAttrac_P[i], NULL, handlerAttrac, NULL);
  136.  
  137.     // Attente des threads
  138.     while (temps < TPS_OUVERTURE_PARC)
  139.         timer();
  140.  
  141.     for (i = 0; i < nbPers; i++)
  142.         pthread_join(tabThreadP[i], NULL);
  143.     for (i = 0; i < nbAttrac_P; i++)
  144.         pthread_join(tabThreadAttrac_P[i], NULL);
  145.  
  146.     // Expulsion des personnes
  147.     for (i = 0; i < nbPers; i++)
  148.     {
  149.         tabPers[i].etat = QUIT;        // Toutes les personnes partent
  150.         somme += tabPers[i].temps;
  151.     }
  152.     puts ("DigiWorld : A Bientot  ! : FERMETURE DES PORTES DU PARC" );
  153.     // Recherche des max dans les deux types d'attractions
  154.     maxAP.max = 0;
  155.     maxAP.id = 0;
  156.     maxAF.max = 0;
  157.     maxAF.id = 0;
  158.     // Attractions payantes
  159.     for ( i = 0 ; i < nbAttrac_P ; i++)
  160.     {
  161.         if (tabAttrac_P[i].visite > maxAP.max)
  162.         {
  163.             maxAP.max = tabAttrac_P[i].visite;
  164.             maxAP.id = i;
  165.         }
  166.         else
  167.         {
  168.             maxAP.max = maxAP.max;
  169.             maxAP.id = maxAP.id;
  170.         }
  171.     }
  172.  
  173.     // Attractions gratuites
  174.     for ( i = 0 ; i < nbAttrac_F ; i++)
  175.     {
  176.         if (tabAttrac_F[i].visite > maxAF.max)
  177.         {
  178.             maxAF.max = tabAttrac_F[i].visite;
  179.             maxAF.id = i;
  180.         }
  181.  
  182.     }
  183.     // Résumé de la journée
  184.     printf ("%d personnes ont visité le parc aujourd'hui \n", nbPers);
  185.     printf ("et ont passé en moyenne %d min %d s dans le parc \n", (somme/nbPers)/60, (somme/nbPers)%60);
  186.     if (nbAttrac_F > 0)
  187.         printf ("L'attraction gratuite la plus visitée est l'attraction %d avec %d visites\n", maxAF.id, maxAF.max);
  188.     printf ("L'attraction payante la plus visitée est l'attraction %d avec %d visites\n", maxAP.id, maxAP.max);
  189.     // Libération de la mémoire
  190.     free (tabPers);
  191.     free (tabThreadP);
  192.     free (tabAttrac_P);
  193.     free (tabThreadAttrac_P);
  194.     free (tabAttrac_F);
  195.     return 0;
  196. }
  197. // Fonction qui compte le temps
  198. int timer ()
  199. {
  200.     sleep(1);
  201.     return ++temps;
  202. }
  203.  
  204. // Fonction pour les threads des attractions payantes
  205. void * handlerAttrac (void* personne)
  206. {
  207.     int ind;
  208.     PERSONNE * p = (PERSONNE *) personne;
  209.     float tmpn;
  210.     int actuelTemps;
  211.     // Indice aléatoir du tableau
  212.     ind = rand()%nbAttrac_P;
  213.     // Vérification si la personne est solvable
  214.     tmpn = p->money - tabAttrac_P[ind].cout;
  215.     if (tmpn < 0)
  216.     {
  217.         p->etat = (rand ()%2)+1;
  218.         handlerPers(p);
  219.         return;
  220.     }
  221.     else
  222.     {
  223.         actuelTemps = temps;
  224.         // TQ que le parc est ouvert on essaye de faire une prise de sémaphore
  225.         while (temps < TPS_OUVERTURE_PARC)
  226.         {
  227.             while (sem_wait (&sem[ind]) == -1);
  228.         }
  229.  
  230.         if (temps >= TPS_OUVERTURE_PARC)
  231.         {
  232.             p->etat = QUIT;
  233.             return;
  234.         }
  235.         else
  236.         {
  237.             tabAttrac_P[ind].visite++;
  238.             p->money -= tabAttrac_P[ind].cout;
  239.             p->temps += temps - actuelTemps;
  240.             return;
  241.         }
  242.  
  243.     }
  244.  
  245. }
  246. void * handlerPers (void* visiteur)
  247. {
  248.     PERSONNE* pers = (PERSONNE*) visiteur;
  249.     // TQ on ne dépasse pas le temps d'ouverture du parc
  250.     while (temps <= TPS_OUVERTURE_PARC)
  251.     {
  252.         // Selon l'état dans lequel la personne se trouve...
  253.         switch (pers->etat)
  254.         {
  255.             case ARR :
  256.                     // Etat initial
  257.                     // Changement d'état
  258.                     pers->etat = (rand ()%2)+1;
  259.                     return;
  260.                     break;
  261.             case FREE:
  262.                     // Etat Attraction libre
  263.                     // Incrémentation du temps
  264.                     pers->temps += (rand()%TPS_OUVERTURE_PARC)+1;
  265.                     // +1 visite
  266.                     tabAttrac_F [(rand ()%nbAttrac_F)+1].visite++;
  267.                     // Changement d'état
  268.                     pers->etat = (rand ()%3)+1;
  269.                     return;
  270.                     break;
  271.             case PAY :
  272.                     // Etat Attraction payante
  273.                     handlerAttrac(pers);
  274.                     return;
  275.                     break;
  276.             case QUIT :
  277.                     // Quitte Digiworld
  278.                     return;
  279.                     break;
  280.         }
  281.     }
  282.     pers->etat = QUIT;
  283.     return;
  284. }


Message édité par tpierron le 10-01-2014 à 17:01:52
Reply

Marsh Posté le 11-01-2014 à 10:05:08    

Bonjour
As-tu remarqué qu'une attraction libre n'était qu'une attraction contrôlée dont certaines valeurs étaient inutilisées ?
Tu aurais pu n'utiliser qu'une seule structure commune pour les deux types en mettant les valeurs inutilisées à 0 ou -1...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 11-01-2014 à 15:24:22    

Citation :


  • La ligne 134 ne me paraît pas bonne. Tu passes NULL comme argument au démarrage de ton thread, thread qui s'attend à avoir un pointeur (valide) sur une structure PERSONNE => SEG FAULT.  



Il suffit de vérifier que le pointeur soit non null si oui return

Citation :


  • Petite faute de frappe ligne 125. Tu as écrit tabAttrac_P[i].visite = 0; tu voulais sans doute écrire tabAttrac_F[i].visite = 0;  



Ok je modifie de suite.

Citation :


  • La personne devrait se mettre dans un file d'attente, mettre à jour une sémaphore lié au thread et laisser le thread de l'attraction gérer ça. Tu vas devoir changer pas mal le code à ce niveau.



Comment gérer cet aspect du programme dans ce cas ? Je suis d'accord sur le fait d'appeler la fonction du thread mais je ne voyais pas comment faire autrement.

Citation :

As-tu remarqué qu'une attraction libre n'était qu'une attraction contrôlée dont certaines valeurs étaient inutilisées ?  
Tu aurais pu n'utiliser qu'une seule structure commune pour les deux types en mettant les valeurs inutilisées à 0 ou -1...


Oui je m'en suis bien rendu compte mais j'essaie d'aller au plus vite car je dois rendre le programme et le rapport demain ><

Message cité 1 fois
Message édité par rohffr le 11-01-2014 à 16:07:56
Reply

Marsh Posté le 11-01-2014 à 16:07:25    

Citation :

La ligne 134 ne me paraît pas bonne. Tu passes NULL comme argument au démarrage de ton thread, thread qui s'attend à avoir un pointeur (valide) sur une structure PERSONNE => SEG FAULT.  


Réglé

Citation :

Petite faute de frappe ligne 125. Tu as écrit tabAttrac_P[i].visite = 0; tu voulais sans doute écrire tabAttrac_F[i].visite = 0;


Réglé
 
Seulement lors de mes affichages à la fin du programme j'affiche que des zéros

Reply

Marsh Posté le 12-01-2014 à 18:07:08    

rohffr a écrit :

Oui je m'en suis bien rendu compte mais j'essaie d'aller au plus vite car je dois rendre le programme et le rapport demain ><


Mauvais calcul. Parfois, prendre quelques minutes pour bien poser les bases te fait gagner ensuite 10 fois plus de temps dans le codage. parce que tu peux utiliser des boucles pour traiter tes éléments au lieu de dupliquer tes instructions ou tes variables. Et etc...
 

rohffr a écrit :

Seulement lors de mes affichages à la fin du programme j'affiche que des zéros


Ben faudrait que tu affiches tes variables à différents moments critiques de ton code !!!
 


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed