Got a tip for us? Let us know
Apr 17, 2011, 12:55 AM  #1 
C++ new statement. Help me
Hi,
Apparently I write a little code which use "new" inside of my function, but it appear that it do not work well. Code:
#include "iostream" #include "cstdlib" #include "iomanip" using namespace std; void inputMatrix(double **M,int& line,int& col){ cout << "Input number of lines and columns : "; cin>>line>>col; M=new double*[line]; for (int i=0; i<line; i++) { M[i]=new double[col]; } cout << "Input your matrix :"<<endl; for (int i=0; i<line; i++) for (int j=0; j<col; j++) cin>>M[i][j]; } void killMatrix(double **M,int line,int col){ cout<<"DD"; for (int i=0; i<line; i++) delete[] M[i]; delete[] M; } int main(){ int line1,col1,line2,col2; double **M1,**M2,**result; inputMatrix(M1,line1,col1); cout<<line1<<" "<<col1<<endl; cout<<M1[0][1]<<endl; // inputMatrix(M2,line2,col2); // cout<<line2<<" "<<col2<<endl; // result=add2Matrix(M1,M2,line1,col1,line2,col2); // outputMatrix(result,line1,col1); killMatrix(M1,line1,col1); // killMatrix(M2,line2,col2); // killMatrix(result,line1,col1); return 0; } I guess "new" do not work properly. Does anyone have any ideas ? Thanks in advance. 

0 
Apr 17, 2011, 03:04 AM  #2 
You need extra level of indirection for M in inputMatrix.
Code:
void inputMatrix(double ***M,int& line,int& col){ cout << "Input number of lines and columns : "; cin>>line>>col; (*M)=new double*[line]; for (int i=0; i<line; i++) { (*M)[i]=new double[col]; } cout << "Input your matrix :"<<endl; for (int i=0; i<line; i++) for (int j=0; j<col; j++) cin>>(*M)[i][j]; } Code:
inputMatrix(&M1,line1,col1); Or alternatively, don't use an outstyle parameter for M, instead pass it back as the result. Code:
double **inputMatrix(int& line,int& col){ cout << "Input number of lines and columns : "; cin>>line>>col; double **M=new double*[line]; for (int i=0; i<line; i++) { M[i]=new double[col]; } cout << "Input your matrix :"<<endl; for (int i=0; i<line; i++) for (int j=0; j<col; j++) cin>>M[i][j]; return M; } Code:
M1=inputMatrix(line1,col1); But (assuming you're just using C++ as a better C) you should create a matrix struct that binds the pointer, col, and line together. Code:
#include <iostream> #include <cstdlib> #include <iomanip> using namespace std; struct matrix { double **values; int line; int col; }; matrix inputMatrix(){ matrix m; cout << "Input number of lines and columns : "; cin>>m.line>>m.col; m.values =new double*[m.line]; for (int i=0; i<m.line; i++) { m.values[i]=new double[m.col]; } cout << "Input your matrix :"<<endl; for (int i=0; i<m.line; i++) for (int j=0; j<m.col; j++) cin>>m.values[i][j]; return m; } void outputMatrix(const matrix &m) { for (int i=0; i<m.line; i++) { for (int j=0; j<m.col; j++) cout << m.values[i][j] << ' '; cout << endl; } } void killMatrix(matrix &m){ for (int i=0; i<m.line; i++) delete[] m.values[i]; delete[] m.values; m.values = NULL; } int main(){ matrix M1, M2, result; M1 = inputMatrix(); // cout<<m1.line<<" "<<m1.col<<endl; // cout<<m1.values[0][1]<<endl; // M2 = inputMatrix(); // cout<<m2.line<<" "<<m2.col<<endl; // result=add2Matrix(M1,M2); outputMatrix(M1); killMatrix(M1); // killMatrix(M2); // killMatrix(result); return 0; } Last edited by jiminaus; Apr 17, 2011 at 03:13 AM. 

0 
Apr 17, 2011, 03:19 AM  #3 
In that function, where do you use the value M that is passed in? You just overwrite its value. That looks very, very suspicious. The value of M1 never gets defined.


0 
Apr 17, 2011, 07:39 AM  #4  
Quote:
To the OP: I assume you are writing this matrix stuff as a learning exercise. It's a popular exercise to learn OO. You should make your matrix class "selfcontained", and have it clean up after itself. You will run into a bunch of problems on the way: How do you copy matrices? Do you copy its contents? Do you hand out references instead? Who is then responsible for cleaning it up, and how do you prevent other code from accessing zombie matrices?
__________________
Computer Programming: An Introduction for the Scientifically Inclined So how much does an iPhone developer make? My iPhone games: Sjoelen, Mazer (free) 

0 
Apr 17, 2011, 08:03 AM  #5  
Quote:
If this is an OOP exercise, than the OP is totally failing. Actually I picked it up as being a FORTRAN port. But maybe that was just because of the byreference function arguments. 

0 
Apr 17, 2011, 09:16 AM  #6 
well in fact I haven't learnt about OPP yet. I wrote this program 'cause I just had a lesson about Matrix.
anyway, thanks alot . I'll test it out and report later. 

0 
Apr 17, 2011, 03:01 PM  #7 
Always use a single dimension array for rectangular multidimensional arrays. It is so much easier, faster and errorfree.


0 
Apr 18, 2011, 03:34 AM  #8  
Quote:
What I was trying to get at is that when people struggle with a problem in C which is easier solved in C++, it's not going to be by substituting "new" for "malloc"
__________________
Computer Programming: An Introduction for the Scientifically Inclined So how much does an iPhone developer make? My iPhone games: Sjoelen, Mazer (free) 

0 
Apr 18, 2011, 11:20 AM  #9 
OK, here I go.
Code:
/* * matrix.cpp * * * Created by NGUYEN Quang Anh on 4/17/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #include "iostream" #include "cstdlib" #include "iomanip" #include "exception" using namespace std; struct matrix { double **value; int line; int col; }; matrix inputMatrix(int& line,int& col){ cout << "Input number of lines and columns : "; cin>>line>>col; matrix M; M.value=new double*[line]; for (int i=0; i<line; i++) { M.value[i]=new double[col]; } cout << "Input your matrix :"<<endl; for (int i=0; i<line; i++) for (int j=0; j<col; j++) cin>>M.value[i][j]; M.line=line; M.col=col; return M; } void killMatrix(matrix M){ for (int i=0; i<M.line; i++) delete[] M.value[i]; delete[] M.value; } void outputMatrix(matrix M){ for (int i=0; i<M.line; i++) { for (int j=0; j<M.col; j++) cout << setw(3) << M.value[i][j] ; cout << endl; } } matrix add2Matrix(matrix M1,matrix M2){ bool notCorrect=((M1.line != M2.line)(M1.col != M2.col)); if (notCorrect) throw 10; matrix result; result.line=M1.line; result.col=M1.col; result.value=new double*[result.line]; for (int i=0; i<result.line; i++) { result.value[i]=new double[result.col]; } for (int i=0; i<result.line; i++) for (int j=0; j<result.col; j++) result.value[i][j]=M1.value[i][j]+M2.value[i][j]; return result; } matrix multi2Matrix(matrix M1,matrix M2){ bool notCorrect=(M1.col != M2.line); if (notCorrect) throw 10; matrix result; result.line=M1.line; result.col=M2.col; result.value=new double*[result.line]; for (int i=0; i<result.line; i++) { result.value[i]=new double[result.col]; } for (int i=0; i<result.line; i++) { for (int j=0; j<result.col; j++) { result.value[i][j]=0; for (int k=0; k<M1.col; k++) result.value[i][j]+=M1.value[i][k]*M2.value[k][j]; } } return result; } int main(){ int line,col; matrix M1,M2,result; M1=inputMatrix(line,col); M2=inputMatrix(line,col); try { result=multi2Matrix(M1,M2); cout << "Your Result :"<< endl; outputMatrix(result); killMatrix(M1); killMatrix(M2); killMatrix(result); } catch (int i){ if (i==10) cerr << "Cannot execute operation" <<endl; killMatrix(M1); killMatrix(M2); } return 0; } 

0 
Apr 18, 2011, 02:49 PM  #10 
Using more than 2 levels of indirection is poor practice and asking for trouble. It's difficult to read and error prone.


0 
Apr 18, 2011, 06:55 PM  #11  
Quote:
Quote:
Let me show you how your example would look in objectoriented C++ that sandar was advocating. Code:
#include <iostream> #include <cstdlib> #include <iomanip> #include <exception> using namespace std; class matrix { public: static matrix inputMatrix(); matrix(int aLine, int aCol); // Constructor matrix(const matrix& aSrcM); // Copy constructor ~matrix(); // Destructor int line() const { return theLine; } int col() const { return theCol; } double get(int aLine, int aCol) const; void set(int aLine, int aCol, double aValue); private: double** theValue; int theLine; int theCol; }; matrix operator +(const matrix& M1, const matrix& M2); matrix operator *(const matrix& M1, const matrix& M2); ostream& operator <<(ostream& os, const matrix& M); matrix::matrix(int aLine, int aCol) { // TODO: Boundscheck aLine and aCol theLine = aLine; theCol = aCol; theValue = new double*[theLine]; for (int i=0; i<theLine; i++) { theValue[i] = new double[theCol]; } } matrix::matrix(const matrix& M) { theLine = M.line(); theCol = M.col(); theValue = new double *[theLine]; for (int i=0; i<theLine; i++) { theValue[i] = new double[theCol]; // TODO: Replace inner loop with memcpy for (int j=0; j<theCol; j++) { set(i, j, M.get(i, j)); } } } matrix::~matrix() { for (int i=0; i<theLine; i++) delete[] theValue[i]; delete[] theValue; } matrix matrix::inputMatrix() { int line, col; cout << "Input number of lines and columns : "; cin >> line >> col; // TODO: Check line and col are valid matrix M(line, col); cout << "Input your matrix :"<<endl; double v; for (int i=0; i<line; i++) { for (int j=0; j<col; j++) { cin >> v; M.set(i, j, v); } } return M; } ostream& operator <<(ostream& os, const matrix& M) { for (int i=0; i<M.line(); i++) { for (int j=0; j<M.col(); j++) os << setw(3) << M.get(i,j); os << endl; } return os; } matrix operator +(const matrix& M1, const matrix& M2) { bool notCorrect=((M1.line() != M2.line())(M1.col() != M2.col())); // TODO: Replace throwing an int with throwing a std::exception // or a custom subcalss of it if (notCorrect) throw 10; matrix result(M1.line(), M1.col()); for (int i=0; i<result.line(); i++) for (int j=0; j<result.col(); j++) result.set(i, j, M1.get(i,j)+M2.get(i,j)); return result; } matrix operator *(const matrix& M1, const matrix& M2) { bool notCorrect=(M1.col != M2.line); // TODO: Replace throwing an int with throwing a std::exception // or a custom subcalss of it if (notCorrect) throw 10; matrix result(M1.line(), M2.col()); for (int i=0; i<result.line(); i++) { for (int j=0; j<result.col(); j++) { result.set(i,j,0); for (int k=0; k<M1.col(); k++) { result.set(i, j, result.get(i,j) + M1.get(i,k)*M2.get(k,j)); } } } return result; } int main() { matrix M1 = matrix::inputMatrix(); matrix M2 = matrix::inputMatrix(); try { matrix result = M1 * M2; cout << "Your Result :" << endl << result; // result will be automatically destructed by compiler at this point } // TODO: Replace throwing an int with throwing a std::exception // or a custom subcalss of it catch (int i){ if (i==10) cerr << "Cannot execute operation" <<endl; } return 0; // M1 and M2 will be automatically destructed by compiler at this point } 

0 
Apr 19, 2011, 12:14 PM  #12  
Quote:
you mean 2 dimension array ? 

0 
Apr 19, 2011, 04:33 PM  #13  
Quote:
In C, the number of stars in a type is the level of indirection. So int* has 1 level of indirection to the int, int** has 2 levels of indirection to the int, int*** had 3 level of indirection to the int, etc. You didn't use more than 2 levels of indirection. You do use 2 levels of indirection for the 2 dimensional array. The first solution I posted for inputMatrix increased the levels of indirection to 3, so that it could pass back the pointer to the 2 dimensional array which it allocates inside itself. The 2 dimensional array is double**, so a pointer to that is double***, which has 3 levels of indirection. 

0 
Apr 20, 2011, 09:33 AM  #14 
Code:
double get(int aLine, int aCol) const; void set(int aLine, int aCol, double aValue); Thanks alot 

0 
Apr 20, 2011, 09:49 AM  #15  
Quote:
Lee 

0 
Apr 20, 2011, 10:13 AM  #16  
Quote:
Oh ya, and another question : Code:
matrix::matrix(const matrix& M) { theLine = M.line(); theCol = M.col(); theValue = new double *[theLine]; for (int i=0; i<theLine; i++) { theValue[i] = new double[theCol]; // TODO: Replace inner loop with memcpy for (int j=0; j<theCol; j++) { set(i, j, M.get(i, j)); } } } http://www.cplusplus.com/reference/c...string/memcpy/ Sorry for asking lot of questions It can't be help since I'm a totally newbie. I just learned about C++ 6 months ago, and since I want to learn it myself, alot of new things appear in front of me and I'm speechless lol :d 

0 
Apr 20, 2011, 11:19 AM  #17  
Quote:
Quote:
Code:
double *sourceRow = M.getRow(i); memcpy(theValue[i],sourceRow,theCol*sizeof(double)); Lee 

0 
Apr 20, 2011, 04:35 PM  #18 
Sorry, I did forget them. They were defined inline in the class at one stage. I removed them from there intending to defined them later with TODO comments about bounds checking the parameters.


0 
«
Previous Thread

Next Thread
»
Thread Tools  Search this Thread 
Display Modes  
Similar Threads  
thread  Thread Starter  Forum  Replies  Last Post 
Ifelse statement not evaluating  alexatwater  iPhone/iPad Programming  2  Mar 13, 2014 02:38 PM 
applescript if statement  wild4life2013  Mac Programming  2  Aug 6, 2013 12:16 AM 
Why doesnt the else statement work in this?  bigMAC28  Mac Programming  2  Aug 4, 2013 05:44 PM 
Can someone explain this statement  DMB15  iPhone  6  Sep 12, 2012 06:41 PM 

All times are GMT 5. The time now is 07:56 PM.