[TABLEAUX 2D] comment passer un tableau 2D dans une fonction ?

cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008 - 26 avril 2008 à 16:18
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 - 27 avril 2008 à 20:10
bonjour, je suis novice en C, et je voudrais passer un tableau 2D dans une fonction.
le but de mon programme est de générer 6 combinaisons de 6 entiers toutres distinces en prenant des nombres entre 1 et 49 inclus: voici mon code ou il me retourne des errueurs que je ne comprends pas:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int hasard(int min, int max);
void grille(int cmp[][2],int li);

int main(int argc, char *argv[])
{
    srand(time(NULL));
    int i,n, cmp[49][2];
     for(i=0;i<49;i++)
     {
         cmp[i][0]=i+1;
         cmp[i][1]=0;
     }
      system("PAUSE"); // le programme plante juste apres ce pause
    for(i=0;i<6;i++)
    {
        grille(cmp,49);
        printf("\n");           
    }
    system("PAUSE");   
return 0;
}

// genere entier aleatoire entre min et max inclus
int hasard(int min, int max)
{
    return (int) (min + ((float) rand() / RAND_MAX * (max - min + 1)));
}

// genere une grille de 6 numeros distince des autres grilles generees
void grille(int cmp[][2],int li)
{
     int i, j, k, e, nb;

     for(i=0;i<6;i++)
     {
        e=0;
        do
        {
          nb=hasard(1,49);
          while(cmp[k][0]!=nb && k<li)
          {
            k=k+1;
          }
          if (cmp[k][1]==0)
          {
            cmp[k][1]=1;
            printf("%d ",nb);
            e=1;
          }else
          {
               e=0;
          }
        }while(e=0);
     }
}

voila, merci de m'aider j'en peux plus

merci d'avance

16 réponses

cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
26 avril 2008 à 16:35
Bonjour,

Il manque k=0 dans grille(), avant, ou au début, de la boucle i. Avec ça ne plante plus !

Jean-François
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
26 avril 2008 à 16:38
... et pas besoin de passer par float pour générer un nombre aléatoire :

int hasard(int min,int max)
{
   return (rand() % (max - min + 1)) + min;
}

Jean-François
0
cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008
27 avril 2008 à 07:29
merci ! j'ai corrigé avec vos conseils, et enlevé la fonction grille, pour la mettre direct dans le code, comme c'est pas enorme:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int hasard(int min, int max);
void grille(int cmp[],int util[],int li);

int main(int argc, char *argv[])
{
    srand(time(NULL));
    int m, n, s, i, k, e, nb, cmp[49],util[49];
  
   
        printf("8 grilles de 6 numeros a genere:\n\n");
        for(m=0;m<49;m++)
        {
            cmp[m]=m+1;
            util[m]=0;
        }
       
        for(m=0;m<8;m++) // pour chaque grille
        {
             for(i=0;i<6;i++) // pour chaque numero de la grille
             { // genere un numero distinct des autres deja utilisés
                  e=0;
                  do
                  { 
                       nb=hasard(1,49);
                       k=0;
                       while(cmp[k]!=nb)
                       {
                            k=k+1;
                       }
                       if (util[k]==0)
                       {
                            util[k]=1;
                            printf("%d ",nb);
                            e=1;
                       }else
                       {
                            e=0;
                       }
                  }while(e=0);
             }
             printf("\n");      
        }
       
        printf("\n\n[ ");
        s=0;
        for(m=0;m<49;m++)
        {
            printf("%d : %d  fois\n",cmp[m],util[m]);
            s=s+util[m];
        }
        printf("\nsoit %d/49 numeros utilises ]\n\n",s);
//    }     
  system("PAUSE");   
  return 0;
}

// genere entier aleatoire entre min et max inclus
int hasard(int min, int max)
{
    return (rand() % (max - min + 1)) + min;
}

mais maintenant mon probleme est que le code me genere des combinaisons allant de 1 a 6 numeros, alors que moi j'en veux que de 6 pile, j'ai beau relire je vois pas, some help ?

normalement sur 8 grilles il devrait utiliser 8*6 numeros, c'est a dire 48, mais pour ma derniere execution, j'arrive a 30, je comprends pas trop d'ou ca sort ca ...

merci en tous cas pour votre aide :)
0
cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008
27 avril 2008 à 07:30
j'ai oublié de supprimer le prototype de grille dans mon dernier message
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
27 avril 2008 à 11:37
Voici une réécriture rapide qui donne un résultat correct.
 
1) Pensez à utiliser des noms de variables qui veulent dire quelque chose, ça aide énormément à l'écriture et à la compréhension (certains commentaires deviennent totalement inutiles) . Une variable sur une lettre c'est bien pour un indice de boucle très local mais dans un traitement plus important on ne comprend plus et il y a trop de riques de la modifier par inadvertance. Le code généré par le compilateur n'a aucun rapport avec la longueur des noms de variables et les disques durs font des centaines de Go alors profitons-en !

2) Pensez aussi à paramétrer. Eviter les valeurs "en dur" comme 6, 8 et 49. Placez-les dans des variables ou des constantes (qui veulent dire quelque chose là aussi !) et le programme devient facilement modifiable. Dans la version ci-dessous, pour avoir 10 grilles, il suffit de modifier iNbGrilles = 10 et recompiler sans se passer en revue tout le programme.

3) Bonne chance au LOTO !

#include <stdio.h>
#include <stdlib.h>
#include <time.h>



int main(int argc,char **argv)
{
   const int iNbGrilles =  8; // nb grilles à générer
   const int iNbTirages =  6; // nb tirages / grille   const int iNbMax     49; // nb max à tirer (min 1)



   bool abGrille[iNbMax];
   int  aiCompteurs[iNbMax];
   int  iGrille,iTirage,iMax;
   int  iHazard,iTotal;
  




   // --- Initialiser les compteurs globaux
   for (iMax=0 ; iMax




   // --- Générer les grilles

   printf("Generer %d grilles de %d numeros\n\n",iNbGrilles,iNbTirages);
   srand(time(NULL));
   for (iGrille=0 ; iGrille




      // --- Remplir la grille
      for (iTirage=0 ; iTirage




            // --- Conserver ce nombre s'il n'a pas déjà été tiré
            // --- (RAPPEL : les indices commencent à zéro !)
            if (! abGrille[iHazard - 1])
            {
               abGrille[iHazard - 1] = true;
               ++aiCompteurs[iHazard - 1];
               break;
            }
         }
      }




      // --- Montrer la grille
      // --- (les tirages sont naturellement ordonnés)
      printf("Grille %d :",iGrille + 1);
      for (iMax=0 ; iMax




   // --- Montrer les compteurs globaux et le total
   printf("\n");
   iTotal = 0;
   for (iMax=0 ; iMax



   system("PAUSE");   
   return 0;
}


Ce qui donne (différent à chaque exécution bien sûr) :

Generer 8 grilles de 6 numeros



Grille 1 :  7 15 17 18 28 44
Grille 2 :  9 14 17 19 29 41
Grille 3 :  8  9 14 15 35 48
Grille 4 : 10 12 33 37 45 47
Grille 5 :  1 11 17 24 30 37
Grille 6 :  6  9 22 25 30 33
Grille 7 :  2  6 25 29 40 44
Grille 8 :  4 16 20 32 37 40



 1 : 1 fois
 2 : 1 fois
 3 : 0 fois
 4 : 1 fois
 5 : 0 fois
 6 : 2 fois
 7 : 1 fois
 8 : 1 fois
 9 : 3 fois
10 : 1 fois
11 : 1 fois
12 : 1 fois
13 : 0 fois
14 : 2 fois
15 : 2 fois
16 : 1 fois
17 : 3 fois
18 : 1 fois
19 : 1 fois
20 : 1 fois
21 : 0 fois
22 : 1 fois
23 : 0 fois
24 : 1 fois
25 : 2 fois
26 : 0 fois
27 : 0 fois
28 : 1 fois
29 : 2 fois
30 : 2 fois
31 : 0 fois
32 : 1 fois
33 : 2 fois
34 : 0 fois
35 : 1 fois
36 : 0 fois
37 : 3 fois
38 : 0 fois
39 : 0 fois
40 : 2 fois
41 : 1 fois
42 : 0 fois
43 : 0 fois
44 : 2 fois
45 : 1 fois
46 : 0 fois
47 : 1 fois
48 : 1 fois
49 : 0 fois



soit 48 numeros utilises / 49 numeros disponibles
Appuyez sur une touche pour continuer...


Jean-François
0
cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008
27 avril 2008 à 15:39
bon, deja un grand merci a toi jfrancois pour tes conseils et surtout pour t'etre cassé la tete a tout reecrire !!
je regarderai ca plus en détail ce soir, mais deja la, a premiere vue, il y a un probleme, c'est que par exemple, 14 et 15 ont ete utilise chacun 2 fois. Ce que je voulais faire a la base, c'est de faire en sorte que sur 8 tirages de 6 numeros par exemple, 6*8=48 nombres soient utilisés une et une fois seulement, c'est pour ca que je fesait tout mon patakes avec la variable e(=0 si on na pas tire un nombre unique et =1 si c'est ce cas) ansi que les tableaux cmp[] et util[](qui contient soit 1 soit 0 si le nombre a deja ete utilise une fois ou pas)

merci en tous cas pour tes conseils sur l'interet de bien nommer ses variables et de mettre des parametres plustot que des nombres en dur, je pense que tu as raison ... ca m'aurai permi de faciliter la relecture aussi je pense ... j'ai merdé lol

merci encore,
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
27 avril 2008 à 15:52
J'avais pas compris ça en effet !
Il suffit de remplacer un test et c'est bon :

            // --- Conserver ce nombre s'il n'a pas déjà été tiré
            // --- (RAPPEL : les indices commencent à zéro !)
            //if (! abGrille[iHazard - 1])
            if (aiCompteurs[iHazard - 1] == 0)

Jean-François
0
cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008
27 avril 2008 à 17:07
merci ca marche !!!

mais j'aurais 2 questions:
- est ce que j'ai bien compri?
        -> abGrille[] sert a stocker si oui ou non le nombre "indice+1" a deja ete utilisé
        -> aiCompteurs[] sert a compter le nombre de fois qu'a ete utilise "indice+1"
- est ce que la boucle suivante ne devrait pas etre infinie ? la condition ne change jamais: true est toujours egal a true:

        // --- Les tirages doivent être différents
         while (true)
         {...}

merci, a bientot
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
27 avril 2008 à 17:55
- Les décalages de 1 sont dus aux indices qui commencent à zéro.

- abGrille[] est un tableau de booléens qui marque le tirage d'un nombre dans une grille (ce tableau est initialisé au début de chaque grille).

- aiCompteurs[] est un tableau de compteurs globaux des nombres tirés (il n'est pas réinitialisé au début de chaque grille). Il sert aussi à ne pas retirer 2 fois le même nombre dans toutes les grilles (avec la dernière modification).

- La boucle while (true) est infinie. On en sort avec le break (on casse la boucle) quand on a trouvé le bon nombre. C'est une structure très pratique qui évite de s'encombrer d'indicateurs et/ou de tests.

         // --- Les tirages doivent être différents
         while (true)
         {
            // --- Tirer un nombre au hazard entre 1 et 'iNbMax'
            iHazard = (rand() % iNbMax) + 1;
            // --- Conserver ce nombre s'il n'a pas déjà été tiré
            // --- (RAPPEL : les indices commencent à zéro !)
            if (aiCompteurs[iHazard - 1] == 0)
            {
               abGrille[iHazard - 1] = true;
               ++aiCompteurs[iHazard - 1];
               break;
            }
         }

Jean-François
0
cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008
27 avril 2008 à 18:00
aaah ok ! en fait lecassage de la boucle avec break sert a remplacer mon e=1 ou 0 c'est ca ?

ok, ok je vois mieux maintenant. merci jfrancois c'est sympa.
a bientot :)
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
27 avril 2008 à 18:23
En effet ça élimine cette variable.

Une petite remarque concernant cette boucle infinie : Avec le choix de ne pas avoir 2 fois le même nombre sur l'ensemble des grilles, il ne faudra pas augmenter le nombre de grilles au-delà de 8. A partir de 9 (précisément à partir du deuxième tirage de cette 9ème grille) cette boucle deviendra réellement infinie puisqu'aucun nombre ne sera disponible !

Jean-François
0
cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008
27 avril 2008 à 18:48
meme si j'augmente le nombre de numero disponibles (en fesant
const int iNbMax=(iNbGrilles*iNbTirages); ) ?

HS: j'aurais une question de plus a te poser, mais qui n'a rien a voir. Comme je vois que t'y connais bien, je suis sous Devcpp (windows) et je voudrais tester si la connection internet est active, si c'est le cas, j'ouvre www.google.fr, sinon, je ne fais rien. aurai tu une idée des include que je dois faire, ainsi que les fonctions a utiliser ? j'ai cherché sur le site, j'ai vu qu'ils parlaient de InternetGetConnectedState(), mais je n'ai pas trop compri son utilisation

merci encore, et desole de te casser les pieds avec mes petites questions la
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
27 avril 2008 à 19:29
1) C'est possible d'initialiser iNbMax comme ça mais ça n'est plus le LOTO ! Il n'y a que 49 boules, à partir de 9 grilles (9x6=54) il faut admettre qu'il y aura des doublons.

2) Je ne connaissais pas la fonction InternetGetConnectedState(). Je viens de la tester comme ça :

#include <stdio.h>
#include <windows.h>
#include <wininet.h>



#pragma comment(lib,"wininet.lib")



int main(void)
{
   DWORD Word;
   if (InternetGetConnectedState(&Word,0))
      printf("Connecte a Internet\n");
   else
      printf("Non connecte a Internet\n");
   return 0;
}


Ce qui donne :

Connecte a Internet

Ce qui est vrai ! Mais si je coupe mon modem/routeur d'Internet, le programme continue de me dire que je suis connecté ! Et il est vrai que l'ordinateur se voie toujours connecté ... mais au routeur (réseau local) pas à Internet. Il faut donc utiliser une méthode qui provoque vraiment une connexion extérieure (un ping sur un site par exemple) pour passer le routeur. J'utilise cette fonction (je programme en anglais !) :

#include <stdio.h>
#include <winsock2.h>



#pragma comment(lib,"ws2_32.lib")






// =====================================================
// Is the Web connected ?
// (Method of the ping with a website to bypass any LAN)
// =====================================================
bool IsWebConnected
(
   const char* pszWebSite // I:website to ping
)                         // O:Web connected
{
   // --- Quit if incorrect website data to ping
   if (pszWebSite == NULL) return false;
   if (*pszWebSite == 0) return false;






   // --- Initialise the use of "Ws2_32.dll"
   WSADATA WSAData;
   if (WSAStartup(MAKEWORD(2,2),&WSAData) != 0) return false;



  
   // --- Create a socket that is bound to a specific service provider
   SOCKET Socket = socket(AF_INET,SOCK_STREAM,0);
   if (Socket == INVALID_SOCKET)
   {
      WSACleanup();
      return false;
   }



  
   // --- Retrieve the host information
   // --- corresponding to a host name from a host database
   bool     bRet = false;
   HOSTENT* Host = gethostbyname(pszWebSite);
   if (Host)
   {
      SOCKADDR_IN SocketIn;
      SocketIn.sin_family           = AF_INET;
      SocketIn.sin_port             = htons(80); // HTTP port
      SocketIn.sin_addr.S_un.S_addr = (DWORD)*((DWORD*)Host->h_addr_list[0]);      if (connect(Socket,(SOCKADDR*)&SocketIn,sizeof(SOCKADDR_IN)) 0) bRet true;
   }






   // --- Release the resources
   closesocket(Socket);
   WSACleanup();
   return bRet;
}





int main(void)
{
   if (IsWebConnected("
www.google.fr
"))
      printf("Connecte a Internet\n");
   else
      printf("Non connecte a Internet\n");
   return 0;
}


Et là la réponse est correcte par rapport à Internet (qq secondes d'attente en cas de non connection).
Eviter de mettre un site qui puisse être indisponible !!!

Jean-François
0
cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008
27 avril 2008 à 19:37
ok, ok, un grand merci a toi, je vais essayer de comprendre la fonction, mais je pense pas y arriver avec mon niveau ...
je vais la copier coller pour l'utiliser, et la taffer ce soir, merci a toi vraiment !

par contre, je viens de la tester, et il me met plein de [Linker error], c'est peut etre les include qui sont pas bons ?
0
cs_Zenith Messages postés 67 Date d'inscription mardi 24 décembre 2002 Statut Membre Dernière intervention 27 avril 2008
27 avril 2008 à 19:37
ok, ok, un grand merci a toi, je vais essayer de comprendre la fonction, mais je pense pas y arriver avec mon niveau ...
je vais la copier coller pour l'utiliser, et la taffer ce soir, merci a toi vraiment !

par contre, je viens de la tester, et il me met plein de [Linker error], c'est peut etre les include qui sont pas bons ?
0
cs_jfrancois Messages postés 482 Date d'inscription vendredi 26 août 2005 Statut Membre Dernière intervention 5 décembre 2009 2
27 avril 2008 à 20:10
Un copier/coller est amplement suffisant au début; le principal étant que ça fonctionne.

Je n'ai aucune erreur à la compilation/édition des liens et le programme est complet mais je suis sous Visual C++ 6.0, il y a certainement des paramètres différents (des *.lib présents par défaut) avec Devcpp que je ne connais pas.

Jean-François
0
Rejoignez-nous