[C++] Problème avec les tableaux

Problème avec les tableaux [C++] - Programmation

Marsh Posté le 21-06-2001 à 10:23:02    

Je voudrais créer un tableau de bool en fonction de la taille x*y que donne l'utilisateur.
 
Pour cela j'emplois:
 
int Fonction(int x, int y)
{
bool bTableau[x][y];
}
 
Mais VC++ ne veut pas compiler car x et y ne sont constants. Comment faire alors un tableau de la bonne dimension?

 

[edit]--Message édité par Alload--[/edit]

Reply

Marsh Posté le 21-06-2001 à 10:23:02   

Reply

Marsh Posté le 21-06-2001 à 10:28:24    

Salut,
 
Essaie de rajouter const aux paramètres de ta fonction, sinon dans ce le meiux c'est d'utiliser malloc. Bon personnellement je te recommande la deuxième solution. :sol:  
 
@+
Archangel


---------------
J'suis timide - Prêt à mourir, mais pas à vivre - Je suis vraiement très fatigué ... - more than meets the eye
Reply

Marsh Posté le 21-06-2001 à 10:31:08    

Et c'est quoi donc ce malloc?

Reply

Marsh Posté le 21-06-2001 à 11:04:26    

c'est pour faire une allocation dynamique de la memoire !!!

Code :
  1. int Fonction(int x, int y)
  2. {
  3. int i;
  4. int j;
  5. bool** bTableau=(bool**)NULL;
  6. bTableau=(bool**)malloc(sizeof(bool*)*x);
  7. if (bTableau==(bool**)NULL) return(-1); // erreur
  8. for (i=0;i<x;i++) bTableau[i]=(bool*)NULL;
  9. for (i=0;i<x;i++) {
  10.   bTableau[i]=(bool*)malloc(sizeof(bool)*y);
  11.   if (bTableau[i]==(bool*)NULL) {
  12.    // erreur, il faut desalloué ce qui à deja été alloué
  13.     for (j=0;j<i;j++) free(bTableau[j]);
  14.     free(bTableau);
  15.    // on quitte la fonction
  16.     return(-1);
  17.     }
  18.   }
  19. // utilisation du tableau
  20. // fin du programme
  21. // attention il ne faut oublier de desallouer le tableau à la fin
  22.   for (i=0;i<x;i++) free(bTableau[i]);
  23.   free(bTableau);
  24.   return(1);
  25. }

Reply

Marsh Posté le 21-06-2001 à 11:11:33    

en c++, on peut faire :    
   

Code :
  1. class BoolTab
  2. {
  3.   int w, h;
  4.  bool* tab;
  5. public:
  6.   BoolTab(int x, int y) : w(x),h(y)
  7.     { tab= new bool[w*h]; }
  8.   ~BoolTab() { delete [] tab; }
  9.   bool& operator () (int x, int y) { return tab[x+y*w]; }
  10. };

   
   
et ensuite dans ton programme tu fais (par exemple) :    
   
BoolTab btab(x,y);    
   
btab(0,0)= true;    
if (btab(1,0)) fonction();

 

[edit]--Message édité par tgrx--[/edit]

Reply

Marsh Posté le 21-06-2001 à 11:44:07    

Faudrait apprendre a darkoli la fonction calloc, parce que boucler dans le tableau pour tout mettre a zero quand ca peut tres bien etre fait a la creation, c'est pas optimal.
Perso, je ferais ainsi:
 
bool* p=(bool*)calloc(x*y,sizeof(bool));  
if (!p)
    return (-1);
//et tu utilises ca de la maniere suivante:
// la valeur tab[i][j] correspond a *(p+(i*y)+j)
// avec bien sur 0<=i<x et 0<=j<y
 
A+,


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

Marsh Posté le 21-06-2001 à 13:41:51    

la difference entre calloc et malloc c'est quoi ?
 
svp ne m'insulter pas je n'ai pas forcement presenter un bout de code optimal, mais le but est plus de comprendre comment ca marche que tu file filer un truc optimale plus complexe a comprendre qu'on y connait pas grand chose.
 
Perso moi aussi je fais :

Code :
  1. bool* p=(bool*)malloc(sizeof(bool)*(x*y)); 
  2. if (p!=bool) return (-1);


 
pour l'accés sa donne aussi : p[(j*y)+i]
 
attention pour l'acces il y a deux possibilité :
  soit x colonne et y ligne : p[(j*x)+i]
  soit x ligne et y colonne : p[(i*y)+j]
 
  i e [0,x[, j e [0,y[
 
c'est pour ca que le  tableau à deux dimension c'est bien quand tu n'as pas l'habitude parce sinon il fait faire tres attention.

Reply

Marsh Posté le 21-06-2001 à 20:28:49    

Quand je lance mon programme, il y a une erreur disant que la mémoire ne peut être écrite.
 
Je pense que le problème vient de la manière dont je définis les différent valeur bool de mon tableau de bool:
 
#include <windows.h>
#include <iostream>
using namespace std;
 
///////////////////////////////////////////////////////////////////
 
class CBoolArray
{
 int width;
 int height;
 
public:
 bool* bArray;
 CBoolArray(int x, int y);
 ~CBoolArray() {delete [] bArray;}
 bool& operator() (int x, int y) {return bArray[x+y*width];}
};
 
CBoolArray::CBoolArray(int x, int y)
{
 width = x;
 height = y;
 bArray = new bool[width * height];
 bArray = FALSE;
}
 
///////////////////////////////////////////////////////////////////
 
int CreateBitmask(const char szBitmap[], CBoolArray bMask, int width, int height, int rtrans,
      int gtrans, int btrans)
{  
 HDC hdcImage;
 HBITMAP hbm;
 
 int pixelvalue = 0;
 
 hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, width,
                              height, LR_CREATEDIBSECTION);
    if (hbm == NULL)
        hbm = (HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, width, height,
                                  LR_LOADFROMFILE | LR_CREATEDIBSECTION);
 
    hdcImage = CreateCompatibleDC(NULL);
    SelectObject(hdcImage, hbm);
 
 for (short y = 1; y <= height; y++)
 {
  for (short x = 1; x <= width; x++)
  {
   short r, g, b;
 
   pixelvalue = GetPixel(hdcImage, x, y);
 
   r = (pixelvalue & 0xFF);
   g = (pixelvalue & 0xFF00)>>8;
   b = (pixelvalue & 0xFF0000)>>16;
 
   if (r != rtrans || g != gtrans || b != btrans)
    bMask(x, y) = TRUE;
  }
 }
 
 return 0;
}
 
///////////////////////////////////////////////////////////////////
 
int main()
{
 CBoolArray BackgroundMask(1024, 768);
 
 CreateBitmask("background.bmp", BackgroundMask, 1024, 768, 255, 0, 255);
 
 if (BackgroundMask(50, 50) == TRUE)
  cout << "TRUE" << endl;
 
 else
  cout << "FALSE" << endl;
 
 while (1)
 {
 }
 
 return 0;
}

Reply

Marsh Posté le 21-06-2001 à 20:51:40    

y'a genre deux <= qu'il faudrait remplacer par des <
si tu veux faire clean, tu peux mettre une vérification de dépassement des valeurs du tableau qui n'est compilée que lorsque la constante DEBUG est définie pour éviter ce genre de prob dans le futur.
 
En général, il vaut mieux définir l'opérateur () deux fois
 
bool & operator() (int x, int y);
et  
const bool & operator () (int x, int y) const;
 
la différence est que dans le deuxième cas, le résultat ne peut pas être une lvalue et est donc toléré pour les fonction prenant en paramètre un const CBoolTab &
 
enfin si tu trouves que 8 bits par bool, c'est trop, tu peux faire un tableau compact.
ie:
#include <vector>
using namespace std;
 
class BoolImage: public vector<bool>
{
 int w,h;
public:
  BoolImage(int tw=0, int th=0):w(tw), h(th), vector<bool>(tw*th){}
  bool & operator () (int x, int y)  
    { return operator[] (x+y*w);}
  const bool & operator () (int x, int y)
    { return operator[] (x+y*w);}
};
 
et voilà
 
et avec cette classe tout marche, y compris
l'op =,
l'op ==,
l'op !=,
et les trucs de vector


---------------
-----------------------
Reply

Marsh Posté le 21-06-2001 à 20:53:35    

pour être plus clair pour le bug:
x doit aller de 0 à <largeur et non de 1 à <=largeur
(idem pour y)
l'accès à des adresses au dlà donne une violation d'accès
(exc c000005?)
ou pire, un pernitieux effet de bord qui tue


---------------
-----------------------
Reply

Marsh Posté le 21-06-2001 à 20:53:35   

Reply

Marsh Posté le 21-06-2001 à 21:50:01    

darkoli a écrit a écrit :

la difference entre calloc et malloc c'est quoi ?
svp ne m'insulter.



C'etait pas une insulte, j'ai pas dit Putain quel nain... :D ;) :D Non, c'etait juste une remarque en passant, car calloc est trop souvent sous-employe, alors que c'est une fonction de base en C, tres pratique.
 
Les fonctions de base de gestion de la memoire en C sont:
malloc, calloc, realloc et free.
 
mettre un #include <stdlib.h> pour utiliser calloc.
 
prototype:
void *calloc(size_t nelem, size_t elsize);
 
parametres:

  • nelem: le nombre d'elements a allouer.
  • elsize: la taille d'un element.


effet:
calloc alloue la memoire correspondante (une zone contigue), et initialise tous les bits de la zone allouee a 0.
 
retour:

  • Si calloc echoue, il renvoie NULL.
  • Si nelem ou elsize est nul, calloc retourne soit null, soit un pointeur predefini. (depend de l'implementation)
  • Sinon, il renvoie un pointeur sur le debut de la zone allouee.


En resume, calloc revient a effectuer un malloc puis a initialiser a 0 tous les bits de la zone allouee.
Les parametres de calloc sont un peu plus sympas que ceux de calloc pour allouer une table.
Le seul truc auquel il faut faire gaffe, c'est qu'il n'y a pas de fonction de base effectuant un recalloc (un realloc avec initialisation a 0 de la zone supplementaire allouee, s'il y a une telle zone).
A+,

 

[edit]--Message édité par gilou--[/edit]


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

Marsh Posté le 21-06-2001 à 22:12:03    

gilou> Je me méfie beaucoup de realloc(), j'ai vu trop souvent d'implémentations foireuses. Quand je veux faire un realloc, je préfère le faire à la mano.
 
Par contre, calloc() est extrêmement utile, effectivement. A mon avis, il ne devrait même plus être recommandé, mais obligatoire quand on alloue une nouvelle chaîne de caractères (qui comme chacun sait doit se terminer par un caractère zéro, en C).
 
Et, au pire, darkoli, plutôt que de boucler sur ton buffer pour l'initialiser, utilise memset(), c'est plus efficace et aussi plus lisible qu'une boucle.

Reply

Marsh Posté le 21-06-2001 à 22:57:30    

Bon j'ai modifié quelque truc, mais ça marche toujours pas... C'est la fonction Set de la classe CBoolArray qui merde je pense. Vous en pensez quoi?
 
#include <windows.h>
#include <iostream>
using namespace std;
 
///////////////////////////////////////////////////////////////////
 
class CBoolArray
{
 int width;
 int height;
 
public:
 bool* bArray;
 CBoolArray(int x, int y);
 ~CBoolArray() {delete [] bArray;}
 Set(int x, int y, bool value);
 bool& operator() (int x, int y) {return bArray[x+y*width];}
};
 
CBoolArray::CBoolArray(int x, int y)
{
 width = x;
 height = y;
 bArray = new bool[width * height];
 bArray = FALSE;
}
 
CBoolArray::Set(int x, int y, bool value)
{
 bArray[x+y*width] = value;
 return 0;
}
 
///////////////////////////////////////////////////////////////////
 
int CreateBitmask(const char szBitmap[], CBoolArray bMask, int width, int height, int rtrans,
      int gtrans, int btrans)
{  
 HDC hdcImage;
 HBITMAP hbm;
 
 int pixelvalue = 0;
 
 hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, width,
                              height, LR_CREATEDIBSECTION);
    if (hbm == NULL)
        hbm = (HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, width, height,
                                  LR_LOADFROMFILE | LR_CREATEDIBSECTION);
 
    hdcImage = CreateCompatibleDC(NULL);
    SelectObject(hdcImage, hbm);
 
 for (short y = 0; y < height; y++)
 {
  for (short x = 0; x < width; x++)
  {
   short r, g, b;
 
   pixelvalue = GetPixel(hdcImage, x, y);
 
   r = (pixelvalue & 0xFF);
   g = (pixelvalue & 0xFF00)>>8;
   b = (pixelvalue & 0xFF0000)>>16;
 
   if (r != rtrans || g != gtrans || b != btrans)
    bMask.Set(x, y, true);
  }
 }
 
 return 0;
}
 
///////////////////////////////////////////////////////////////////
 
int main()
{
 CBoolArray BackgroundMask(1024, 768);
 
 CreateBitmask("background.bmp", BackgroundMask, 1024, 768, 255, 0, 255);
 
 if (BackgroundMask(50, 50) == true)
  cout << "TRUE" << endl;
 
 else
  cout << "FALSE" << endl;
 
 while (1)
 {
 }
 
 return 0;
}

 

[edit]--Message édité par Alload--[/edit]

Reply

Marsh Posté le 21-06-2001 à 23:02:17    

tu comprends ce que tu tapes ? :)
 
 bArray = new bool[width * height];
 bArray = FALSE;

Reply

Marsh Posté le 21-06-2001 à 23:15:01    

Oui c'est vrai que c'est pas malin... J'avais pas fait gaffe... Lol quel imbécile je suis déjà :D
 
Maintenant il arrive pas à lire avec le:
 
Background(50, 50);
 
Putain je vais pas y arriver à finir ce prog de merde...

Reply

Marsh Posté le 22-06-2001 à 00:01:08    

BifaceMcLeOD a écrit a écrit :

gilou> Je me méfie beaucoup de realloc(), j'ai vu trop souvent d'implémentations foireuses. Quand je veux faire un realloc, je préfère le faire à la mano.
 
Par contre, calloc() est extrêmement utile, effectivement. A mon avis, il ne devrait même plus être recommandé, mais obligatoire quand on alloue une nouvelle chaîne de caractères (qui comme chacun sait doit se terminer par un caractère zéro, en C).
 
Et, au pire, darkoli, plutôt que de boucler sur ton buffer pour l'initialiser, utilise memset(), c'est plus efficace et aussi plus lisible qu'une boucle.  




 
 
ok ok ben je vais utiliser calloc alors.
mais c'est vrai que pour realloc j'ai eu plein de merdes bizarre alors moi aussi je le fais à la main.

Reply

Marsh Posté le 22-06-2001 à 02:21:00    

BifaceMcLeOD a écrit a écrit :

gilou> Je me méfie beaucoup de realloc(), j'ai vu trop souvent d'implémentations foireuses. Quand je veux faire un realloc, je préfère le faire à la mano.



 
Oui, oui, mon post etait la pour insister sur l'utilisation de calloc, pas sur celle de realloc.
A+,


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

Marsh Posté le 22-06-2001 à 09:50:51    

Mais pourquoi ce que je veux ne peut pas être lu? La tableau a l'air d'être bien défini et j'extracte correctement les infos...

Reply

Sujets relatifs:

Leave a Replay

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