d0jones
Messages postés10Date d'inscriptionvendredi 29 décembre 2000StatutMembreDernière intervention15 janvier 2013
-
6 nov. 2011 à 12:16
pop70
Messages postés181Date d'inscriptionmardi 6 avril 2010StatutMembreDernière intervention 7 janvier 2012
-
7 nov. 2011 à 16:52
bonjour,
j'ai un petit souci, quand j'essai d'accéder à la donnée de ma struct j'ai le message suivant :
Exception non gérée à 0x01202029 dans ListTemplate.exe : 0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0x00000000.
Liste.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include
#ifndef _LIST_
#define _LIST_
using namespace std;
template <typename T>
struct cell
{
public:
T data;
cell<T>* next;
};
template <class T>
class Liste
{
public:
Liste(void)
{
this->first=NULL;
this->last=NULL;
this->size=0;
}
Liste(const Liste<T>& list)
{
if (list.size != 0 && list.first != NULL)
{
const cell<T> *temp = list.first;
while (temp->next != NULL)
{
this->AddInQueue(temp->data);
temp = temp->next;
}
}
}
virtual ~Liste(void)
{
delete(this->first);
delete(this->last);
}
int GetSize()
{
return this->size;
}
void AddInHead(T t)
{
cell<T>* c = new cell<T>();
c->data = t;
c->next = this->first;
this->first = c;
this->size++;
}
void AddInQueue(T t)
{
cell<T>* c = new cell<T>();
c->data = t;
c->next = NULL;
this->last = c;
this->size++;
}
void Concat(const Liste<T>& list)
{
if (list.first != NULL)
{
const cell<T> *temp = list.first;
while (temp->next != NULL)
{
this->AddInQueue(temp->data);
temp = temp->next;
}
}
}
T ElementAt(int pos)
{
if (pos > this->size)
{
return NULL;
}
else
{
const cell<T> *temp = this->first;
int cpt = 0;
for (int i=0; i<=pos; i++)
{
if (i == pos)
{
T data = temp->data;
return data;
}
else
{
temp = temp->next;
}
}
/*while (temp->next != NULL)
{
if (cpt == pos)
{
return temp->data;
}
cpt++;
temp = temp->next;
}*/
return -1;
}
}
inline const std::ostream & operator <<(std::ostream & out)
{
if (this->first != NULL)
{
const cell *temp = this->first;
for (int i = 0; i < this->size; i++)
{
out << (int)temp->data << " - " ;
temp = temp->next;
}
}
return out;
}
private:
int size;
cell<T>* first;
cell<T>* last;
};
#endif
le fichier Liste.cpp est vide
le main :
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include
#include "liste.h"
using namespace std;
int main (int argc, char** argv)
{
Liste* list = new Liste();
cout << "constructeur par defaut : longueur de la liste : " << list->GetSize() <<endl;
list->AddInHead(1);
cout << "ajout en tete de '1' : longueur de la liste : " << list->GetSize() <<endl;
cout << " contenu de la liste : " << list << endl;
list->AddInQueue(2);
cout << "ajout en queue de '2' : longueur de la liste : " << list->GetSize() <<endl;
cout << " contenu de la liste : " << list << endl;
cout << "element a la position 1 : " << list->ElementAt(1) << endl;
Liste* list1 = new Liste();
list1->AddInQueue(3);
list1->AddInQueue(4);
list1->AddInQueue(5);
cout << "creation de la liste 1 contenant les elements '3,4,5'" <<endl;
cout << " contenu de la liste : " << list1 << endl;
list->Concat(*list1);
cout << "concat de list(2) et list1(3) : longeur de la la liste : " << list->GetSize() << endl;
cout << " contenu de la liste : " << list << endl;
Liste* list2 = new Liste(*list);
cout << "constructeur par recopie : longueur de la liste : " << list2->GetSize() << endl;
cout << " contenu de la liste : " << list2 << endl;
char n;
scanf ("%c",&n);
return 0;
}
pop70
Messages postés181Date d'inscriptionmardi 6 avril 2010StatutMembreDernière intervention 7 janvier 201210 6 nov. 2011 à 14:31
En fait j'en arrive à çeci :
friend std::ostream& operator <<(std::ostream& out, Liste<T>*& list) //(pour pouvoir faire std::cout << list)
{
if (list->ElementAt(0) != NULL)
{
const cell<T> *temp = list->GetFirst(); // ici il manque un <T>
for (int i = 0; i < list->GetSize(); i++)
{
out << (T)temp->data << " - " ;
temp = temp->next;
}
}
return out;
}
Mais il reste une erreur dans AddInQueue: last pointe sur la dernière cellule, lui affecte sa valeur, et indique que la suivante ne pointera sur rien. Mais à quelle moment la variable next de l'avant-dernière cellule pointe sur la nouvelle
Jamais, donc la liste contient bien le nombre d'éléments voulu, mais ils ne sont pas reliés entre eux... Contrairement à la fonction AddInHead, qui elle fonctionne correctement, et du coup fait planter l'affichage.
Les "includes" devraient être à l'intérieur de la garde et pas au dessus. (Donc les "includes" en dessous du ifndef/define)
using namespace std;
Évite les "using namespace", voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
struct cell
En C++, une structure et une classe, c'est la même chose. Donc "cell" devrait avoir une majuscule, et le "public" est inutile, puisqu'une struct est déjà publique par défaut.
De même, généralement un nom de méthode commence par une lettre minuscule.
Liste(void)
Devrait être List(). En C++, une fonction qui ne prend pas d'argument s'écrit comme cela. Il n'y a qu'en C où l'on est obligé de mettre "void".
int size;
cell<T>* first;
cell<T>* last;
On met généralement un différenciateur sur les attributs de classe. Par exemple "first" devrait être "_first".
this->size=0;
Les "this->" sont inutiles, et il est d'usage de ne pas les mettre.
this->first=NULL;
this->last=NULL;
Évite les NULL, voir: [0217021.free.fr/portfolio/axel.berardino/articles/null-en-cpp 0217021.free.fr/portfolio/axel.berardino/articles/null-en-cpp]. Préfère 0 (ou "nullptr" si tu es en C++0x).
Le "return" est débranchant. Donc il est inutile de mettre un "else". Pas besoin non plus de crochets lorsque tu as une seule instruction.
if (pos > this->size)
return NULL;
// code
(À corriger partout)
Enfin pour la fonction d'affichage, il est d'usage de ne pas utiliser de friend (ni de cast d'ailleurs). On réalise généralement une fonction publique "print" qui prend un std::ostream en argument. Puis on appelle cette fonction dans la fonction de "sucrement".
Ça permet de laisser la logique au sein de la classe, et de laisser le rôle de sucrement à la fonction de sucrement.
Ex:
Dans ta classe:
void print(std::ostream& out)
{
if (list->ElementAt(0) != 0)
{
const cell<T> *temp = list->GetFirst();
for (int i = 0; i < list->GetSize(); ++i)
{
out << temp->data << " - " ;
temp = temp->next;
}
}
}
Au niveau de ton main:
Pas besoin de faire des new (surtout que tu oublies les delete qui vont avec !).
Tu peux directement remplacer: "Liste* list = new Liste();" par "Liste list;" (et donc toutes les "->" deviennent des ".").
Les includes du C n'ont rien à faire là (donc retire les stdio.h et stdlib.h). Si tu veux mettre une pause, un "std::cin.get()" remplacera avantageusement ton scanf.
Enfin, sépare la déclaration et le code. Il ne devrait pas y avoir de code dans un header.
________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
Sans friend, l'operateur de flux << n'est pas valide, le compilo retournera
...\main.cpp|147|error: 'std::ostream& Liste<T>::operator<<(std::ostream&, Liste<T>*&)' must take exactly one argument
à la différence des opérateurs + - = ...
Sinon pour l'abscence de void je ne suis pas sûr, en C le type de retour par défaut est bien int, mais en C++ ça semble l'être aussi : en l'abscence de type de retour et de retour on obtient un warning :
warning: no return statement in function returning non-void
qui n'est résolu qu'en retournant un entier.
De plus même en retournant un entier, certains compilos (comme Code::Blocks), disent avoir une erreur ISO C++ qui interdit la déclaration sans type :
...\main.cpp|76|error: ISO C++ forbids declaration of 'AddInQueue' with no type|
cptpingu
Messages postés3837Date d'inscriptiondimanche 12 décembre 2004StatutModérateurDernière intervention28 mars 2023123 7 nov. 2011 à 13:29
Sans friend, l'operateur de flux << n'est pas valide, le compilo retournera
Attention, ne pas confondre (la version interne):
std::ostream& Liste<T>::operator<<(std::ostream&)
et (la version externe):
std::ostream& operator<<(std::ostream&, const Liste<T>&)
qui sont deux surcharges différentes (qui ont à peu près le même effet, je ne rentre pas dans les détails).
Voici un exemple très simple qui étayera mes dires:
#include
class Test
{
public:
Test()
: _a(1), _b(2), _c(3)
{
}
void print(std::ostream& out) const
{
out << _a << " " << _b << " " << _c;
}
private:
int _a;
int _b;
int _c;
};
std::ostream& operator<<(std::ostream& out, const Test& test)
{
test.print(out);
return out;
}
int main()
{
Test test;
std::cout << test << std::endl;
return 0;
}
Sinon pour l'abscence de void je ne suis pas sûr, en C le type de retour par défaut est bien int,
Je parle du void en argument, et non du type de retour. Ex: int func(void) en C++ s'écrit int func().
En C, int func() veut dire "nombre d'argument inconnu" et int func(void) veut dire "pas d'argument".
En C++, la notion de "nombre d'argument inconnu" est retirée, et on a adopté l'écriture "int func()".
Je te remercie des remarques, car tu viens de me faire remarquer que je n'ai peut être pas été clair dans mes explications :)
________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
pop70
Messages postés181Date d'inscriptionmardi 6 avril 2010StatutMembreDernière intervention 7 janvier 201210 7 nov. 2011 à 16:52
Ah d'accord !
Merci pour les précisions
Sinon j'avais jamais fait la différence entre int funct(void) et int funct() en C ; en fait une fois j'avais essayé les 2 puis fait un objdump, mais le code assembleur était identique (du moins au point de vue du main), donc j'en avais conclu que c'était pareil. Mais du coup j'imagine que int func(void) respecte plus les normes :)