Boucle for et pointeur

Boucle for et pointeur - C - Programmation

Marsh Posté le 29-12-2009 à 23:02:46    

Bonjour
 
Je suis actuellement sur un projet en C et j'ai un tableau de structures (avec 2 champs) qui ressemble à ça:
 
http://ups.imagup.com/06/1262171485.png
 
j'utilise donc des pointeurs *diti et *fiti qui pointent sur des cases du tableau, ce que je voudrais c'est parcourir ce tableau à l'aide d'une boucle for j'ai donc fait ça avec un pointeur test :
 
for(test = diti ; test < (fiti+1) ; test++)
 {
   ................................................................
 }
 
seulement ça ne fonctionne pas, la boucle est infinie...
 
Merci d'avance pour votre aide  ;)

Reply

Marsh Posté le 29-12-2009 à 23:02:46   

Reply

Marsh Posté le 30-12-2009 à 00:14:48    

En informatique, il y a quatre grandes étapes :
 
- analyse
- programmation
- test
- debug
 
Cette quatrième étape est inévitable. Il ne faut donc pas avoir peur de l'affronter dès maintenant.
Cela consiste souvent à mettre des traces, pour voir comment évolue le programme.
 
Dans votre cas, je conseillerais de mettre ces deux lignes avant d'entrer dans la boucle, pour voir si les bornes sont bien celles que vous croyez avoir :

fprintf(stderr, "diti=%ld, (fiti+1)=%ld", (long int)(diti), (long int)(fiti+1));
exit(0);

Reply

Marsh Posté le 30-12-2009 à 00:45:44    

Hmm. Debugger au fprintf, on a quand même vu mieux. Il vaut mieux apprendre directement à utiliser un debugger, outil essentiel à tout développeur, pour toute sa carrière. Autant s'y mettre le plus tôt possible, c'est un gain de temps considérable.

Reply

Marsh Posté le 30-12-2009 à 00:55:11    

Tant qu'on aura pas le code source, on ne fera que parler dans le vide sans avoir de chances de cerner la cause du pb.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 30-12-2009 à 01:17:14    

Bon je l'avais pas mis complet parce qu'il est un peu long mais si vous y tenez  :D  
 
A noter que j'ai courcircuité toute la première partie qui ne sert qu'à entrer les données en mettant toute les infos directement dans les tableaux afin de tester la nouvelle fonction crée c'est à dire la fonction optimise()
 
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. /*Déclarations des fonctions*/
  5. void ajout_ville();
  6. void distance();
  7. void parcours();
  8. void purger();
  9. void optimise();
  10. /*Déclarations des constantes*/
  11. #define LONGNOM 30
  12. #define NB_VILLES 20
  13. #define NB_CHEMINS 5
  14. /*Déclarations des variables globales*/
  15. int *nbvilles;
  16. char ville[NB_VILLES][LONGNOM]={"paris","arras","reims","dijon","metz"};
  17. struct {
  18.         short ville_suiv;
  19.         short distance;
  20.        } chemin[NB_VILLES][NB_CHEMINS]={{{1,170},{2,140},{3,315},{-1,0},{-1,0}},{{0,170},{4,345},{2,160},{-1,0},{-1,0}},{{0,140},{1,160},{4,175},{-1,0},{-1,0}},{{0,315},{4,235},{-1,0},{-1,0},{-1,0}},{{1,345},{2,175},{3,235},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}},{{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}}};;
  21. typedef struct
  22.        {
  23.         short numville;
  24.         short numsuiv;
  25.        } DITI;
  26. int main()
  27. {
  28. /*Déclarations des variables locales*/
  29. int i,j;
  30. char code[8];
  31. nbvilles=0;
  32. /*Initialisation du tableau 'chemin'
  33. for(i=0;i<NB_VILLES;i++)
  34.   {
  35.    for(j=0;j<NB_CHEMINS;j++)
  36.     {
  37.      chemin[i][j].ville_suiv=-1;
  38.     }
  39.   }*/
  40. /*Affichage du menu*/
  41. while(strcmp(code,"quitter" )!=0)
  42. {
  43.   printf("-Pour entrer une nouvelle ville, tapez 'ville'\n" );
  44.   printf("-Pour entrer une distance entre 2 villes, tapez 'distance'\n" );
  45.   printf("-Pour calculer un parcours, tapez 'parcours'\n" );
  46.   printf("-Pour rechercher l'itinéraire optimal entre deux villes, tapez 'optimise'\n" );
  47.   printf("-Pour quitter le programme, tapez 'quitter'\n" );
  48.   scanf("%s",code);
  49.   purger();
  50.   if(strcmp(code,"ville" )==0) ajout_ville(&nbvilles);
  51.   else if(strcmp(code,"distance" )==0) distance(&nbvilles);
  52.   else if(strcmp(code,"parcours" )==0) parcours(&nbvilles);
  53.   else if(strcmp(code,"optimise" )==0) optimise(&nbvilles);
  54. }
  55. return 0;
  56. }
  57. void ajout_ville(int *nbvilles)
  58. {
  59.   int i;
  60.   char nomville[LONGNOM];
  61.   /*Vérification qu'on ne depasse pas la capacité du tableau*/
  62.   if(*nbvilles>=NB_VILLES)
  63.    {
  64.     printf("Vous avez atteint le nombre maximum de villes\n" );
  65.     return;
  66.    }
  67.   /*Entrée de la nouvelle ville*/
  68.   (*nbvilles)++;
  69.   printf("Entrez le nom de la nouvelle ville:\n" );
  70.   scanf("%s",nomville);
  71.   purger();
  72.   /*Vérification que la ville n'est pas déjà existante*/
  73.   for(i=0;i<*nbvilles;i++)
  74.    {
  75.     if(strcmp(ville[i],nomville)==0)
  76.      {
  77.       printf("La ville existe déjà !\n" );
  78.       (*nbvilles)--;
  79.       return;
  80.      }
  81.    }
  82.   /*Copie de la ville dans le tableau*/
  83.   strcpy(ville[*nbvilles-1],nomville);
  84. }
  85. void distance(int *nbvilles)
  86. {
  87.   char ville1[LONGNOM],ville2[LONGNOM];
  88.   int longueur, depart, arrivee, i;
  89.   depart=21;
  90.   arrivee=21;
  91.   /*Entrée des villes et de la distance*/
  92.   printf("Entrez la première ville\n" );
  93.   scanf("%s",ville1);
  94.   purger();
  95.   printf("Entrez la deuxième ville\n" );
  96.   scanf("%s",ville2);
  97.   purger();
  98.   printf("Entrez la distance entre les 2\n" );
  99.   scanf("%i",&longueur);
  100.   purger();
  101.   /*Recherche des villes dans le tableau*/
  102.   for(i=0;i<*nbvilles;i++)
  103.    {
  104.     if(strcmp(ville[i],ville1)==0) depart=i;
  105.     if(strcmp(ville[i],ville2)==0) arrivee=i;
  106.    }
  107.   /*Vérification que les 2 villes existent*/
  108.   if(depart==21)
  109.    {
  110.     printf("La ville %s n'existe pas ! (Utilisez le module 'Entrer une ville')\n\n",ville1);
  111.     return;
  112.    }
  113.   if(arrivee==21)
  114.    {
  115.     printf("La ville %s n'existe pas ! (Utilisez le module 'Entrer une ville')\n\n",ville2);
  116.     return;
  117.    }
  118.   /*Entrées des informations dans le tableau chemin*/
  119.   i=0;
  120.   while(chemin[depart][i].ville_suiv!=-1) i++;
  121.     chemin[depart][i].ville_suiv=arrivee;
  122.     chemin[depart][i].distance=longueur;
  123.   i=0;
  124.   while (chemin[arrivee][i].ville_suiv!=-1) i++;
  125.     chemin[arrivee][i].ville_suiv=depart;
  126.     chemin[arrivee][i].distance=longueur;
  127. }
  128. void parcours(int *nbvilles)
  129. {
  130.   int i,j,k,ville_courante,longueur,ville_precedente;
  131.   longueur=0;
  132.   /*Affichage de toutes les villes avec leur numéro*/
  133.   for(i=0;i<*nbvilles;i++) printf("%i-%s\n",i,ville[i]);
  134.   /*Demande de saisie de la ville de départ*/
  135.   printf("Entrez le numéro de la ville de départ:\n" );
  136.   scanf("%i",&ville_courante);
  137.   purger();
  138.  
  139.   i=0;
  140.   while(chemin[ville_courante][i].ville_suiv!=-1)
  141.    {
  142.     printf("Destinations possibles:\n" );
  143.     for(j=0;chemin[ville_courante][j].ville_suiv!=-1;j++) printf("%i-%s\n",chemin[ville_courante][j].ville_suiv,ville[chemin[ville_courante][j].ville_suiv]);
  144.     printf("La longueur totale parcourue est de %i Km\n",longueur);
  145.     ville_precedente=ville_courante;
  146.     i=0;
  147.     printf("Entrez le numéro de la ville suivante:\n" );
  148.     scanf("%i",&ville_courante);
  149.     purger();
  150.     while(ville_precedente==ville_courante)
  151.      {
  152.       printf("Vous etes déja à %s, entrez une autre ville svp:\n",ville[ville_courante]);
  153.       scanf("%i",&ville_courante);
  154.       purger();
  155.      }
  156.     if(ville_courante==99) return;
  157.     k=0;
  158.     while(chemin[ville_courante][k].ville_suiv!=ville_precedente) k++;
  159.     longueur+=chemin[ville_courante][k].distance;
  160.     i++;
  161.    }
  162.     printf("Il n'y a pas d'autres villes suivantes ! (Utilisez le module 'Entrer une distance')\n\n" );
  163.   }
  164. void optimise(int *nbvilles)
  165. {
  166. *nbvilles=5;
  167.   /*Déclarations des variables locales*/
  168.   DITI *diti;
  169.   DITI *fiti;
  170.   DITI *test;
  171.   int long_opti,optimal[NB_VILLES],nbville_opti,i,long_iti,ville_fin,j;
  172.   short sortie;
  173.   /*Allocation des pointeurs*/
  174.   diti=malloc(sizeof(DITI));
  175.   fiti=malloc(sizeof(DITI));
  176.   test=malloc(sizeof(DITI));
  177. for(i=0;i<NB_VILLES;i++)
  178.   {
  179.    for(j=0;j<NB_CHEMINS;j++)
  180.     {
  181.      printf("%i\n",chemin[i][j].ville_suiv);
  182.     }
  183.   }
  184.   /*Initialisation des variables*/
  185.   long_opti=32000;
  186.   long_iti=0;
  187.   nbville_opti=0;
  188.   sortie=0;
  189.   /*Demande du choix de l'itinéraire*/
  190.   printf("Villes disponibles:\n" );
  191.   for(i=0;i<*nbvilles;i++) printf("%i-%s\n",i,ville[i]);
  192.   printf("Entrez l'itinéraire à calculer\n" );
  193.   printf("N° de la ville de départ\n" );
  194.   scanf("%hi",&diti->numville);
  195.   purger();
  196.   printf("N° de la ville d'arrivée\n" );
  197.   scanf("%i",&ville_fin);
  198.   purger();
  199.   /*On met le premier chemin à essayer dans la première case du tableau*/
  200.   if(chemin[0][diti->numville].ville_suiv!=-1) diti->numsuiv=0;
  201.   else printf("Il n'y a aucun chemin qui part de cette ville !\n" );
  202.   fiti=diti;
  203.   /*Boucle jusqu'à la fin de la recherche*/
  204.   while(sortie!=1)
  205.    {
  206.     if(chemin[fiti->numsuiv][fiti->numville].ville_suiv!=-1)
  207.      {
  208.       (fiti+1)->numville=chemin[fiti->numsuiv][fiti->numville].ville_suiv;
  209.       (fiti+1)->numsuiv=0;
  210.      }
  211.     else
  212.      {
  213.       fiti--;
  214.       if (fiti==diti) sortie=1;
  215.      }
  216.     /*Recherche si la ville n'est pas déjà présente*/
  217.     for(test=diti;test<(fiti+1);test++)
  218.      {
  219.       if((fiti+1)->numville==test->numville)
  220.        {
  221.         (fiti->numsuiv)++;
  222.         (fiti+1)->numville=chemin[fiti->numsuiv][fiti->numville].ville_suiv;
  223.         break;
  224.        }
  225.       else
  226.        {
  227.         long_iti+=chemin[fiti->numsuiv][fiti->numville].distance;
  228.         nbville_opti++;
  229.         fiti++;
  230.        }
  231.      }
  232.       if(fiti->numville==ville_fin && long_iti<long_opti)
  233.        {
  234.         long_opti=long_iti;
  235.         for(i=0;i<nbville_opti;i++) optimal[i]=(diti+i)->numville;
  236.         fiti--;
  237.         long_iti-=chemin[fiti->numville][fiti->numsuiv].distance;
  238.         nbville_opti--;
  239.         fiti->numsuiv++;
  240.        }
  241.     }
  242.   /*On affiche la longueur totale et la liste des villes traversés*/
  243.   printf("La distance la plus courte entre %s et %s est de %i Km\n",ville[diti->numville],ville[ville_fin],long_opti);
  244.   printf("Liste des villes traversées:\n" );
  245.   for(i=0;i<nbville_opti;i++) printf("%s\n",ville[optimal[i]]);
  246. }
  247. void purger()
  248. {
  249.   int c;
  250.   while ((c=getchar()) != '\n' && c != EOF)
  251.   {}
  252. }

Reply

Marsh Posté le 30-12-2009 à 10:50:30    

Je ne comprends pas votre logique:

Code :
  1. DITI *diti;
  2.   DITI *fiti;
  3.   DITI *test;
  4.  
  5.   /*Allocation des pointeurs*/
  6.   diti=malloc(sizeof(DITI));
  7.   fiti=malloc(sizeof(DITI));
  8.   test=malloc(sizeof(DITI));


Vous déclarez vos pointeurs et allouez la structure pointée. OK.

 

Mais ensuite, vous faites des allègrement des fiti++ et fiti-- alors que l'on n'a pas créé un tableau de DITI et donc que fiti++ a priori pointe sur n'importe quoi.
Ça ne marche pas pour les mêmes raisons dans la ligne
for (test=diti;test<(fiti+1);test++)
Nulle part vous n'avez réservé les adresses mémoires entre diti et fiti pour les utiliser comme des pointeurs sur des DITI (alloués je ne sais ou)
J'ai comme l'impression que vous avec pensé allouer un tableau et puis vous ne l'avez pas fait (peut être parce que vous n'en connaissiez pas la taille, variable).

 
Code :
  1. if(chemin[fiti->numsuiv][fiti->numville].ville_suiv!=-1)
  2.      {
  3.       (fiti+1)->numville=chemin[fiti->numsuiv][fiti->numville].ville_suiv;
  4.       (fiti+1)->numsuiv=0;
  5.      }


c'est ici que votre logique pêche: logiquement, ça devrait planter ici à l'exécution vu que fiti+1 peut à priori pointer sur n'importe quoi. Il y a plusieurs méthodes à envisager pour faire ce que vous voulez.
Soit vous utilisez un tableau de pointeurs sur des DITI, auquel cas vous vous devez faire un malloc pour la structure sur laquelle va pointer fiti+1, et alors seulement remplir cette structure. Mais votre algo devra tester que vous ne dépassez pas la taille du tableau.
Soit vous vous utilisez un tableau de DITI, et vous pouvez remplir la structure. Il sera alors plus simple d'utiliser des indexs que des pointeurs. Mais votre algo devra tester que vous ne dépassez pas la taille du tableau.
Soit vous utilisez une liste doublement chainée, vous avez a gérer des champs fiti->suivant et fiti->precedent au lieu de fiti++ et fiti-- et vous vous vous devez faire un malloc pour la structure sur laquelle va pointer fiti->suivant ici et alors seulement remplir cette structure.
A+,

Message cité 1 fois
Message édité par gilou le 30-12-2009 à 11:29:52

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 31-12-2009 à 18:29:25    

Bonjour,
 
tout d'abord merci de vous être penché sur le problème
 

gilou a écrit :

Je ne comprends pas votre logique:


 
La logique est  bonne, en fait comme au départ on a fiti=diti, faire fiti+1 reviens à incrémenter fiti de 4 octets (structure de 2 entiers courts) et donc fiti+1 ne pointe pas n'importe ou, il pointera vers l'adresse de diti[1] et je vous prouve ce que j'avance, voici le screen du programme qui fonctionne (les problèmes ne venaient pas de la boucle for mais du reste de la fonction):
 
http://ups.imagup.com/06/1262328034.png
http://ups.imagup.com/06/1262328069.png
 
J'ai mis des printf dans le for, on voit bien le pointeur se déplacer de 4 octets, en tout cas problème résolu  :bounce:  
 
a+  :hello:

Reply

Marsh Posté le 01-01-2010 à 01:01:12    

DISASTER! ... quesqu' on a pas mis encore sur
cette page!!!!  :ouch:

Reply

Marsh Posté le 01-01-2010 à 11:46:45    

Bonjour et bonne année à tous !
 
Je viens enfin de comprendre ce qu'a essayé de me dire Gilou (mieux vaut tard que jamais !!!) il est vrai que les adresses du tableau diti ne sont pas allouées (d'ailleurs je ne comprends pas pourquoi ça ne plante pas....) j'ai donc essayé ça:
 
  /*Allocation des pointeurs*/
  for(i=0;i<*nbvilles;i++) diti[i]=malloc(sizeof(DITI));
 
mais pourquoi j'ai "D10.c:197: erreur: incompatible types in assignment" je capte pas

Reply

Marsh Posté le 01-01-2010 à 11:48:45    

Citation :

La logique est  bonne, en fait comme au départ on a fiti=diti, faire fiti+1 reviens à incrémenter fiti de 4 octets (structure de 2 entiers courts) et donc fiti+1 ne pointe pas n'importe ou, il pointera vers l'adresse de diti[1] et je vous prouve ce que j'avance, voici le screen du programme qui fonctionne (les problèmes ne venaient pas de la boucle for mais du reste de la fonction):

Non: fiti est un pointeur sur une structure DITI.
faire fiti+1 incrémente fiti de la taille de la structure pointée DITI (éventuellement alignée) en effet, et fiti interprète cela comme une structure DITI mais rien ne dit que c'en est une. Mais si cette zone pointée n'a pas été allouée pour y mettre une structure DITI (et je n'ai pas vu cela dans votre code), en fait, après l'incrémentation, fiti pointe sur n'importe quoi, interprété comme un DITI.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 01-01-2010 à 11:48:45   

Reply

Marsh Posté le 01-01-2010 à 11:51:26    

Citation :

diti[i]=malloc(sizeof(DITI));

diti est déclaré comme un pointeur, pas comme un tableau de pointeur, voila pourquoi ça coince.
Vous aimeriez déclarer DITI diti[*nbvilles];  mais comme on est en C  ce n'est pas possible.

 

On doit donc passer par une déclaration dynamique de ce type: DITI *diti = malloc(*nbvilles*sizeof(DITI)); déclare diti comme un pointeur sur un DITI mais on en a alloué *nbvilles consécutifs.  il faudra gérer la libération de ce qui est alloué en fin de fonction.

 

Ou alors, vous faites plus bourrin: DITI diti[NB_VILLES]; avec un tableau de la taille maximale.

 

A+,


Message édité par gilou le 01-01-2010 à 12:22:30

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 01-01-2010 à 14:33:51    

Ok merci ça fonctionne, je m'embrouille encore un peu avec les pointeurs mais ça commence à rentrer, ce que je trouve génant avec le c c'est que même quand un programme fonctionne, le code n'est pas forcément bien écrit, c'est pas évident quand on veut apprendre....

Reply

Marsh Posté le 01-01-2010 à 15:09:15    

jamsss a écrit :

Ok merci ça fonctionne, je m'embrouille encore un peu avec les pointeurs mais ça commence à rentrer, ce que je trouve génant avec le c c'est que même quand un programme fonctionne, le code n'est pas forcément bien écrit, c'est pas évident quand on veut apprendre....

Petit a petit, en progressant, on apprend a écrire du code C propre.
 
Typiquement dans votre programme, nbvilles n'est pas kosher dans ses usages:
int *nbvilles; déclaré comme globale
Or nbvilles n'est employé comme variable que dans main et donc ce devrait être une variable locale à main).
distance(&nbvilles);
Or nbvilles n'est pas modifié par distance on devrait donc avoir distance(nbvilles); et le code de distance modifié pour employer un nombre et non un pointeur sur un nombre.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 01-01-2010 à 17:47:44    

oui je suis d'accord pour *nbvilles, au départ je l'avais déclaré en local dans main, ce qui passait très bien sur un premier PC (avec mandriva 64 bits) et qui ne passait plus sur un deuxième PC (avec mandriva 32 bits), je l'ai mis en globale et le problème a semblé résolu (à moins que ça vienne de gcc mais je pense que c'est la même version ou alors c'est autre chose...)

Reply

Marsh Posté le 13-01-2010 à 21:31:38    

Le problème a peut être semblé résolu, mais il ne l'était pas. :)
Quand un programme passe sur un compilo et pas sur un autre, c'est le plus souvent que le programme a un vrai problème, et que par chance, un des compilos compense, par hasard, le problème. Je me souviens d'un compilo C DEC qui initialisait à 0 toute variable numérique pas initialisée, et à "" toute chaine pas initialisée, etc. C'était sympa, mais ça camouflait les erreurs d'initialisation, lesquelles se manifestaient tout de suite à l'exécution du programme sur une machine SUN (après compilation du même source, par gcc).
 
Il est rare qu'on ait besoin d'une globale dans un programme C (les cas qui me viennent en tête sont des cas ou cette variable peut être accédée/modifiée par quelque chose d'externe au programme), au pire, une variable est déclarée dans le corps de main.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

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