C++ using a **pointer in a function argument not working - c++

I have a function that expects a pointer array as such:
void SortResistance(MyClass ** pointerArray, int arraySize);
and does a bubble sort. Inside that function I can access any two array elements using:
MyClass * item1 = *pointerArray + i;
MyClass * item2 = *pointerArray + i + 1;
Where I'm iterating over the array. So far so good. When I swap the values using a very simple swap function such as:
void Swap(MyClass ** item1, MyClass ** item2);
The values on the pointers swap as expected.
My problem is that I don't know how to reassign them back to pointerArray.
This doesn't work:
*(pointerArray + i) = item1;
*(pointerArray + i + 1) = item2;
(Well, it works when i equals 0 but otherwise it just shifts the pointee, not its value.)
I'm wondering if anyone would please help me with this problem. The function prototypes cannot be changed so I'm assuming they are correct.
Here is the gory detail in the simplest possible implementation. Thank you very much for your responses.
I was asked to look at something similar to the following declarations and to implement:
#include <string>
using namespace std;
void main()
{
//TODO: instantiate an array of pointers and sort them using the below
};
class MyClass
{
public:
double value;
string name;
}
void Sort(MyClass ** myArray, int arraySize)
{
//TODO: implement bubble sort
}
void Swap(MyClass ** pointer1, MyClass ** pointer2)
{
MyClass *temp = *pointer1;
*pointer1 = *pointer2;
*pointer2 = temp;
}
My solution, based on something like the following http://www.cplusplus.com/reference/algorithm/sort/ would be something like this:
#include <string>
using namespace std;
class MyClass
{
public:
double value;
string name;
};
void Swap(MyClass ** pointer1, MyClass ** pointer2)
{
MyClass *temp = *pointer1;
*pointer1 = *pointer2;
*pointer2 = temp;
}
void Sort(MyClass ** myArray, int arraySize)
{
bool done = false; // this flag will be used to check whether we have to continue the algorithm
while (!done)
{
done = true; // assume that the array is currently sorted
for (int i = 0; i < arraySize - 1; i++) // for every element in the array
{
MyClass * p1 = *myArray + i;
MyClass * p2 = *myArray + i + 1;
//MyClass * p1 = *(myArray + i);
//MyClass * p2 = *(myArray + i + 1);
//MyClass * p1 = myArray[i];
//MyClass * p2 = myArray[i + 1];
if ( p1->value > p2->value ) // compare the current element with the following one
{
// They are in the wrong order, swap them
Swap(&p1, &p2);
//Swap(*(&myArray + i), *(&myArray + i + 1));
//Swap(myArray + i, myArray + i + 1);
*(myArray + i) = p1;
*(myArray + i + 1) = p2;
done = false; // since we performed a swap, the array needs to be checked to see if it is sorted
// this is done in the next iteration of the while
}
}
}
}
void main()
{
MyClass item1; item1.name = "item1"; item1.value = 25.5;
MyClass item2; item2.name = "item2"; item2.value = 15.5;
MyClass myItems[2]; myItems[0] = item1; myItems[1] = item2;
MyClass * myPointerToItemArray = myItems;
Sort(&myPointerToItemArray, 2);
}
The code compiles fine under VS 2010. As you can see, everything goes well until I have to reassign the new set of pointers to the array. Any advice would be greatly appreciated. I'm starting to think the declarations have to be modified to make this work.

It's a lot easier if you treat it as an actual array rather than a pointer, e.g.
MyClass* item1 = pointerArray[i];
MyClass* item2 = pointerArray[i + 1];
and:
pointerArray[i] = item1;
pointerArray[i + 1] = item2;
You don't need to modify the function prototypes to do this.

Alright, I've done a little debugging in my own compiler... try
MyClass * item1 = *(pointerArray + i);
MyClass * item2 = *(pointerArray + i + 1);
And leave the rest of the code the same.

try catching the array values in a reference:
MyClass &* item1 = *pointerArray + i;
MyClass &* item2 = *pointerArray + i + 1;
then you shouldn't need to re-assign the values after the fact.
EDIT:
What you were doing is essentially making a copy to the pointers in item1, item2. Swapping them swapped the copies, but not the original. You could try omitting the copies and just doing something like this:
Swap(&(*pointerArray + i), &(*pointerArray + i + 1));

After quite a while I was able to make it work. The code for the example problem above is given here. Thank you all for your suggestions.
#include <string>
using namespace std;
class MyClass
{
public:
double value;
string name;
};
void Swap(MyClass ** pointer1, MyClass ** pointer2)
{
MyClass *temp = *pointer1;
*pointer1 = *pointer2;
*pointer2 = temp;
}
void Sort(MyClass ** myArray, int arraySize)
{
//sorting
bool done = false;
while (!done)
{
done = true; // assume that the array is currently sorted
for (int i = 0; i < arraySize - 1; i++) // for every element in the array
{
if (myArray[i]->value > myArray[i + 1]->value)
{
Swap(&myArray[i], &myArray[i + 1]);
//MyClass temp = *myArray[i];
//*myArray[i] = *myArray[i + 1];
//*myArray[i + 1] = temp;
done = false;
}
}
}
};
void main()
{
MyClass item1; item1.name = "item1"; item1.value = 25.5;
MyClass item2; item2.name = "item2"; item2.value = 15.5;
MyClass item3; item3.name = "item3"; item3.value = 10.5;
MyClass * myItems[3]; myItems[0] = &item1; myItems[1] = &item2; myItems[2] = &item3;
MyClass ** dp = myItems;
Sort(dp, 3);
}

Related

what is this dynamic object creation * []

What does this mean? The following is a snippet from
here
class HashTableEntry {
public:
int k;
int v;
HashTableEntry(int k, int v) {
this->k= k;
this->v = v;
}
};
class HashMapTable {
private:
HashTableEntry **t;
public:
HashMapTable() {
t = new HashTableEntry * [T_S]; //What does this do
for (int i = 0; i< T_S; i++) {
t[i] = NULL;
}
}
In this code, t is a double pointer and it is assigned to new HashTableEntry * [T_S]
Does new HashTableEntry * [T_S] mean the Object HashTableEntry is being made into a pointer to point to an array with size of T_S?
If it is, I am not understanding how a dynamically created object with the new HashTableEntry is being delcared as an [T_S] when the definition of HashTableEntry is clearly a class/struct
t = new HashTableEntry * [T_S]
This creates an array of pointers to HashTableEntry. It creates T_S counts of them.
Perhaps it is clearer if written like this:
using HTEntry = HashTableEntry*;
t = new HTEntry [T_S];

Initialize and declare dynamically multiple variables of random entities in a loop in C++

This is my code:
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <vector>
#define ENTITY(A) entity##A
#define ALM(A) alm##A
struct TEntity{
private:
int sumx;
int sumy;
const char * rep;
int m_ix;
int m_iy;
public:
TEntity(int x, int y, int sum_x, int sum_y, const char * txt);
};
TEntity::TEntity(int x, int y, int sum_x, int sum_y, const char * txt) {
m_ix = x;
m_iy = y;
sumx = sum_x;
sumy = sum_y;
rep = txt;
}
class IAlmacenable {
private:
void * element;
public:
IAlmacenable(void * e);
IAlmacenable();
void * getValue();
};
IAlmacenable::IAlmacenable(void *e) {
element = e;
}
IAlmacenable::IAlmacenable() {
element = nullptr;
}
void * IAlmacenable::getValue() {
return element;
}
class TList {
private:
std::vector<IAlmacenable*> elementos;
int position;
public:
TList();
int Size();
int Push(IAlmacenable* psz);
};
TList::TList() {
elementos = std::vector<IAlmacenable*>();
position = 0;
}
int TList::Size() {
return elementos.size();
}
int TList::Push(IAlmacenable* psz) {
int res = 0;
if (elementos.size() >= elementos.max_size()) {
res = -1;
}
else {
elementos.push_back(psz);
}
return res;
}
int main(){
srand(time(NULL));
TList *list = new TList();
//we can put entities in the list and the rest will be filled up to 5
int size = list->Size();
for(int i = size; i<5;i++){
const char c[] = {(rand() % 2 ? 65 + rand() % 25 : 97 + rand() % 25), '\0'};
TEntity ENTITY(i)(rand() % 10, rand() % 10, rand() % 5, rand() % 5, c);
IAlmacenable ALM(i)(&ENTITY(i));
list->Push(&ALM(i));
size++;
}
//do things like printing their value...
delete list;
return 0;
}
I need to create a new variable everytime it run the "TEntity ENTITY(i)" line,
the problem is that it creates the same variable always, I think it is because it creates the variable entityi and therefore it is overwriting on the same variable, besides it seems that the random it generates is always the same number since all entities have the same values ​​in all its parameters. The c variable create a const char * random variable between a-z, A-Z , I don't put the print code because it is unnecessary, so what can I do? Is there any way to dynamically create variables of entities whose values ​​are random?
EDIT
Here is the new code fixed (the macros have been eliminated since they were not necessary and the necessary code has been included to be able to execute it) but there is still the same problem that they are generated with the same parameters (since they are still the same variable):
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <vector>
#include <conio.h>
#include <windows.h>
struct TEntity{
private:
int sumx;
int sumy;
const char * rep;
int m_ix;
int m_iy;
public:
TEntity(int x, int y, int sum_x, int sum_y, const char * txt);
void movimiento();
void pinta();
};
TEntity::TEntity(int x, int y, int sum_x, int sum_y, const char * txt) {
m_ix = x;
m_iy = y;
sumx = sum_x;
sumy = sum_y;
rep = txt;
}
void TEntity::movimiento() {
m_ix += sumx;
m_iy += sumy;
}
void TEntity::pinta() {
gotoxy(static_cast<short int>(m_ix), static_cast<short int>(m_iy));
printf("%s", rep);
}
void gotoxy(short int x, short int y)
{
COORD pos = {x, y};
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos);
}
void clear()
{
system("cls");
}
class IAlmacenable {
private:
void * element;
public:
IAlmacenable(void * e);
IAlmacenable();
void * getValue();
};
IAlmacenable::IAlmacenable(void *e) {
element = e;
}
IAlmacenable::IAlmacenable() {
element = nullptr;
}
void * IAlmacenable::getValue() {
return element;
}
class TList {
private:
std::vector<IAlmacenable*> elementos;
int position;
public:
TList();
int Size();
int Push(IAlmacenable* psz);
IAlmacenable* First();
IAlmacenable* Next();
};
TList::TList() {
elementos = std::vector<IAlmacenable*>();
position = 0;
}
int TList::Size() {
return elementos.size();
}
int TList::Push(IAlmacenable* psz) {
int res = 0;
if (elementos.size() >= elementos.max_size()) {
res = -1;
}
else {
elementos.push_back(psz);
}
return res;
}
IAlmacenable* TList::First() {
IAlmacenable* res;
if (elementos.empty()) {
res = nullptr;
}
else {
res = elementos.front();
position = 1;
}
return res;
}
IAlmacenable* TList::Next() {
IAlmacenable* res;
if (elementos.empty()) {
res = nullptr;
}
else {
int pos = position;
int size = elementos.size();
if (pos < size) {
res = elementos.at(position);
position++;
}
else {
res = this->First();
}
}
return res;
}
int main(){
srand(time(NULL));
TList *list = new TList();
//we can put entities in the list and the rest will be filled up to 5
int size = list->Size();
for(int i = size; i<5;i++){
const char c[] = {(rand() % 2 ? 65 + rand() % 25 : 97 + rand() % 25), '\0'};
TEntity *entity = new TEntity(rand() % 10, rand() % 10, rand() % 5, rand() % 5, c);
IAlmacenable *alm = new IAlmacenable(entity);
list->Push(alm);
size++;
}
while(true){
clear();
for (int i = 0; i < size; i++) {
reinterpret_cast<TEntity *>(list->Next()->getValue())->pinta();
reinterpret_cast<TEntity *>(list->Next()->getValue())->movimiento();
}
Sleep(2000);
}
delete list;
return 0;
}
There is some confusion here.
Some points:
The macro is not fit-for-purpose, as you already know; you're just creating a variable name entityi each time;
That doesn't matter! The object only exists for the duration of the loop iteration anyway; C++ doesn't let you create multiple objects with the same name at the same time. In fact you can get rid of the entire macro stuff and just call the object entity;
Now that that's out of the way, you're getting repeated results because you're storing a pointer to each iteration of that local variable — on each occasion, that's a dangling pointer to an object that's been destroyed. Don't store dangling pointers!
You can either:
Dynamically allocate the objects that you're adding to the list, or
Store actual objects rather than pointers-to-objects.
Either way, the local-scope name is irrelevant and certainly need not change repeatedly for each loop iteration.

How can you preserve the value of a pointer in c ++ without overwriting it

I Have this sandbox code for a proyect more complicated :
#include <sstream>
#include <iostream>
#include <vector>
using namespace std;
class Table
{
friend class Variable;
public:
Variable * variables[1021];
};
class Variable
{
friend class Nodo;
public:
char clas;
Nodo * ini;
};
class Nodo
{
public:
char clas;
Variable * father;
private:
float * value;
public:
Nodo();
void set_value(float);
float * get_value();
};
Nodo::Nodo()
{
clas = ' ';
father = NULL;
value = NULL;
}
void Nodo::set_value(float m)
{
float * r = new float();
r = &m;
value = (float *)r;
}
float * Nodo::get_value()
{
return this->value;
}
And this is the main:
void main ()
{
Nodo * n = new Nodo(); // OK.
n->set_value(5.3442); // Ok.
Variable * v = new Variable(); // This is the problem.
// When I declare another pointer an initilized it, n lost the value stored in value.
Variable * v0 = new Variable(); // Here the same.
v->ini = n;
n->father = v;
Table * t = new Table();
t->variables[0] = v;
v0 = t->variables[0];
cout << *(static_cast<float *>(v0->ini->get_value())) << endl;
}
How can I stock the value in the pointer without change? It seems that I should use const, or something similar, but I don't know how. Declaring the field value as private doesn't help. The idea is replace value with a void * later, to store any king of basic date not only float data.
Thanks!
This looks wrong:
void Nodo::set_value(float m)
{
float * r = new float();
r = &m;
value = (float *)r;
}
r is assigned pointer to m which is a temporary, this pointer will be invalid once set_value finishes. Also you overwrite r value, so you have a leak here. The correct version would be:
void Nodo::set_value(float m)
{
float * r = new float();
*r = m;
value = r;
}
btw. I am not digging deeper in your code, ...

copying an array of int*

I have to create a copy constructor for my object, which look like this;
class DTable {
private:
std::string s_name;
int* *array;
int size;
public:
DTable();
DTable(std::string sName);
DTable(DTable &pcOther);
~DTable();
void vSetName(std::string sName);
std::string info();
int getValue(int index, bool &ok);
bool setValue(int index, int val);
const int defaultArrSize = 10;
const std::string defaultArrName = "Default Name";
};
Where array variable points at array of int*. Copy constructor i came up with looks like this;
DTable::DTable(DTable & pcOther) {
s_name = pcOther.s_name + "_copy";
size = pcOther.size;
array = new int*[size];
for (int i = 0; i < size; i++) {
array[i] = new int;
*array[i] = pcOther.*array[i];
}
}
The problem is that, i just cannot copy values of pointed int array to another array. Solution like this leaves me with error
expression must have pointer to member type
Also,
array[i] = pcOther.array[i];
is wrong, because that just copies references, so after altering one object, copy of it will be altered too. I want to avoid that.
I'd love to use different structure for this, but it has to be dynamically allocated array of int*
You can use the memcpy(),
void * memcpy ( void * destination, const void * source, size_t num );
or
*array[i] = *(pcOther.array[i])
for e.g.
DTable::DTable(DTable & pcOther) {
s_name = pcOther.s_name + "_copy";
size = pcOther.size;
array = new int*[size];
for (int i = 0; i < size; i++) {
array[i] = new int;
*array[i] = *(pcOther.array[i]);
// or
memcpy ( array[i], pcOther.array[i] , sizeof(int)*1 );
}
}

I can't display variables of different types included in array

I have to do a program for college.
I have 3 classes already declared in the statement of the problem.
First class:
class piesa_a{
protected:
int id;
char *tip;
int pret;
};
Second class:
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
};
Third class:
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
};
In main I need to create an array in which to store items such piesa_a, piesa_b, piesa_c. Then I have to sort items by price.
I have this code so far: http://pastebin.com/nx2FGSfe
The program is incomplete because it does not displays each item in the array.
I got stuck here. But if you display the array's elements when they are outside of it, it works.
SHORT: I have an error on line 143 and I want to solve it.
main.cpp:143:18: error: request for member ‘afisare’ in ‘*(v + ((unsigned int)(((unsigned int)i) * 4u)))’, which is of non-class type ‘piesa_a*’
The code is here:
#include <cstdlib>
#include<iostream>
#include<string.h>
using namespace std;
class piesa_a{
protected:
int id;
char *tip;
int pret;
public:
piesa_a()
{
id = 0;
tip = new char[1];
pret = 0;
}
piesa_a(int aidi, char *typ, int pretz)
{
id = aidi;
tip = new char[strlen(typ)+1];
strcpy(tip,typ);
pret = pretz;
}
piesa_a&operator =(piesa_a alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
return *this;
}
virtual void afisare()
{
cout<<"\n Piesa A: "<<id<<" "<<tip<<" "<<pret;
}
};
class piesa_b:public piesa_a
{
private:
float lungime;
bool bw;
public:
piesa_b():piesa_a(){lungime = 0;bw = 0;}
piesa_b(float lg,bool bl, int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
lungime = lg;
bw = bl;
}
piesa_b&operator =(piesa_b &c)
{
id = c.id;
tip = new char[strlen(c.tip)+1];
strcpy(tip,c.tip);
pret = c.pret;
lungime = c.lungime;
bw = c.bw;
return *this;
}
void afisare()
{
piesa_a::afisare();
cout<<"impreuna cu piesa B: "<<lungime<<" "<<bw<<"\n";
}
};
class piesa_c:public piesa_a
{
private:
int nr;
piesa_b *buf;
public:
piesa_c():piesa_a(){nr=0; buf = new piesa_b[nr];}
piesa_c(int n, piesa_b *bu,int aid, char *tipi, int pretzz):piesa_a(aid,tipi,pretzz)
{
nr = n;
buf = new piesa_b[nr];
for(int i=0;i<nr;i++)
buf[i]= bu[i];
}
piesa_c&operator =(piesa_c &alta)
{
id = alta.id;
tip = new char[strlen(alta.tip)+1];
strcpy(tip,alta.tip);
pret = alta.pret;
nr = alta.nr;
for(int i=0;i<alta.nr;i++)
buf[i] = alta.buf[i];
}
void afisare()
{
for(int i=0;i<nr;i++)
buf[i].afisare();
}
};
int main(int argc, char** argv) {
piesa_b *H;
H = new piesa_b[2];
piesa_a A(4,"TIPA",120);
piesa_b B(100,1,3,"TIPA",120);
H[0]=B;
H[1]=B;
piesa_c C(2, H,14,"TIPC",20);
piesa_a** v = new piesa_a*[3];
v[0] = &A;
v[1] = &B;
v[2] = &C;
for(int i=0;i<3;i++)
v[i].afisare();
return 0;
}
What's wrong?
In C++ (and current C), casts are almost always a sign that the programmer didn't know how to use the language as it is supposed to be used. If you need an array of 3 types of data, the cleanest solution is an array of objects of a class that is base to the 3. And if you want to display each item differently, you'll want to overload the << operator, so you just iterate over the array and go << on each item. Sorted by price means that the class includes a price field, and you use the sort from the standard template library, passing a comparison operation that just compares prices.