OVH Cloud OVH Cloud

BC++ 3.0petit souci

14 réponses
Avatar
Acetonik
bjr

Avec BC++ vers 3.0 , j'ai construit une classe "setint" qui travaille sur
des ensembles d'entiers.
tout se passe bien , sauf que si je remplace un ensemble A par un ensemble
C[i] issu d'un tableau tout dérape ;comme si l'allocation n'avait pas été
faite par *(new setint ) .

Merci ,par avance, pour votre aide à un débutant.

PS : Mon programme ci dessous fonctionne ,
mais ne fonctionne plus si on decommente les 5 lignes.

#ifndef __SETINTBO_H
#include <setintbo.h>
#endif

#ifndef __CONIO_H
#include <conio.h>
#endif

main()
{int i, j;
setint A,B[10],C[10], E[10][10];


clrscr();
for (i=1;i<10;i++)
{B[i]=*(new setint);
C[i]=*(new setint);
for (j=1;j<10;j++) E[i][j]= *(new setint);
}

for (i=1;i<10;i++)
for (j=1;j<10;j++)
{B[i].ajoute(i*j);
E[i][j].ajoute(i+j);
}


for (i=1;i<8;i++)
{for (j=1;j<8;j++)
A=reunion(E[i][j],B[i]);
affiche(A);
}

///////// A est remplace par C[i]

// for (i=1;i<8;i++)
// {for (j=1;j<8;j++)
// C[i]=reunion(E[i][j],B[i]);
// affiche(C[i]);
// }

getch();

return (0);
}

10 réponses

1 2
Avatar
kanze
Acetonik wrote:

Avec BC++ vers 3.0 , j'ai construit une classe "setint" qui
travaille sur des ensembles d'entiers. tout se passe bien ,
sauf que si je remplace un ensemble A par un ensemble C[i]
issu d'un tableau tout dérape ;comme si l'allocation n'avait
pas été faite par *(new setint ) .


J'ai l'impression que tu ne nous montres pas le plus intéressant
(l'implémentation de setint).

Merci ,par avance, pour votre aide à un débutant.


Alors, j'indiquerai ce que je trouve.

PS : Mon programme ci dessous fonctionne ,
mais ne fonctionne plus si on decommente les 5 lignes.

#ifndef __SETINTBO_H


Déjà un premier problème, au moins si tu postes ici : les noms
qui commence par __ sont réservés à l'implémentation. Alors, ou
bien, tu as défini un nom interdit (et il vaut mieux changer le
nom), ou bien, il s'agit de quelque chose de propre à ton
implémentation. Et là, c'est difficile à t'aider, parce qu'on
n'a pas forcement la même implémentation.

#include <setintbo.h>


Les include à <...> sont aussi pour les en-têtes « système »,
c-à-d de l'implémentation. Si setintbo.h est à toi, il faut
l'inclure :

#include "setintbo.h"

S'il fait partie de l'implémentation, c'est comme ci-dessus : ce
n'est pas standard, et moi, au moins, je n'en ai jamais entendu
parler.

#endif

#ifndef __CONIO_H
#include <conio.h>
#endif


Même commentaire que ci-dessus. Sauf qu'ici, j'ai bien entendu
parler d'un conio.h dans certaines implémentations (mais pas
celles dont je me sers -- ce n'est pas standard).

main()


Au moins que conio.h soit réelement étrange, ça ne doit pas
passer à la compilation. Quel est le type de rétour de main ?

Il faut déclarer ou « int main() », ou « int main( int argc,
char** argv ) ». (Sauf qu'évidemment, on peut donner les noms
qu'on veut aux paramètres dans la deuxième forme.) Rien d'autre
n'est portable.

{int i, j;
setint A,B[10],C[10], E[10][10];


Vue qu'on est dans C++, on ne déclare pas les variables avant de
pouvoir les initialiser. (Il y a quelques exceptions, mais le
fait de déclarer toutes les variables en tête est un C-isme.)

clrscr();


Encore une fonction que je ne connais pas. (Ou plutôt, que je
connais comme extension présente dans mes implémentations... à
condition d'avoir include <curses.h>.)

for (i=1;i<10;i++)
{B[i]=*(new setint);
C[i]=*(new setint);


Et voilà des pertes de mémoire en pagaille. Je ne sais pas ce
que tu voulais faire ici, mais ...

-- Tu as déclaré B et C comme des objets de type setint[]. Du
coup, le compilateur en a appelé le constructeur dès la
déclaration. Tu n'as donc rien à faire de plus pour les
initialiser, au moins que tu veux les initialiser avec
quelque chose d'autre que les valeurs par défaut.

-- Dans l'expression x=(*new setint), tu alloues un nouveau
setint dans la mémoire dynamique, que tu copies dans la
variable locale. En revanche, tu ne sauves pas le pointeur
rendu par new, ce qui veut dire que tu ne vas jamais plus
accéder à l'objet alloué, ni jamais le libérer. (Il y a une
exception ici, si le constructeur de setint inscrit l'objet
dans un régistre quelque part. Mais ça m'étonnerait que ce
soit le cas de setint.)

Ce que tu as écris est manifestement faux, mais sans savoir ce
que tu veux y faire, je ne peux pas dire ce qu'il faut à la
place. Si le but est simplement d'initialiser les B[i] et les
C[i], c'est déjà fait.

for (j=1;j<10;j++) E[i][j]= *(new setint);
}

for (i=1;i<10;i++)
for (j=1;j<10;j++)
{B[i].ajoute(i*j);
E[i][j].ajoute(i+j);
}

for (i=1;i<8;i++)
{for (j=1;j<8;j++)
A=reunion(E[i][j],B[i]);
affiche(A);
}

///////// A est remplace par C[i]

// for (i=1;i<8;i++)
// {for (j=1;j<8;j++)
// C[i]=reunion(E[i][j],B[i]);
// affiche(C[i]);
// }


Sans savoir ce que font les fonctions en question, on ne peut
rien dire.

getch();


Encore une fonction non-standard.

(Mais je dis ça juste pour que tu le saches, étant donné que tu
as que tu étais débuttant. Il n'y a pas de problème à se servir
des extensions dans des petits programmes d'essais, qui n'ont
pas la prétention à être portable. À condition de savoir que ce
sont des extensions, et de savoir les éviter quand la
portabilité est de mise.)

return (0);


On n'a pas vraiment besoin des parenthèses ici.

}


--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Fabien LE LEZ
On 20 Oct 2005 23:55:20 -0700, "kanze" :

#ifndef __CONIO_H
#include <conio.h>
#endif


Même commentaire que ci-dessus. Sauf qu'ici, j'ai bien entendu
parler d'un conio.h dans certaines implémentations (mais pas
celles dont je me sers -- ce n'est pas standard).


Typique Borland, effectivement.
Par contre, mettre des gardes externes me paraît pour le moins
fastidieux et peu utile, à moins que Borland C++ 3 soit vraiment
beaucoup plus lent que les versions 4 et 5.

main()


Au moins que conio.h soit réelement étrange, ça ne doit pas
passer à la compilation. Quel est le type de rétour de main ?


Là encore, Borland C++ l'accepte, avec les options par défaut du moins
(sous prétexte que dans les premiers C, c'était autorisé).
Ce qui, je te l'accorde, est une très mauvaise raison pour laisser
traîner des trucs pareils dans un code.

et de savoir les éviter quand la
portabilité est de mise.


De toutes façons, s'il utilise BC++ 3, très vieux compilateur (j'ai
acheté la version 4.5 en 1995 !), c'est que c'est un cas vraiment
spécial. De l'embarqué peut-être ? Ou des petites réparations sur un
logiciel qui tourne sous MS-DOS ?


Avatar
Acetonik
"Fabien LE LEZ" a écrit dans le message de
news:

De toutes façons, s'il utilise BC++ 3, très vieux compilateur (j'ai
acheté la version 4.5 en 1995 !), c'est que c'est un cas vraiment
spécial. De l'embarqué peut-être ? Ou des petites réparations sur un
logiciel qui tourne sous MS-DOS ?


J'ai crée un programme qui resout rapidement les SUDOKU de niveau "tres tres
difficile" avec Mapple (logiciel de Maths où l'on peut creer quelque
procedure -pas convivial du tout ; mais puissant )
Je cherchais à tansposer cela dans un Langage Orienté Objet ; et le
BC++3 est ce dont je dispose .( Ancien OK , mais c'est ce que javais utilisé
un peu il y a déjà quelques années )
J'ai aussi Linux ( et K Develop ) , ce serait préférable si j'ai bien
compris ce qui se dit par ailleurs.

Merci pour vos avis

Cordialement
acetonik

Avatar
Fabien LE LEZ
On Fri, 21 Oct 2005 12:31:43 +0200, "Acetonik"
:

et le
BC++3 est ce dont je dispose


Si jamais tu as un accès à Internet, je te conseille de télécharger un
compilateur gratuit plus récent (et donc plus conforme).
Sous Windows, Dev-C++ est la "solution évidente", mais il y en a
d'autres. Cf les discussions récentes à ce sujet ici même.

Avatar
Acetonik
[...]
Tout d'abord ,merci pour vos conseils.
J'ai essayé d'en tenir compte dans mes fichiers.

Je souhaite seulement creer un petit programme qui utilise des ensembles et
leur opérations(réunion ...)
Les fichiers settint.h et setint.cpp , pour definir la classe des
ensembles;
essetint.cpp , le fichier d'essai de cette classe ( creation d' ensembles et
leur affichage).

Mon souci : Le programme fonctionne parfaitement avec les commentaires
( dans les 10 dernieres lignes) du programme d'essai.
Quand je décommente , cela ne fonctionne plus du tout ; avec le peu que je
sais en C++ je ne vois pas pourquoi ...
Merci par avance si vous pouviez encore m'aider .


////////////////////////////////////////////////////////////////////////////
///////////////////////////////////
/* fichier SETINT.H */
/* d,claration de la classe setint*/

struct noeud
{
int valeur; //valeur d'un ,l,ent de l'ensemble
noeud * suivant ; //pointeur sur le noeud suivant
}; //de la liste

class setint
{ noeud * debut; //pointeur sur le début de la liste
int nelem; //nombre courant d'éléments
noeud * courant; //pointeur sur noeud courant
public:
setint (int ); //constructeur
setint (setint &); //constructeur par recopie
~setint (); //destructeur
void ajoute (int); //ajout d'un ,l,ment
int appartient (int); //appartenance d'un ,l,ment
int cardinal (); //cardinal de l'ensemble
void init (); //initialisation it,ration
int prochain (); //entier suivant
int existe(); //test fin liste
};

void affiche(setint);
setint moins (setint,setint); //soustraction de deux ensembles
setint inter (setint,setint); //intersection de deux ensembles
setint reunion (setint,setint); //r,union de deux ensembles

////////////////////////////////////////////////////////////////////////////
///////////////////////////////////
/* fichier SETINT.cpp */
/* la classe setint*/

#include <iostream.h>
#include "setint.h"

setint::setint (int )

{ debut = NULL ;
nelem = 0 ;
}

setint::setint (setint & e)
{ nelem = e.nelem ;
//cr,ation d'une nouvelle liste identique . l'ancienne
noeud * adsource = e.debut ;
noeud * adbut ;
debut = NULL ;

while (adsource)
{adbut = new noeud ; //cr,ation nouveau noeud
adbut->valeur = adsource->valeur;//copie valeur
adbut->suivant = debut; //insertion nouveau noeud
debut = adbut ; //dans nouvelle liste
adsource = adsource->suivant; //noeud suivant ancienne liste
}
}

setint::~setint ()
{ noeud * adn ;
noeud * courant = debut ;
while (courant)
{adn = courant ; //lib,ration de tous
courant = courant->suivant; //les noeuds
delete adn ; //de la liste
}
}

void setint:: ajoute (int nb)
{ if (!appartient (nb) ) // si nb n'appartient pas . la liste
{noeud * adn = new noeud; // on l'ajoute en d,but de liste
adn->valeur = nb ;
adn->suivant = debut ;
debut = adn ;
nelem++ ;
}
}


int setint::appartient (int nb)
{ noeud * courant = debut;

while (courant && (courant->valeur != nb) ) courant = courant->suivant;
return (courant != NULL);
}


int setint::cardinal ()
{ return nelem;
}

void setint::init()
{courant Þbut;
}


int setint::prochain ()
{ if (courant)
{int val = courant->valeur;
courant = courant->suivant;
return val;
}
else return 0;
}

int setint::existe ()
{ return (courant != NULL);

}


void affiche(setint ens)
{ ens.init();
cout <<"{";
if (ens.cardinal()!=0)
{while (ens.existe ())
{
cout <<ens.prochain();
if(ens.existe ()) cout<<",";
};}
else cout<<" ";
cout <<"}";
}


setint moins(setint ens1,setint ens2)
{ setint ens3;
int nb;

ens1.init();
while (ens1.existe ())
{nb= ens1.prochain();
if (!ens2.appartient (nb)) ens3.ajoute(nb);
}
return ens3;
}

setint inter(setint ens1,setint ens2)
{ setint ens3;
int nb;

ens1.init();
while (ens1.existe ())
{nb= ens1.prochain();
if (ens2.appartient (nb)) ens3.ajoute(nb);
}
return ens3;
}

setint reunion(setint ens1,setint ens2)
{ setint ens3;

ens1.init();
while (ens1.existe ()) ens3.ajoute(ens1.prochain());

ens2.init();
while (ens2.existe ()) ens3.ajoute(ens2.prochain());
return ens3;
}

////////////////////////////////////////////////////////////////////////////
///////////////////////////////////
/*fichier d'essai*/

#include <iostream.h>
#include "setint.h"


int main()

{
int i, j ;
setint A ;
for(i=1;i<4;i++) for(j=1;j<6;j++)
A.ajoute(i*j);
affiche(A);


setint B[10],E[10][10];
for(i=1;i<10;i++)
{for(i=1;i<10;i++)
B[i].ajoute(i*j);
E[i][j].ajoute(i+j);
}

cout<<"n";
for(i=1;i<10;i++)
{for(j=1;j<10;j++)
A=reunion(E[i][j],B[i]);
affiche(A);
}
/*////////////////////NE FONCTIONNE PAS /////////////////////
cout<<"n";
setint C[10];
for(i=1;i<10;i++)
{for(j=1;j<10;j++)
C[i]=reunion(E[i][j],B[i]);
affiche(C[i]);
}
/////////////////////////////////////////*/
return 0;
}
Avatar
Acetonik
"Fabien LE LEZ" a écrit dans le message de
news:
On Fri, 21 Oct 2005 12:31:43 +0200, "Acetonik"
:

et le
BC++3 est ce dont je dispose


Si jamais tu as un accès à Internet, je te conseille de télécharger un
compilateur gratuit plus récent (et donc plus conforme).
Sous Windows, Dev-C++ est la "solution évidente", mais il y en a
d'autres. Cf les discussions récentes à ce sujet ici même.

Tres intéressant ,

Je prend note , merci beaucoup.


Avatar
Fabien LE LEZ
On Sat, 22 Oct 2005 11:03:11 +0200, "Acetonik"
:

class setint
{ noeud * debut; //pointeur sur le début de la liste
int nelem; //nombre courant d'éléments


Y a-t-il une raison particulière expliquant pourquoi tu programmes
toi-même une liste chaînée au lieu d'utiliser les conteneurs de la
STL ?

Si la raison est une méconnaissance de la STL, c'est une mauvaise
raison : apprendre les bases de l'utilisation de std::vector<> ou
std::list<> te prendra nettement moins longtemps qu'implémenter une
classe "liste chaînée" un tant soit peu fiable.

Si la raison est une volonté d'apprendre à faire une liste chaînée,
fais-le au moins proprement, avec une encapsulation décente.
Je te conseillerais même de faire une classe ayant la même interface
que std::list<>.

Avatar
Acetonik
"Fabien LE LEZ" a écrit dans le message de
news:
On Sat, 22 Oct 2005 11:03:11 +0200, "Acetonik"
:

Y a-t-il une raison particulière expliquant pourquoi tu programmes
toi-même une liste chaînée au lieu d'utiliser les conteneurs de la
STL ?
Si la raison est une méconnaissance de la STL,
J'avais pensé à utiliser Tclasss.lib fourni avec BC++3 mais cela ne

me convenait pas.

Si la raison est une volonté d'apprendre à faire une liste chaînée,
fais-le au moins proprement, avec une encapsulation décente.
Je te conseillerais même de faire une classe ayant la même interface
que std::list<>.
Oui , j'ai voulu réapprendre quelques bases que j'avais oubliées .

(Je précise que je n'ai jamais été informaticien ...)

Je vais me mettre à niveau et m'informer.

Cordialement

--
Acetonik

Avatar
Alexandre
class setint
{ noeud * debut; //pointeur sur le début de la liste
int nelem; //nombre courant d'éléments


Y a-t-il une raison particulière expliquant pourquoi tu programmes
toi-même une liste chaînée au lieu d'utiliser les conteneurs de la
STL ?


je ne suis pas sur que la STL soit fournie avec BC++ 3.0. Je ne m'en sers
plus depuis longtemps (je ne dois pas même plus avoir les disquettes, vu que
j'ai plus de lecteur de disquettes ;-)) mais il me semble qu'il n'implèmente
pas les template. Donc ...


Si la raison est une méconnaissance de la STL, c'est une mauvaise
raison : apprendre les bases de l'utilisation de std::vector<> ou
std::list<> te prendra nettement moins longtemps qu'implémenter une
classe "liste chaînée" un tant soit peu fiable.

Si la raison est une volonté d'apprendre à faire une liste chaînée,
fais-le au moins proprement, avec une encapsulation décente.
Je te conseillerais même de faire une classe ayant la même interface
que std::list<>.




Avatar
James Kanze
Fabien LE LEZ wrote:
On Sat, 22 Oct 2005 11:03:11 +0200, "Acetonik"
:


class setint
{ noeud * debut; //pointeur sur le début de la liste
int nelem; //nombre courant d'éléments



Y a-t-il une raison particulière expliquant pourquoi tu
programmes toi-même une liste chaînée au lieu d'utiliser les
conteneurs de la STL ?


Il a parlé ailleurs de Sukodo. Si l'intervale est des entiers
est limité à 1...9, bool isMember[10] me semble une
implémentation tout à fait adéquate, et on ne peut plus simple.
Pourquoi s'emmerder quand ce n'est pas la peine ?

Sinon, pour implémenter un ensemble, std::set pourrait servir.
Ou un std::vector qu'on garde trié grace à lower_bound et al.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


1 2