[TABLEAUX 2D] comment passer un tableau 2D dans une fonction ?
cs_Zenith
Messages postés67Date d'inscriptionmardi 24 décembre 2002StatutMembreDernière intervention27 avril 2008
-
26 avril 2008 à 16:18
cs_jfrancois
Messages postés482Date d'inscriptionvendredi 26 août 2005StatutMembreDerniè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:
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;
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");
}
// 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 ...
cs_jfrancois
Messages postés482Date d'inscriptionvendredi 26 août 2005StatutMembreDernière intervention 5 décembre 20092 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.
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) :
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...
cs_Zenith
Messages postés67Date d'inscriptionmardi 24 décembre 2002StatutMembreDernière intervention27 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
cs_jfrancois
Messages postés482Date d'inscriptionvendredi 26 août 2005StatutMembreDernière intervention 5 décembre 20092 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)
cs_Zenith
Messages postés67Date d'inscriptionmardi 24 décembre 2002StatutMembreDernière intervention27 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)
{...}
cs_jfrancois
Messages postés482Date d'inscriptionvendredi 26 août 2005StatutMembreDernière intervention 5 décembre 20092 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;
}
}
cs_jfrancois
Messages postés482Date d'inscriptionvendredi 26 août 2005StatutMembreDernière intervention 5 décembre 20092 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 !
cs_Zenith
Messages postés67Date d'inscriptionmardi 24 décembre 2002StatutMembreDernière intervention27 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
cs_jfrancois
Messages postés482Date d'inscriptionvendredi 26 août 2005StatutMembreDernière intervention 5 décembre 20092 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 :
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 !!!
cs_Zenith
Messages postés67Date d'inscriptionmardi 24 décembre 2002StatutMembreDernière intervention27 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 ?
cs_Zenith
Messages postés67Date d'inscriptionmardi 24 décembre 2002StatutMembreDernière intervention27 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 ?
cs_jfrancois
Messages postés482Date d'inscriptionvendredi 26 août 2005StatutMembreDernière intervention 5 décembre 20092 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.