rule of three exercise unexpected result [duplicate] - c++

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 7 years ago.
I try to learn C++ basis in my free time and follow exercises of a book. Firstly, when I enter 9 as row and 8 as column I get malloc freeing error. Secondly, I get 0 as output I can't see what I enter. I want to write the program because I can reinforce rule of three. It's certainly not homework. Besides, I think it is hard question and efficient question. If the question can be answered, it will be helpful. Because I've searched on google I can't find out halfway decent thing about solution. Also, can you check my copy constructor, assignment operator and destructor and tell me where my errors at?
Write a class TwoD that implements the two-dimensional dynamic array
of doubles using ideas from this display in its constructors. You
should have a private member of type pointer to double to point to
the dynamic array, and two int (or unsigned int) values that are
MaxRows and MaxCols. You should supply a default constructor for which
you are to choose a default maximum row and column sizes and a
parameterized constructor that allows the programmer to set maximum
row and column sizes. Further, you should provide a void member
function that allows setting a particu- lar row and column entry and a
member function that returns a particular row and column entry as a
value of type double. Remark: It is difficult or impossible (depending
on the details) to overload [ ] so it works as you would like for
two-dimensional arrays. So simply use accessor and mutator functions
using ordinary function notation. Overload the + operator as a friend
function to add two two-dimensional arrays. This function should
return the TwoD object whose ith row, jth column element is the sum of
the ith row, jth column element of the left-hand operand TwoD object
and the ith row, jth column element of the right-hand operand TwoD
object. Provide a copy constructor, an overloaded operator =, and a
destructor. Declare class member functions that do not change the data
as const members.
My effort
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class TwoD
{
public:
TwoD();
TwoD(int row, int column);
void setRowCol();
double getVal(int row, int column);
friend const TwoD operator +(const TwoD& first, const TwoD& second);
int getterRow() const;
int getterCol() const;
void setterRow(int row);
void setterCol(int column);
TwoD(const TwoD& object);
TwoD& operator =(const TwoD& rightSide);
void putArr() const;
~TwoD();
static TwoD constructFromUserInput();
private:
int MaxRows;
int MaxCols;
double **arr;
};
int main(int argc, char const *argv[])
{
cout << "All size of TwoD object must be same\n\n";
TwoD arr1 = TwoD::constructFromUserInput();
TwoD arr2 = TwoD::constructFromUserInput();
TwoD arr3;
arr3 = arr1 + arr2;
TwoD arr4(arr3);
arr1.putArr();
arr2.putArr();
arr3.putArr();
arr4.putArr();
return 0;
}
void TwoD::setRowCol()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
MaxRows = r_user;
MaxCols = c_user;
TwoD(MaxRows,MaxCols);
}
TwoD::TwoD(int row, int column)
: MaxRows(row), MaxCols(column)
{
arr = new double*[row];
for (int i = 0; i < row; i++)
{
arr[i] = new double[column];
}
for (int i = 0; i < MaxRows; i++)
{
for (int j = 0; j < MaxCols; j++)
{
cout << "Enter for " << i << j << "=> ";
cin >> arr[i][j];
}
}
}
TwoD::TwoD()
: MaxRows(2), MaxCols(2)
{
arr = new double*[2];
for (int i = 0; i < 2; i++)
{
arr[i] = new double[2];
}
}
double TwoD::getVal(int row, int column)
{
return arr[row][column];
}
const TwoD operator +(const TwoD& first, const TwoD& second)
{
TwoD sum;
for (int i = 0; i < first.MaxRows; i++)
{
for (int j = 0; j < first.MaxCols; j++)
{
sum.arr[i][j] = first.arr[i][j] + second.arr[i][j];
}
}
return sum;
}
TwoD::TwoD(const TwoD& object)
{
MaxRows = object.MaxRows;
MaxCols = object.MaxCols;
arr = new double*[MaxRows];
for (int i = 0; i < MaxRows; i++)
{
arr[i] = new double[MaxCols];
}
for ( int i = 0; i < MaxRows; i++ )
{
for ( int j = 0; j < MaxCols; j++ )
{
arr[i][j] = object.arr[i][j];
}
}
}
TwoD::~TwoD()
{
for (int i = 0; i < MaxRows; i++)
delete [] arr[i];
delete [] arr;
}
TwoD& TwoD::operator =(const TwoD& rightSide)
{
if (this == &rightSide)
{
return *this;
}
for (int i = 0; i < MaxRows; i++)
delete [] arr[i];
delete [] arr;
arr = new double*[rightSide.MaxRows];
for (int i = 0; i < rightSide.MaxRows; i++)
{
arr[i] = new double[rightSide.MaxCols];
}
MaxRows = rightSide.MaxRows;
MaxCols = rightSide.MaxCols;
for (int i = 0; i < MaxRows; i++)
{
for (int j = 0; j < MaxCols; j++)
{
arr[i][j] = rightSide.arr[i][j];
}
}
return *this;
}
void TwoD::putArr() const
{
for (int i = 0; i < MaxRows; i++)
{
for (int j = 0; j < MaxCols; j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
}
int TwoD::getterRow() const
{
return MaxRows;
}
int TwoD::getterCol() const
{
return MaxCols;
}
void TwoD::setterRow(int row)
{
MaxRows = row;
}
void TwoD::setterCol(int column)
{
MaxCols = column;
}
TwoD TwoD::constructFromUserInput()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
// Construct an object.
TwoD obj(r_user, c_user);
// Return the object
return obj;
}

your copy constructor creates the arrays, but never copies the contents.
The copy assignment operator does this correctly. For that matter, you have loads of duplicated new[] loops, a couple of delete[] loops, and you should have two copy loops. Factor these out into functions, and you only need to get them right once.
sum creates a default-sized object and then, probably, overruns both row and column dimensions. The usual (easy and correct) implementation is to create a local copy of the left-hand argument (using the copy ctor you fixed above) and forward to operator+=. That operator is much easier to get right.
you have a way of printing these matrices out. Do it! Do it everywhere! This makes it easy to see which stage things went wrong at.
this book doesn't sound very good. It's teaching poor practice for no obvious reason (the operator+ trick is standard, you should use unique_ptr if you can't use vector, etc. etc.)
Edits: I'll reply to some comments here because they're in danger of turning into a chat session, and I don't want to spend more time on this.
I have fixed copy constructor is it right?
This is a good time to figure out how to test and debug code. Add print statements, use a debugger, split things out into functions you can test and then write tests for them.
what you mean a couple of delete[] loops and having two copy loops
Look for loops in your code. I can see 3 loops calling new[], all doing essentially the same thing. I can see 2 loops calling delete[], one in the destructor and one in the copy assignment operator. Just search your own code for the for keyword!
I really don't find a way to print out matrices
so where did TwoD::putArr come from? Admittedly ostream& operator<<(ostream&, TwoD const &) would be a better name for it, but you wrote it so you might as well use it.
I can't get destructor into main()
you can't stop the destructor being called when main finishes - your objects go out of scope then. Just stick a breakpoint in the destructor and it will be called.
Because arr is private how can I test?
you can still see it in the debugger, you can still print the contents (as above), you can still call getVal from a unit test, you can just make it public until you've figured out your problem(s)

Problem with your code:
void TwoD::setRowCol()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
MaxRows = r_user;
MaxCols = c_user;
///
/// This constructs a new TwoD object but does not change
/// object on which the function was invoked.
///
TwoD(MaxRows,MaxCols);
}
Ways to solve the problem:
Update the member data
void TwoD::setRowCol()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
// Delete the current memory
for (int i = 0; i < MaxRows; i++)
{
delete [] arr[i];
}
delete [] arr;
MaxRows = r_user;
MaxCols = c_user;
// Allocate new memory.
arr = new double*[MaxRows];
for (int i = 0; i < MaxRows; i++)
{
arr[i] = new double[MaxCols];
}
// Now read the data.
for (int i = 0; i < MaxRows; i++)
{
for (int j = 0; j < MaxCols; j++)
{
cout << "Enter for " << i << j << "=> ";
cin >> arr[i][j];
}
}
}
Create a function that returns a brand new object
I recommend this method.
First, update the constructor that takes the row and the column so that it does not have any code to read data from user input.
TwoD::TwoD(int row, int column)
: MaxRows(row), MaxCols(column)
{
arr = new double*[row];
for (int i = 0; i < row; i++)
{
arr[i] = new double[column];
}
}
Second, add a static member function to construct an object from user input.
static TwoD constructFromUserInput();
and implement it as:
TwoD TwoD::constructFromUserInput()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
// Construct an object.
TwoD obj(r_user, c_user);
// Now read the data.
for (int i = 0; i < r_user; i++)
{
for (int j = 0; j < c_user; j++)
{
cout << "Enter for " << i << j << "=> ";
cin >> obj.arr[i][j];
}
}
// Return the object
return obj;
}
Third, use the new function from main.
int main(int argc, char const *argv[])
{
cout << "All size of TwoD object must be same\n\n";
TwoD arr1 = TwoD::constructFromUserInput();
TwoD arr2 = TwoD::constructFromUserInput();
TwoD arr3;
arr3 = arr1 + arr2;
arr1.putArr();
arr2.putArr();
arr3.putArr();
return 0;
}

Related

How to declare arrays which are functions argument, if their size is to be determined by the user input at the start of program

For my "basics of programming" project i was ordered to make a "memory game". 2 players in their respective turns choose which cards to reveal on a "m x n" sized board. "m" and "n" are to be chosen at the start of each game. My question is, how can I create an array of structures used to display the board a the moment of user's input. So far I just used a const int to create an array of a maximum size, however more than 95% of the arrays indexes are empty using this method. Is there a way to create the array right after user's input while also having those functions defined and declared with an array of structures that's the size of the input? Here's my code so far:
const int MAX_M = 1000;
const int MAX_N = 1000;
Karta Plansza2[MAX_M][MAX_N];
void SprawdzanieParzystosci(int& m, int& n);
void RozmiaryTablicy(int& m, int& n);
void generuj(int m, int n, Karta Plansza[MAX_M][MAX_N]);
void WyswietleniePlanszy(int m, int n, Karta Plansza[MAX_M][MAX_N]);
void generuj(int m, int n, Karta Plansza[][MAX_N])
{
srand((unsigned int)time(NULL));
char A;
int B;
int C;
int D;
int k = 0;
int w1, w2, k1, k2;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
Plansza[i][j].WartoscKarty = 0;
}
while (k < (m*n))
{
A = char(rand() % 10 + 65);
B = (rand() % 10);
C = (rand() % 10);
D = ((rand() % 2000000) + 1);
do{
w1 = rand() % m;
k1 = rand() % n;
}while(Plansza[w1][k1].WartoscKarty != 0);
Plansza[w1][k1].ZnakPierwszy = A;
Plansza[w1][k1].LiczbaPierwsza = B;
Plansza[w1][k1].LiczbaDruga = C;
Plansza[w1][k1].WartoscKarty = D;
k++;
do{
w2 = rand() % m;
k2 = rand() % n;
} while (Plansza[w2][k2].WartoscKarty != 0);
Plansza[w2][k2].ZnakPierwszy = A;
Plansza[w2][k2].LiczbaPierwsza = B;
Plansza[w2][k2].LiczbaDruga = C;
Plansza[w2][k2].WartoscKarty = D;
k++;
}
}
/////////////////////////////////////////////////////
void WyswietleniePlanszy(int m, int n, Karta Plansza[MAX_M][MAX_N])
{
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
cout << "***" << setw(5);
cout << "\n";
for (int j = 0; j < n; j++)
cout << "*" << Plansza[i][j].ZnakPierwszy << "*" << " ";
cout << "\n";
for (int j = 0; j < n; j++)
cout << "*" << Plansza[i][j].LiczbaPierwsza << "*" << " ";
cout << "\n";
for (int j = 0; j < n; j++)
cout << "*" << Plansza[i][j].LiczbaDruga << "*" << " ";
cout << "\n";
// for(int j = 0; j < 10; j++)
// cout << wzor[i][j].num4 << " ";
for (int j = 0; j < n; j++)
cout << "***" << setw(5);
cout << "\n";
cout << endl;
}
}
/////////////////////////////////////////////////////
void RozmiaryTablicy(int& m, int& n)
{
cout << "Podaj rozmiar m tablicy: ";
cin >> m;
cout << "Podaj rozmiar n tablicy: ";
cin >> n;
}
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
void SprawdzanieParzystosci(int& m, int& n)
{
while ((m * n) % 2 != 0 || (m <= 0) || (n <= 0)) {
RozmiaryTablicy(m, n);
if((m * n) % 2 != 0 || (m <= 0) || (n <= 0)) cout << "Zle dane. Prosze podac dane jeszcze raz" << endl;
}
}
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
int main()
{
int m =1;
int n =1;
SprawdzanieParzystosci(m, n);
generuj(m,n,Plansza2);
WyswietleniePlanszy(m,n,Plansza2);
cout << m << endl;
cout << n << endl;
system("pause");
return 0;
}
For example, If the user inputs m = 5 an n = 6 it would create an Plansza[5][6] array instead of a Plansza[1000][1000] array
Quick hack of a board, remark the nice board[row][column] notation and the returned reference to the field. C++17 (might work in C++14)
#include <iostream>
#include <memory>
#include <cstring>
using DaType = char;
class Board {
int rows = 0;
int cols = 0;
std::unique_ptr<DaType[]> board; // RAII
public:
class Row {
DaType *board;
public:
Row(DaType *row) : board(row) {}
DaType& operator[](int col) { return board[col]; }
};
Board(int row, int col) : rows(row), cols(col), board(std::make_unique<DaType[]>(row*col)) { memset(board.get(), '.', rows*cols); }
Row operator[](int row) { return Row(board.get()+row*cols); }
};
int main() {
const int sx = 6, sy = 10;
Board board(sx,sy);
board[3][5] = 'x';
for (int i = 0; i < sx; ++i ) {
for (int j = 0; j < sy; ++j )
std::cout << board[i][j];
std::cout << '\n';
}
}
Ps. it seemed simpler last time I did this ...
Update thanks to IlCapitano
class Board {
int rows = 0;
int cols = 0;
std::unique_ptr<DaType[]> board; // RAII
public:
Board(int row, int col) : rows(row), cols(col), board(std::make_unique<DaType[]>(row*col)) { memset(board.get(), '.', rows*cols); }
DaType *operator[](int row) { return board.get()+row*cols; }
};
The easiest way to solve this would be to just use std::vector, since the size of arrays in arguments, stackallocations, etc. has to be known at compile-time.
The easiest option without using vector would be to declare Plansza2 as a Karta* and allocate the memory dynamically after SprawdzanieParzystosci using Plansza2 = new Karta[m*n]; (Don't forget to call delete[](Plansza2); before ending your program). If you do this you can access the cells with Plansza2[y * m + x] (assuming m is width and n is height). The advantage of mapping the 2-dimensional array to a 1 dimensional array by placing all rows after one another is that you only need one allocation and one deletion, and furthermore it improves cache-friendliness.
A cleaner way to solve this (removing the possibility for a memory leak if something throws an exception or you forget to call delete) would be to create your own class for 2-dimensional arrays, that would call new[] in the constructor and delete[] in the destructor. If you do that you could define Karta& operator()(int x, int y); and const Karta& operator()(int x, int y) const; to return the appropriate cell, allowing you to access a cell with dynamicMap(x, y). operator[] can only take one argument and is therefor more complicated to use to access a 2-dimensional array (you can for example take an std::pair as the argument or return a proxy-class that also has operator[] defined). However if you write your own destructor, you need to take care of the copy-(always) and move-(c++11 onwards) constructors and assignment operators, since the default instantiations would lead to your destructor trying to delete the same pointer multiple times. An example for a move-assignment operator is:
DynamicMap& DynamicMap::operator=( DynamicMap&& map ){
if(this == &map)
return *this; //Don't do anything if both maps are the same map
dataPointer = map.dataPointer; //Copy the pointer to "this"
map.dataPointer = nullptr; //Assign nullptr to map.dataPointer because delete[] does nothing if called with null as an argument
//You can move other members in the above fashion, using std::move for types more complex than a pointer or integral, but be careful to leave map in a valid, but empty state, so that you do not try to free the same resource twice.
return *this;
}
The move constructor doesn't require the if-clause at the start, but is otherwise identical and the copy-constructor/assignment operator should probably declared as = delete; since it will probably be a bug if you copy your map. If you do need to define the copy operations, do not copy the pointer but instead create a new array and copy the contents.

C6385 warning in VS (in regard to dynamic arrays)

My code is supposed to print the Union and Intersection of two sets of integers.
Why do I get this warning?
Is it because I use dynamic arrays and it's size could be anything in runtime?
How can I fix it? My code works fine but this warning really bugs me.
P.S: I know it would be a lot easier to use std::vector but my teacher required to use arrays.
#include <iostream>
using namespace std;
void UnionFunc(int[],int,int[],int,int[],int&);
void IntersectionFunc(int[], int, int[], int, int[], int&);
int main() {
int* A;
int SizeA;
int* B;
int SizeB;
int* Union;
int UnionSize=0;
int* Intersection;
int IntersectionSize=0;
cout << "Enter the Size of First Set : "; cin >> SizeA;
A = new int[SizeA];
cout << "Enter the Size of Second Set : "; cin >> SizeB;
B = new int[SizeB];
Intersection = new int[SizeA >= SizeB ? SizeB : SizeA];
Union = new int[SizeA + SizeB];
for (int i = 0; i < SizeA; i++) {
cout << "Set A[" << i + 1 << "] = ";
cin >> A[i];
}
for (int i = 0; i < SizeB; i++) {
cout << "Set B[" << i + 1 << "] = ";
cin >> B[i];
}
UnionFunc(A,SizeA,B,SizeB,Union,UnionSize);
IntersectionFunc(A, SizeA, B, SizeB, Intersection, IntersectionSize);
cout <<endl<< "Union Set : ";
for (int i = 0; i < UnionSize; i++) {
cout << Union[i] << ",";
}
cout <<endl <<"Intersection Set : ";
for (int i = 0; i < IntersectionSize; i++) {
cout << Intersection[i] << ",";
}
system("pause>n");
return 0;
}
void UnionFunc(int A[],int SizeA, int B[],int SizeB, int Union[],int &UnionSize) {
//Adding First Array to Union Array
for (int i = 0; i < SizeA;i++) {
Union[i] = A[i];
UnionSize++;
}
//Checking if second array's elemnts already exist in union arry, if not adding them
bool exist;
for (int i = 0; i < SizeB; i++) {
exist = false;
for (int j = 0; j < UnionSize; j++) {
if (B[i] == Union[j] ) {
exist = true;
}
}
if (exist == false) {
Union[UnionSize] = B[i];
UnionSize++;
}
}
}
void IntersectionFunc(int A[], int SizeA, int B[], int SizeB, int Intersection[], int& IntersectionSize) {
for (int i = 0; i < SizeA; i++) {
for (int j = 0; j < SizeB; j++) {
if (A[i] == B[j]) {
Intersection[IntersectionSize] = A[i];
IntersectionSize++;
}
}
}
}
Is it because I use dynamic arrays and it's size could be anything in
runtime?
Yes! The compiler doesn't know (and, as your code is written, can't know) that both SizeA and SizeB will be 'valid' numbers - so the size of the three int arrays you create could be less than is required for the Intersection[i] 'read' to be valid.
A 'quick and dirty' fix for this is to provide a visible guarantee to the compiler that the arrays you create will be at least a certain size, like this:
A = new int[max(1,SizeA)]; // Compiler can now 'see' a minimum size
And similarly for the other allocations you make with the new[] operator.
(I have tested this with VS2019, adding the max(1,SizeA) and max(1,SizeB) 'fixes' to just the allocations of A and B and the warning is removed.)

Incorrect output from overloaded [] function

The spec says that the function must return the row of the matrix specified by the "row number" in []
Class Definition:
class Matrix
{
public:
//functions taken out
private:
double ** matrix; // the matrix array
unsigned rows; // # rows
unsigned cols; // # columns
};
The brief main:
cout << "Test []: " << endl;
try {
Matrix row = m0[0]; //**m0 is Matrix m0(1,1); where the constructor creates the appropriate array**
cout << row << endl;
row = m0[1];
cout << row << endl;
row = m0[100]; // should throw an exception
} catch (const char * err) {
cout << err << endl;
}
The Function implementation:
double& Matrix::operator [](const unsigned int &sub)
{
if( sub >= rows)
{
const char * error = "Error: invalid row index";
throw error;
} else
{
return *matrix[sub];
}
}
Overloaded << operator for display:
//This is working for my other displays so this shouldn't be the problem
ostream &operator << (ostream &ostrm, const Matrix &obj)
{
//Loop through to display
for(unsigned int i = 0; i < obj.rows; i++)
{
for(unsigned int j = 0; j< obj.cols; j++)
{
ostrm << setw(10) << setprecision(3) << obj.matrix[i][j];
}
ostrm << endl;
}
return ostrm;
}
Overloaded = operator:
//Again this works for everything else
Matrix& Matrix::operator=(const Matrix &rhs)
{
//Copy Rows and Cols
rows = rhs.rows;
cols = rhs.cols;
//If statement to check for self assignment
if(&rhs == this)
{
return *this;
}
else
{
delete [] matrix;
matrix = new double*[rows]; //Allocate Dynamic Array
//Deep copy elements by looping and copying each element
for(unsigned int i = 0; i < rows; i++)
{
matrix[i] = new double[cols];
for(unsigned int j = 0; j < cols; j++)
{
matrix[i][j] = rhs.matrix[i][j];
}
}
return *this;
}
}
My Output:
Test []:
Error: invalid row index
Expected Output:
Test []:
17.2 -3 -0.5 6
8.2 4 3 1
Error: invalid row index
I am uncertain as to why the rows are not displaying or possibly not even being stored.
Thanks in advance
Aside comment: your assignment operator is leaking memory: you delete matrix, but you need to delete also the individual rows (using the original value of rows)
for(unsigned int i = 0; i < rows; i++)
delete[] matrix[i];
Your operator[] should return a double[] or double *, not a double - you want to return a whole row, not a single value.
Your "test []" code should not even compile... Matrix row = m0[0]; assigns a double to a Matrix object.
Etc.
Bottom line: just use Eigen.
The first line is wrong.
operator[] is returning a double. You assign it to a Matrix. The Matrix is initialized with one value. You've taken out your Constructors. Which one is called? I assume, the called constructor initializes the rows and cols members with zero. When they're zero, the output stream operator does nothing.
I managed to find a solution that worked for my question. Below is what I implemented in case someone else has a similar problem.
Matrix temp(1, cols); //Calls my constructor here
for(unsigned int i = 0; i < 1; i++)
{
for(unsigned int j = 0; j < cols; j++)
{
temp.matrix[i][j] = matrix[sub][j]; //Accessed temp's matrix and assigned it with what is in the matrix that called the function
}
}
return temp;
Thank you to everyone who helped and added some input. Much appreciated

Dual selection sorting an array - honestly stumped

void dualSort(int [], double [], int);
int main()
{
const int ARRAY_SIZE = 1000; // Array size
double accountNumbers[ARRAY_SIZE]; // Array with 1000 elements
double accountBalances[ARRAY_SIZE]; // Loop counter variable
int count = 0; // Input file stream object
ifstream inputFile;
// Open the file.
inputFile.open("FinalNumbers.txt");
// Read the numbers from the file into the array
while (count < ARRAY_SIZE && inputFile >> accountNumbers[count] >> accountBalances[count] ) {
count++;
}
inputFile.close();
// Display the read data
cout << "The bank account numbers are: " << endl;
for (int count = 0; count < ARRAY_SIZE; count++) {
cout << accountNumbers[count] << "\n" << accountBalances[count] << " " << endl;
}
void dualSort(int accountNumbers[], double accountBalances, int ARRAY_SIZE);
}
I am required to use the selection sort or bubble sort algorithm.
I have Bank Account Numbers that have to be correspondingly and ascending sorted with there Account Balance, all the data is read from a file.
After sorting the data I have to rewrite it into another file, which is the least of my worries.
So the question is how do I go about sorting my accountNumbers in ascending order along with their accountBalance following them.
You need to sort according to accountNumbers but apply every swap operation to both arrays.
Here is the code using selection sort:
void dualSort(int accountNumbers[], double accountBalances[], int ARRAY_SIZE)
{
int minIndex;
for(int i = 0; i < ARRAY_SIZE - 1; i++)
{
minIndex = i;
for(int j = i + 1; j < ARRAY_SIZE; j++)
{
if(accountNumbers[j] < accountNumbers[minIndex])
{
minIndex = j;
}
}
swap(accountNumbers[i], accountNumbers[minIndex]);
swap(accountBalances[i], accountBalances[minIndex]);
}
}
You can declare a struct:
struct Account{
int accountNum;
int accountBalance;
bool operator<(const Account& a);
};
Then overload the comparison operator:
bool Account::operator<(const Account& a);
{
return (accountNum < a.accountNum);
}
Then put all your data in a struct vector using for loops:
std::vector<Account> accVec;
Finally sort vector using std::sort()
std::sort(accVec.begin(), accVec.end());
Now you have your data neatly stored in a vector in ascending order of account number.
Alternatively you can apply regular bubbleSort to sort the elements, as shown by "abcOfJavaAndCPP"
for(int j = 1; j < accVec.size(); ++j)
for(int i = 1; i < accVec.size() ; ++i)
if(accVec[i-1] < accVec[i])
std::swap(accVec[i], accVec[i+1]);
to do bubble sort algorithm you must do 2 for loops and a temporary variable
int tempAccNumber=0;
int tempAccBalance=0;
for(int j=0;j<ARRAY_SIZE-1;++j)
for(int i=0;i<ARRAY_SIZE-1;++i)
if(accountNumbers[i]>accountNumbers[i+1])
{
tempAccNumber=accountNumbers[i];
accountNumbers[i]=accountNumbers[i+1];
accountNumbers[i+1]=tempAccNumber;
tempAccBalance=accountBalances[i];
accountBalances[i]=accountBalances[i+1];
accountBalances[i+1]=tempAccBalance;
}
just implement this to your function that do the bubble sort
Code can be simplified quite a bit by using some more modern C++ techniques:
#include <vector>
struct Account {
double balance;
int number;
};
bool operator<(const Account& lhs, const Account& rhs) {
return lhs.number < rhs.number;
}
void dualSort(vector<Account>& v) {
for (std::size_t i = 0; i != v.size() - 1; ++i) {
for (std::size_t j = 0; j != v.size() - 1; ++j) {
if (v[j] < v[j+1]) std::swap(v[j], v[j+1]);
}
}
}
int main()
{
const int ARRAY_SIZE = 1000; // Array size
std::vector<Account> v(ARRAY_SIZE);
std::ifstream inputFile;
// Open the file.
inputFile.open("FinalNumbers.txt");
for (std::size_t i = 0; i != ARRAY_SIZE; ++i) {
inputFile >> v[i].number >> v[i].balance;
}
inputFile.close();
// Display the read data
cout << "The bank account numbers are: " << endl;
for (int count = 0; count < ARRAY_SIZE; count++) {
cout << v[count].number << "\n" << v[count].balance << " " << endl;
}
void dualSort(v);
}
Would encourage you to learn about classes, or even just structs to start, and also get familiar with std::vector as you should be using it a lot.

operator overloading [][] 2d array c++

I have a 2D array and I want to define a function that returns the value of the index that the user gives me using operator overloading.
In other words:
void MyMatrix::ReturnValue()
{
int row = 0, col = 0;
cout << "Return Value From the last Matrix" << endl;
cout << "----------------------------------" << endl;
cout << "Please Enter the index: [" << row << "][" << col << "] =" << ((*this).matrix)[row][col] << endl;
}
The operation ((*this).matrix)[row][col] should return an int.
I have no idea how to build the operator [][].
Alternatively, I could concatenate a couple of calls to the operator [], but I didn't succeed in it, because the first call to that operaror will return int* and the second one will return int, and it compel to build another operator, and I dont want to do that.
The data matrix is defined like
int** matrix; matrix = new int*[row];
if (matrix == NULL)
{
cout << "Allocation memory - Failed";
}
for (int i = 0; i < row; i++)//Allocation memory
{
matrix[i] = new int[col];
if (matrix[i] == NULL)
{
cout << "Allocation memory - Failed";
return;
}
}
What can I do?
Thank you,
Simply, such an operator does not exist, so you can not overload it.
A possible solution is to define two classes: the Matrix and the Row.
You can define the operator[] of a Matrix so that it returns a Row, then define the same operator for the Row so that it returns an actual value (int or whatever you want, your Matrix could be also a template).
This way, the statement myMatrix[row][col] will be legal and meaningful.
The same can be done in order to assign a new Row to a Matrix or to change a value in a Row.
* EDIT *
As suggested in the comments, also you should take in consideration to use operator() instead of operator[] for such a case.
This way, there wouldn't be anymore the need for a Row class too.
You can define your own operator [] for the class. A straightforward approach can look the following way
#include <iostream>
#include <iomanip>
struct A
{
enum { Rows = 3, Cols = 4 };
int matrix[Rows][Cols];
int ( & operator []( size_t i ) )[Cols]
{
return matrix[i];
}
};
int main()
{
A a;
for ( size_t i = 0; i < a.Rows; i++ )
{
for ( size_t j = 0; j < a.Cols; j++ ) a[i][j] = a.Cols * i + j;
}
for ( size_t i = 0; i < a.Rows; i++ )
{
for ( size_t j = 0; j < a.Cols; j++ ) std::cout << std::setw( 2 ) << a[i][j] << ' ';
std::cout << std::endl;
}
}
The program output is
0 1 2 3
4 5 6 7
8 9 10 11
I have no idea how to build the operator [][].
Sometimes it is fine to use a different operator, namely ():
int& Matrix::operator () (int x, int y)
{
return matrix[x][y];
}
const int& Matrix::operator () (int x, int y) const
{
return matrix[x][y];
}
int diagonal (const Matrix& m, int x)
{
return m (x, x); // Usage.
}
Advantage:
No need to use "intermediate" class like Row or Column.
Better control than with Row& Matrix operator (int); where someone could use the Row reference to drop in a row of, say, illegal length. If Matrix should represent a rectangular thing (image, matrix in Algebra) that's a potential source of error.
Might be less tedious in higher dimensions, because operator[] needs classes for all lower dimensions.
Disadvantage:
Uncommon, different syntax.
No more easy replacement of complete rows / columns, if that's desired. However, replacing columns is not easy, anyway, provided you used rows to model (and vice versa).
In either case, there are pros and cons if the number of dimensions are not known at runtime.
I was looking for self-tested array replacement...
Improved version returns reference or NULL reference and checks boundaries inside.
#include <iostream>
#include <iomanip>
template<typename T, int cols>
class Arr1
{
public:
Arr1(T (&place)[cols]) : me(place) {};
const size_t &Cols = cols;
T &operator [](size_t i)
{
if (i < cols && this != NULL) return me[i];
else {
printf("Out of bounds !\n");
T *crash = NULL;
return *crash;
}
}
private:
T (&me)[cols];
};
template<typename T, int rows, int cols>
class Arr2
{
public:
const size_t &Rows = rows;
const size_t &Cols = cols;
Arr2() {
ret = NULL;
for (size_t i = 0; i < rows; i++) // demo - fill member array
{
for (size_t j = 0; j < cols; j++) matrix[i][j] = cols * i + j;
}
}
~Arr2() {
if (ret) delete ret;
}
Arr1<T, cols>(&operator [](size_t i))
{
if (ret != NULL) delete ret;
if (i < rows) {
ret = new Arr1<T, cols>(matrix[i]);
return *ret;
}
else {
ret = NULL;
printf("Out of bounds !\n");
return *ret;
}
}
//T(&MemberCheck)[rows][cols] = matrix;
private:
T matrix[rows][cols];
Arr1<T, cols> *ret;
};
template<typename T,int rows, int cols>
class Arr
{
public:
const size_t &Rows = rows;
const size_t &Cols = cols;
T(&operator [](size_t i))[cols]
{
if (i < rows) return matrix[i];
else {
printf("Out of bounds !\n");
T(*crash)[cols] = NULL;
return *crash;
}
}
T (&MemberCheck)[rows][cols] = matrix;
private:
T matrix[rows][cols];
};
void main2()
{
std::cout << "Single object version:" << endl;
Arr<int, 3, 4> a;
for (size_t i = 0; i <= a.Rows; i++)
{
int *x = &a[i][0];
if (!x) printf("Fill loop - %i out of bounds...\n", i);
else for (size_t j = 0; j < a.Cols; j++) a[i][j] = a.Cols * i + j;
}
for (size_t i = 0; i < a.Rows; i++)
{
for (size_t j = 0; j <= a.Cols; j++) {
std::cout << std::setw(2) << a[i][j] << ' ';
if (a.MemberCheck[i][j] != a[i][j])
printf("Internal error !");
}
std::cout << std::endl;
}
std::cout << endl << "Double object version:" << endl;
Arr2<int, 3, 4> a2;
for (size_t i = 0; i < a2.Rows; i++)
{
for (size_t j = 0; j <= a2.Cols; j++) {
int &x = a2[i][j];
if (&x)
{
x++;
std::cout << std::setw(2) << a2[i][j] << ' ';
//if (&a2.MemberCheck[i][j] != &a2[i][j])
// printf("Internal error !");
}
}
}
}
Output
Single object version:
Out of bounds !
Fill loop - 3 out of bounds...
0 1 2 3 4
4 5 6 7 8
8 9 10 11 -858993460
Double object version:
1 2 3 4 Out of bounds !
5 6 7 8 Out of bounds !
9 10 11 12 Out of bounds !
it works fine in the program below
#include<iostream>
using namespace std;
class A{
public:
int r,c;
int** val;
A()
{
r=0;c=0;val=NULL;
}
A(int row,int col)
{
r=row;c=col;
int count=0;
val=new int*[row];
for(int i=0;i<r;i++){
val[i]=new int[col];
for(int j=0;j<c;j++){
count++;
val[i][j]=count;
}
}
}
int* &operator[](int index){
return val[index];
}
};
int main(void){
A a(3,3);
cout<<a[1][2];
return 0;
}
here, a[1][2] first computes a[1]-->which returns 2nd row as (int*) type
then it's read as (int*)[2] which returns 3rd element of that row.In short,
a[1][2]------>(a[1])[2]------>(val[1])[2]------>val[1][2].