Newsgroup: it.comp.lang.c++
Titolo: Cerco Errore Fantasma... A I U T A T E M I !

Ciao a tutti!
Sono un povero studente che è rimasto ingarbugliato in qualche linea di
c++...
Ho scritto una classe Matrix ( che chiaramente identifica l'oggetto
matrice ) ma ho trovato i seguenti problemi...
Nell'overloading degli operatori "*" e "+" avviene una cosa strana:
Le matrici restituite presentano nell'entrata (0,0) sempre il valore 0 o cmq
un valore NULL...
Inoltre nel caso "+", qualche volta l'entratre in basso a destra risultano
con valori NULL
Infine Se moltiplico matrici non NxN mi viene sempre restituta una matrice
con valori nell'ultima colonna sballati...
Ho provato a capire dove fosse l'errore e ho scoperto che fin quando il
programma gira all'interno della funzione, tutto risulta giusto...Mi spiego
meglio: se faccio stampare la matrice all'interno della funz "operator+" (o
*) appena prima del return mi stampa una matrice senza errori... PERCHE?
Ecco il sorgente nelle parti d'interesse...
------------------------------------------
------------------------------------------
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
using namespace std;
class Matrix {
      friend ostream &operator<< ( ostream &, const Matrix & );
    public:
      Matrix( int, int, bool=false );
      Matrix( int, bool=false );
      ~Matrix();
      void print() const ;
      void fill( bool=false );
      void erase();
      int getEntry( int, int ) const;
      bool setEntry( int, int, int );
      Matrix &operator= ( const Matrix &right );
      Matrix operator+ ( const Matrix &right ) const;
      Matrix operator* ( const Matrix &right ) const;
      bool operator== ( const Matrix &right ) const;
      bool operator!= ( const Matrix &right ) const;
      int getRow() const { return row+1; };
      int getCol() const { return col+1; };
      void setTab( int n ) { tab = ( n>1 )? n : 5; };
      int getTab() const { return tab; };
    private:
      int row;
      int col;
      int tab;
      int *matrix;
};
#endif
//------------------------------------------------------
//                the functions
//------------------------------------------------------
Matrix::Matrix( int i, int j, bool self )
{
row = ( i<0 )? 0 : i;
col = ( j<0 )? 0 : j;
matrix = new int[ (row+1)*(col+1)  ];
tab = 5;             // maybe at least 4
fill( self );
}
//------------------------------------------------------
Matrix::Matrix( int i, bool self )
{
row = ( i<0 )? 0 : i;
col = row;
matrix = new int [ (row+1)*(col+1) ];
fill( self );
}
//------------------------------------------------------
void Matrix::fill ( bool self )
{
if (self)
   {
   for ( int i=0; i<=row; i++ )
      for ( int j=0; j<=col; j++ )
         *(matrix + i*(col+1) + j) = rand()%20;          // may be at least
%16
   }
else
   {
   cout << "Please insert matrix's entries..." << endl;
   for ( int i=0; i<=row; i++ )
      { for ( int j=0; j<=col; j++ )
           { cout <<" ("<<i<<","<<j<<") ";
           cin >> *(matrix + i*(col+1) + j); }
       cout << endl; }
   }
}
//------------------------------------------------------
void Matrix::print() const
{
for ( int i=0; i < (row+1)*(col+1); i++ )
    {
    if ( i%(col+1) == 0 )  // && i!=0
       cout << endl << endl;
    cout << setw( 4 ) << *( matrix + i );
    }
cout << endl << endl;
}
//------------------------------------------------------
//                 Overloading Functions
//------------------------------------------------------
Matrix Matrix::operator+( const Matrix &right ) const
{                                                        // bad 1st & last
value
int x = ( row > right.row )? row : right.row,
    y = ( col > right.col )? col : right.col;
Matrix sum( x, y, 1 );
for ( int i=0; i<=x; i++ )
    for ( int j=0; j<=y; j++ )
      *(sum.matrix + i*(y+1) + j ) =
            ((i > row || j > col)? 0 : *(matrix + i*(col+1) + j) ) +
            ((i > (right.row) || j > (right.col) )? 0 : *(right.matrix +
i*(right.col+1) + j) );
return sum;
}
//------------------------------------------------------
Matrix Matrix::operator* ( const Matrix &right ) const
{
int x = row,
    y = right.col;                                  // bad 1st & -sometimes-
last col value
Matrix prod( x, y, 1 );
prod.erase();
int max = ( col > right.row )? col : right.row;
for ( int i=0; i<=x; i++ )
    for ( int k=0; k<=y; k++ )
        for ( int a=0; a<=max; a++ )
           *(prod.matrix + i*(y+1) + k ) +=
                   (( a <= col )? *(matrix + i*(col+1) + a) : 0 ) *
                   (( a <= right.row )? *(right.matrix + a*(right.col+1) +
k ) : 0 );
cout << prod << endl;                           //test
return prod;
}
//------------------------------------------------------
//                   Friend Functions
//------------------------------------------------------
ostream &operator<< ( ostream &output, const Matrix &right )
{
for ( int i=0; i < (right.row+1)*(right.col+1); i++ )
    {
    if ( i%(right.col+1) == 0 )  // && i!=0
       output << endl << endl;
    output << setw( 4 ) << *( right.matrix + i );
    }
output << endl << endl;
return output;
}
******************************************
Infine, perchè la seguente istruzione a volte gira e altre no?
--------------
int tab= n;
...
cout << setw ( tab ) << ... ;
--------------
Grazie anche se siete arrivati alla fine di questo post (credo sia
lunghetto)
Daniele

 for ( int i=0; i < (row+1)*(col+1); i++ )
Bensi'...
for ( int i=0; i < ( (row+1)*(col+1) ) - 1; i++ )
..dato che per ( row + 1 ) * ( col + 1 ) = k elementi, l'indice puo' andare
da 0 a k-1 (anche l'elemento zero devi contare).
Ciao!
*** Azimuth ***

 ha scritto nel messaggio
news:ao69ah$2chg$1...@newsreader1.mclink.it...


 matrice ) ma ho trovato i seguenti problemi...
prova a dare un occhio a questa:
http://groups.google.com/groups?hl=it&lr=&ie=UTF-8&oe=UTF-8&selm=h4e99.8
8861%24n04.2529857%
40twister2.libero.it
o a questa:
http://www.osl.iu.edu/research/mtl/
--
Gerolamo

 e poi se fosse un probl di "off by 1" windows si sarebbe lamentato, no?
Non necessariamente, di norma il comportamento e' indefinito -- Windows, in
particolare, non si lamenta se sfori entro 4 Kb[1].
Ciao!
*** Azimuth ***
[1] Ovviamente, la cosa e' un pelino piu' complessa... :-)

 matrice senza errori... PERCHE?
Non ho studiato attentamente il codice, però ho notato la mancanza della
definizione di un costruttore copia. 
Quando operator+ restituisce sum, viene invocato il costruttore copia
sintetizzato dal compilatore, che nel nostro caso è inadeguato in quanto
copia il valore del puntatore 'matrix' e non il contenuto dell'array. Il
valore di 'matrix' si troverà perciò ad essere condiviso da oggetto copia
e oggetto originale, il cui distruttore presumibilmente invocherà
delete[].
Se, anzichè usare new[]/delete[], avessimo usato std::vector<int>, non
avremmo avuto questo problema.
Max

 Non so se questi possono andare bene!
si, hai ragione infatti nella prima stesura facevo una cosa del tipo
-----------------------------
for ( int i=0; i<=x; i++ )
    for ( int j=0; j<=y; j++ )
      *(sum.matrix + i*(y+1) + j ) =
            ((i > row || j > col)? 0 : *(matrix + i*col + j) ) +
            ((i > (right.row) || j > (right.col) )? 0 : *(right.matrix +
i*right.col + j) );
-----------------------------
invece che...
-----------------------------
for ( int i=0; i<=x; i++ )
    for ( int j=0; j<=y; j++ )
      *(sum.matrix + i*(y+1) + j ) =
            ((i > row || j > col)? 0 : *(matrix + i*(col+1) + j) ) +
            ((i > (right.row) || j > (right.col) )? 0 : *(right.matrix +
i*(right.col+1) + j) );
-----------------------------
xò come t ho detto se faccio:
----------------------------
Matrix Matrix::operator+( const Matrix &right ) const
{                                                        // bad 1st & last
...
cout << sum << endl;
return sum;
}
-----------------------------
sum viene "stampata bene e restituita male"
è questo che proprio non capisco, vedi?
Quindi nn credo che il problema sia nei vari loop
----------
Sto iniziando a valutare la possibilità che sia colpa del compilatore...[1]
ma il Dev-cpp va bene a tutti, nn capisco perche solo con me debba fare i
capricci
CIAO e grazie ancora!
dan
///
Nota:
[1] tempo fa l'istruzione "system("PAUSE");" mi faceva impallare un
programma... esempio di bug

 avremmo avuto questo problema.
Fino ad ora è la teoria che mi piace di più!
cmq nn ho usato vector per vari motivi:
1. x ignoranza: ho una conoscienza molto scarsa della STL
2. Questa classe l'ho fatta primaditutto per scopi didattici: a me nn serve
il programma di per se mi serve programmare;
3. (potrebbe essere una cazzata) Usando un oggetto della STL cme vector
rischio di appesantire il programma in primis:
la classe matrix mi serve x implemetare un classe sui grafi... l'oggetto
grafo mi servira' x un programma che devo portare all'esame di ASD.
Ciao e Grazie anche a te!
Daniele

 Quindi nn credo che il problema sia nei vari loop
Comunque ho provato ora a compilare il tuo codice, ma secondo il mio
compilatore[1] mancano le definizioni di "Matrix::erase()" e
"Matrix::~Matrix()".
Ciao!
*** Azimuth ***
[1] MS VC++ 6.0 SP3

Ciao A tutti, vi ringrazio per il copioso interesse verso il mio problema...
visto che alcuni di voi hanno provato a compilare il mio codice, ecco la
classe completa "matrix.h"
Spero davvero di capire dov'è che sbaglio...
Fiducioso nelle vostre menti (che lecchino!)
Daniele
****************************************************************************
****
#ifndef MATRIX_H
#define MATRIX_H

using namespace std;
class Matrix {

    public:




    private:

};
#endif




fill( self );
}
//------------------------------------------------------


fill( self );
}
//------------------------------------------------------


//------------------------------------------------------
void Matrix::print() const
{

cout << endl << endl;
/*
for ( int i=0; i<=row; i++ )
    {
    for ( int j=0; j<=col; j++ )
       cout << setw( 4 ) << *(matrix + i*(col+1) + j);        // 4 should be
tab
    cout << endl << endl;
    }
*/
}
//------------------------------------------------------
void Matrix::erase()
{
for ( int i=0; i<=row; i++ )
   for ( int j=0; j<=col; j++ )
     *(matrix + i*(col+1) + j) = 0;
}
//------------------------------------------------------
Matrix::~Matrix()
{
delete [] matrix;
matrix= NULL;
}
//------------------------------------------------------
int Matrix::getEntry ( int x, int y ) const
{
if ( x<0 || y<0 || x>row || y>col )
return 0;
return *(matrix + x*(col+1) + y );
}
//------------------------------------------------------
bool Matrix::setEntry ( int x, int y, int val )
{
if ( x<0 || y<0 || x>row || y>col )
return false;
*( matrix + x*(col+1) + y ) = val;
return true;
}
//------------------------------------------------------
//                 Overloading Functions
//------------------------------------------------------
Matrix &Matrix::operator=( const Matrix &right )
{
int k = (right.row+1)*(right.col+1);
if ( row!=right.row || col!=right.col )
   {
   delete [] matrix;
   row=right.row;
   col=right.col;
   matrix = new int[ k ];
   }
for ( int i=0; i< k; i++ )
   *(matrix + i ) = *(right.matrix + i );
/*
for ( int i=0; i<=col; i++ )
    for ( int j=0; j<=row; j++ )
        *(matrix + i*(col+1) + j) = *(right.matrix + i*(col+1) + j);
*/
        return *this;
}
//------------------------------------------------------
Matrix Matrix::operator+( const Matrix &right ) const
{                                                        // bad 1st & last
value
int x = ( row > right.row )? row : right.row,
    y = ( col > right.col )? col : right.col;
Matrix sum( x, y, 1 );
for ( int i=0; i<=x; i++ )
    for ( int j=0; j<=y; j++ )
      *(sum.matrix + i*(y+1) + j ) =
            ((i > row || j > col)? 0 : *(matrix + i*(col+1) + j) ) +
            ((i > (right.row) || j > (right.col) )? 0 : *(right.matrix +
i*(right.col+1) + j) );
return sum;
}
//------------------------------------------------------
Matrix Matrix::operator* ( const Matrix &right ) const
{
int x = row,
    y = right.col;                                  // bad 1st & -sometimes-
last value
Matrix prod( x, y, 1 );
prod.erase();
int max = ( col > right.row )? col : right.row;
for ( int i=0; i<=x; i++ )
    for ( int k=0; k<=y; k++ )
        for ( int a=0; a<=max; a++ )
           *(prod.matrix + i*(y+1) + k ) +=
                   (( a <= col )? *(matrix + i*(col+1) + a) : 0 ) *
                   (( a <= right.row )? *(right.matrix + a*(right.col+1) +
k ) : 0 );
//prod.print();                           // test
//cout << endl;                           //
return prod;
}
//------------------------------------------------------
bool Matrix::operator==( const Matrix &right ) const
{
if ( col != right.col || row != right.row )
   return false;
for ( int i=0; i<=row; i++ )
    for ( int j=0; j<=col; j++ )
        if ( *(matrix + i*(col+1) + j ) != *(right.matrix + i*(col+1) +
j ) )
           return false;
return true;
}
//------------------------------------------------------
bool Matrix::operator!= ( const Matrix &right ) const
{
if ( col != right.col || row != right.row )
   return true;
for ( int i=0; i<=row; i++ )
    for ( int j=0; j<=col; j++ )
        if ( *(matrix + i*(col+1) + j ) != *(right.matrix + i*(col+1) +
j ) )
           return true;
return false;


 "Matrix::~Matrix()".
mannaggia a me e a quando ho pensato a tagliare il sorgente per rendere il
post + piccolo!
:-)
cmq ora ho postato tutta la classe (è il post da 8kb (secondo Outlook));

 Daniele
Ci daresti anche un esempio di main, per far prima?
*** Azimuth ***

 rischio di appesantire il programma in primis:
std::vector<> è stato pensato proprio come alternativa standard all'uso di
new[]/delete[]. Non vedo perchè nel tuo caso debba comportare penalità in
fatto di prestazioni, o "appesantimento". Dopoutto, std::vector<>
incapsula ciò che tu hai comunque implementato, unitamente a ciò che ti
sei dimenticato di implementare.
Max


Compilando col Microsoft Visual C++ 6 ottengo errori:
C:\Test\console\fileout.cpp(302) : error C2248: 'row' : cannot access
private member declared in class 'Matrix'
        C:\Test\console\fileout.cpp(51) : see declaration of 'row'
E' l'ennesimo baco del compilatore microsoft?
Maurus


eccoti il mio tester
:-)
Dan
*******************************************
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "matrix.h"
int main(void)
{
srand( time( NULL ) );
Matrix m1( 6, 5, true );
Matrix m2( 4, 7, true );
Matrix m3( 2, true );
Matrix m4( 2, true );
cout << m1 <<  "\n\t\tpause 1..." << endl << endl;
system("PAUSE");
m2.print();
cout  << "\n\t\tpause 2..." << endl << endl;
system("PAUSE");
m3 = m1 + m2;
cout << m3  << "\n\t\tpause 3..." << endl << endl;
system("PAUSE");
m4 = m1*m2;
cout << m4  << "\n\t\tpause 4..." << endl << endl;
char i;
cout << "Enter a char to end..." << endl;
   cin >> i;
   return 0;
}

 sei dimenticato di implementare.
bhè nel mio caso avrà un peso poco rilevante, ma sufficente da determinare
un abbasamento del voto:
usando un puntatore a memoria ho accesso diretto ai dati, nessuna chiamata a
funzione etc etc, cosa che mi aspetto d trovare nei vector, quindi
prestazioni maggiori, nonchè un professore felice poichè ho rispettato i
versetti del suo vangelo (cioè il libro che c ha fatto comprare e
studiare)... se avessi usato vector avrei avuto un programma + lento e un
prof. incazzato!
Quando sarò ing. usero' vector! :-)
Grazie davvero! La tua soluzione mi sembra giusta e appagante, ora al
lavoro!!
Daniele


boh!!! l'operator<< è friend quindi l'accesso ai membri private ce l'ha!!
e poi col dev-cpp va benissimo!
DAn

 andare da 0 a k-1 (anche l'elemento zero devi contare).
Guarda che il ciclo che hai scritto va da 0 a k-2... :-)
-- 
In silenzio anche un idiota sembra intelligente. Ma non c'č problema,
l'idiota vuol sempre dire la sua.