pushing an array to a function in c++? - c++

{
int a[3];
mainClassStack.pushNumber(a[1,2,3]);
break;
}
void stack_class::pushNumber(int numberFunc)
{
if(head==NULL)
{
head = new stack_struct;
head->number = numberFunc;
head->next_number = NULL;
tailPointer=head;
}
else
{
pointerFunc = new stack_struct;
pointerFunc->number=numberFunc;
pointerFunc->next_number=NULL;
head->next_number=pointerFunc;
head=pointerFunc;
}
}
void stack_class::pushNumber(char charFunc)
{
int a=0;
a=charFunc;
if(head==NULL)
{
head = new stack_struct;
head->number = a;
head->next_number = NULL;
tailPointer=head;
}
else
{
pointerFunc = new stack_struct;
pointerFunc->number=a;
pointerFunc->next_number=NULL;
head->next_number=pointerFunc;
head=pointerFunc;
}
}
void stack_class::pushNumber(int arrayFunc[3])
{
if(head==NULL)
{
for(int i=0;i<3;i++)
{
head = new stack_struct;
head->number = arrayFunc[i];
head->next_number = NULL;
tailPointer=head;
}
}
else
{
for(int i=0;i<3;i++)
{
pointerFunc = new stack_struct;
pointerFunc->number=arrayFunc[i];
pointerFunc->next_number=NULL;
head->next_number=pointerFunc;
head=pointerFunc;
}
}
}
I am overloading functions and pushing an array into the appropriate function which will later add the values from the arrays to a dynamic linked list. So far I have written this, but when I try to print the linked list, it shows garbage. What am I doing wrong here?

Does this make more sense to you?
void Foo(int arg[])
{
printf("%i\n", arg[0]);
printf("%i\n", arg[1]);
printf("%i\n", arg[2]);
}
int main()
{
int a[3] = {1,2,3};
Foo(a);
return 0;
}
Output is:
1
2
3

To make more clear what others are pointing out, the comma operator returns the last value in the series. The value of the expression (1, 2, 3) is therefore 3, and so the expression a[1, 2, 3] is nothing more than a long way of saying a[3].
But there's something else that looks goofy right away, which is this loop here:
if(head==NULL)
{
for(int i=0;i<3;i++)
{
head = new stack_struct;
head->number = arrayFunc[i];
head->next_number = NULL;
tailPointer=head;
}
}
You point head to a new thing, set a couple things inside it, and then set tailPointer to point to that same new thing...but then immediately do the same two more times. Do you see the problem? At the end of the loop, you've created three items whose next_number values are all NULL, and head and tailPointer both point to the same thing: the last one created. You have nothing at all pointing to the first two items you created, and none of them point to each other. In other words, there is no linked list at all at the end of this operation (although there are a few new objects lying out there in memory somewhere with no way to access or de-allocate them).
You probably mean to have your if statement inside your loop, rather than the other way around, but you need to change more than just that, because the code in the other for loop might be a little problematic as well. It creates a new item, then sets up a link from the head item to the new one, but then it moves the head to point to the new one, so you are successfully adding an item to the tail of the list, but leaving yourself with a head variable that is actually pointing at the tail.
I suggest the best way to see what's going on is to take a pencil and paper, write down your variables and draw boxes to represent your objects, with their member variables inside, then step-by-step follow your code, writing in variable values or erasing and drawing arrows from the pointers to show where each one lands. I think you'll immediately see where your algorithm is going awry.

C++ does not allow to pass an entire array as an argument to a function. However, You can pass a pointer to an array by specifying the array's name without an index.
If you want to pass a single-dimension array as an argument in a function, you would have to declare function formal parameter in one of following three ways and all three declaration methods produce similar results because each tells the compiler that an integer pointer is going to be received.
Way-1
Formal parameters as a pointer as follows:
void myFunction(int *param)
{
.
.
.
}
Way-2
Formal parameters as a sized array as follows:
void myFunction(int param[10])
{
.
.
.
}
Way-3
Formal parameters as an unsized array as follows:
void myFunction(int param[])
{
.
.
.
}

Related

Assign address to pointer inside struct

I am trying to implement a path-finding algorithm.
So i have a 2d array with structs in it, and would like to follow the
track of the best opinion from one location to another. Therefore i try to work with structs (easy data handling) and pointer to other structs.
This is how it works in principle.
struct location{
int x;
int y;
location* parent;
};
int main(){
map_inf current;
vector<map_inf> allData;
someData = getData(); // returns vector of structs
current = someData[0];
while(current.x != 15 && current.y != 30){
for(int i = 1; i < someData.size(); i++){
someData[i].parent = &current;
allData.push_back(someData[i]);
}
someData = getData(); // get new data
current = someData[0];
}
for(int i=0; i<allData.size(); i++){
///////////////////////////////////////
// ALL PARENT POINTERS ARE EQUAL. WHY ?
///////////////////////////////////////
}
}
When i view my code with the debugger i can see that the "current"-element is correct and the pointers will be set properly. But when "someData" get fully processed and there is new data all previous parent pointers in allData also get updated.
You should increament/update the current pointer after the end of the for loop or in the for loop. You just used current = someData[0]; at the end of the for loop which means the current will contain the same pointer pointed by someData[0].

Why is the 2nd level of the pointers in a hash table not need malloc() to allocate memory?

I am currently learning separate chaining to resolve collisions in hashing. Below shows an example that creates a hash table. I see hash_tbl *new_table = malloc(sizeof(hash_tbl)); allocates a big chunk of memory for new_table. Next, new_table->list = malloc(sizeof(node *) * size); seems to divide new_table by size to store the 1st level of pointer of node **list.
Q1: The part I can't figure out is that why I do NOT need to malloc() the 2nd level of the pointer at node **list; marked by ###?
Q2: Since the code is correct, does for (int i=0; i<size; i++){
new_table->list[i] = NULL; } initialize the head pointer of the linked list pointed to by new_tbl->list[i]?
p.s. Could someone can illustrate his explanation graphically?
typedef struct Node {
char *str;
struct Node *next;
} node;
typedef struct Hash_Tbl {
int size;
node **list; //###
} hash_tbl;
int main() {
int size = 6;
create_hash_table(size);
}
hash_tbl *create_hash_table(int size) {
if (size < 1) return NULL;
hash_tbl *new_table = malloc(sizeof(hash_tbl));
if (new_table == NULL) return NULL;
new_table->list = malloc(sizeof(node *) * size);
if (new_table->list == NULL) return NULL;
// Initialize the elements of the hash table
for (int i=0; i<size; i++){
new_table->list[i] = NULL;
}
new_table->size = size;
return new_table;
}
I can't figure out is that why do I NOT need to malloc() the 2nd level of the pointer at node **list;
Since the hash table starts off empty, you do not need to allocate the 2nd level yet. The code of create_hash_table sets all buckets to NULL to indicate that they are empty.
does [for loop] initialize the head pointer of the linked list pointed to be new_tbl->list[i]?
There isn't one "head pointer" in a hash table. Each element of the list[] array is a head pointer of its own. All these pointers are initialized to NULL, indicating that their corresponding bucket is empty.
Initially, all bucket lists are empty. When you start adding items to the hash table, the lists start filling in.
The diagram below shows a hash table with six buckets. Buckets 1 and 3 have some items; the remaining buckets are empty. Bucket 1 has no collisions, while bucket 3 has a two-way collision.
The part I can't figure out is that why do I NOT need to malloc() the 2nd level of the pointer at node **list; marked by ###?
The 2nd level of pointer will be allocated whenever required. This is just the initialization part and that is why we simply initialize it to NULL here.
Since the code is correct, does for (int i=0; ilist[i] = NULL; } initialize the head pointer of the linked list pointed to be new_tbl->list[i]?
Consider new_table->list as an array of pointers. With each element representing a chain of nodes. So, in a sense you are correct. Each element of this array could be a head to the respective chains/buckets you are going to form later on.

A class array inside of a class - issues with dynamic arrays (c++)

My homework is that I have to make a class (register) which contains 3 class arrays (birds, mammals, reptiles) which are in the animal class. Animal is the friend of Register. I will only show the birds part, to keep it simple.
The register class looks like:
class Register
{
Bird* birds;
unsigned int birdSize;
public:
...
}
The constructor of register:
Register::Register()
{
this->birds = new Bird[0];
this->birdSize = NULL;
}
Now I have a function in register that adds one element to the birds array, the input is cin.
void Register::add()
{
...
if (birdSize == 0)
{
birds = new Bird[0];
Bird* temp = new Bird[0];
temp[0].add();
this->birds = temp;
birdSize++;
}
else
{
Bird* temp = new Bird[birdSize+1];
for (unsigned int i=0; i<=birdSize; i++)
{
temp[i] = this->birds[i];
}
temp[birdSize+1].add();
birds = new Bird[birdSize+1];
birds = temp;
birdSize++;
}
temp[0].add() has the cin, it works properly. When I run the program, the user has to add 2 birds to the array. The problem occurs when reaching the part under 'else', so the second element of the array. The program surely reaches "temp[birdSize+1].add();" while running, then the "xyz.exe has stopped working" window pops up and it says in the details " Fault Module Name: StackHash_7e8e" so I'm sure something is wrong with the memory allocation, but the problem is that when I try to find the problematic line in debug mode, everything works fine.
Well, not everything. The program has a print() function, it prints out everything in Register. The second element of the array is the same as the first.
I have no clue what to do. I read many forum posts, read a cpp book, watched online tutorials, but I can't find the solution for this problem. Please help.
Array index starts from 0. So in else part you are writing
Bird* temp = new Bird[birdSize+1]; // size =birdSize +1;
So valid index range will be 0 -> birdSize, not birdSize+1.
The problem is
temp[birdSize+1].add();
you are using birdSize+1th index. It should be
temp[birdSize].add();
There are other bugs in your code:
for (unsigned int i=0; i<=birdSize; i++) // should be i<birdSize
{
temp[i] = this->birds[i];
}
There are other bad coding in your program:
Register::Register()
{
this->birds = new Bird[0]; // should be this->birds=NULL
this->birdSize = NULL; // should be this->birdSize = 0
}
And obviously if your homework does not demand it, you should not use arrays in this way. For variable size container, use vector, list.... Array is only when the size is fixed.

Why is my class' destructor being called when leaving the scope of a private function belonging to the class?

I've been refreshing myself with C++ and am trying to create a linked list class with 2 strings that has a function which will sort items in the list alphabetically. I send them to a swap function by passing pointers to the two items in the list being compared and then they trade pointer information so that the list is "reorganized", as shown here:
void LinkedList::swapItem(LinkedList* a, LinkedList* b)
{
LinkedList temp = *a;
a->pNext = b->pNext;
// if statement to prevent b->pNext from pointing back to b if items are 'adjecent' to eachother in the list
if(b == temp.pNext)
{
b->pNext = a;
}
else
{
b->pNext = temp.pNext;
}
a->idNum = b->idNum;
b->idNum = temp.idNum;
}
This function is called by another function which is supposed to check the values of the "last name" string and determine if they need to be swapped. Then it switches the iterators(which are the pointers that were passed in to the swap function), and is supposed to continue through the list, but after the swap function, the iterators/pointers point to the same place but the data in the objects is just gone because the destructor is called at the end of the swap function! why would it call the destructor when the objects are still being used? Is there a way to tell the destructor to stop? Here is the code for sorting alphabetically:
LinkedList* LinkedList::sortAlpha()
{
LinkedList *top = this;
LinkedList *pItrA = this;
LinkedList *pItrB = this->pNext;
LinkedList *temp = NULL;
while(pItrA != NULL)
{
while(pItrB != NULL)
{
if(pItrA->alphaOrder > pItrB->alphaOrder)
{
swapItem(pItrA, pItrB);
temp = pItrA;
pItrA = pItrB;
pItrB = temp;
temp = NULL;
if(pItrB->idNum == 0)
{
// Tracks the pointer at the "top" of the list if pItrB is the new top item
top = pItrB;
}
}
pItrB = pItrB->pNext;
}
pItrA = pItrA->pNext;
}
return top;
}
I know this code is probably VERY messy, or at best inefficient, but I'm not too concerned about that because I'm just trying to understand how it all works and why.
This creates a local temporary LinkedList, initialized by copying a into it:
LinkedList temp = *a;
When that temporary goes out of scope, its destructor gets called. That is what is supposed to happen, and you can't stop it without eliminating the temporary.
You should rewrite your swap function so that it doesn't require making a copy of a in this way. It doesn't seem like you can make your current swap function correct unless you do so.
One of two things are likely happening when you create this temporary:
The copy constructor does a shallow copy, bringing over pointers from the source.
The copy constructor does a deep copy on plain pointers, and replicates the structure.
You use reference-counted pointers and do something much fancier.
The shallow copy lets you test pointers directly, as you do in your swap function. A deep copy would give you unrelated pointers between the two copies. And #3 seems unlikely at the moment.
Then, when you destroy the temporary, a couple different things might be happening:
You don't delete anything, leading to potential memory leaks.
You delete the entire chain starting at the temporary, obliterating a good portion of your linked list (assuming a shallow copy).
I'm guessing since you came here, the situation looks closer to #2.
Including my further thoughts from below: Your swap logic looks flawed. To swap items in a singly linked list, you need to manipulate the next pointers of the predecessors to the swapped nodes, and you do not have those available to you in your swap function.
In this case, you're better off just swapping the other members of the class, as opposed to manipulating pointers. If your class had a large amount of data in it, then you might be better off with pointer manipulation, but you need to know the predecessors of the two nodes you're swapping (or at least a pointer/reference to the pNext in the predecessors) to do it correctly.
The variable temp is being destroyed, and presumably destroying the other LinkedList objects that it points to. Instead, rewrite as:
void LinkedList::swapItem(LinkedList* a, LinkedList* b)
{
LinkedList* tmpNext = a->pNext;
auto tmpId = a->idNum; // I use auto because I don't know what type idNum is (int ?)
a->pNext = b->pNext;
// if statement to prevent b->pNext from pointing back to b if items are 'adjecent' to eachother in the list
if(b == tmpNext)
{
b->pNext = a;
}
else
{
b->pNext = tmpNext;
}
a->idNum = b->idNum;
b->idNum = tmpId;
}
Joe Z was correct with
You delete the entire chain starting at the temporary, obliterating a good portion of your linked list (assuming a shallow copy)
So I rewrote the alphaSort function to handle everything:
LinkedList* LinkedList::sortAlpha()
{
bool sorted = false;
LinkedList* top = this;
LinkedList* prev = NULL;
LinkedList* itr = NULL;
while(sorted == false)
{
prev = NULL;
itr = top;
sorted = true;
while(itr != NULL)
{
if(itr->pNext != NULL && itr->alphaOrder > itr->pNext->alphaOrder)
{
LinkedList *temp = itr;
LinkedList *tempNext = itr->pNext->pNext;
if(itr->idNum == 0)
{
itr->idNum = itr->pNext->idNum;
itr->pNext->idNum = 0;
top = itr->pNext;
}
itr = itr->pNext;
itr->pNext = temp;
itr->pNext->pNext = tempNext;
sorted = false;
if(prev != NULL)
{
prev->pNext = itr;
}
}
prev = itr;
itr = itr->pNext;
}
}
itr = top;
int idCounter = 0;
while(itr != NULL)
{
itr->idNum = idCounter;
idCounter++;
itr = itr->pNext;
}
return top;
}
Thanks for the input everyone!

Pointers and Objects in C++, x86 Compilation Error

I'm creating a binary tree by linking individual nodes all the way up to the root node, which I return from the method.
MaxWinnerTree::MaxWinnerTree(int elements)
{
WinnerTree(elements);
}
`Node MaxWinnerTree::WinnerTree(int elements)
{
int size = 1;
while (size<elements)
size = size * 2; //gets closest power of 2 to create full bottom row
Node* a[size]; //array of pointers to nodes
for (int i = (2*elements-1); i>0; i--)
{
//Create nodes and link them to parent, right, and left values
if (i > elements-1) //leaf
{
//Create new nodes with data -1, store pointer to it in array
*a[i] = newNode(i,-1,NULL,NULL,NULL);
}
else // not leaf
{
//Create node with data = max of children, store pointer
*a[i] = newNode(i,-1,a[i*2],a[i*2 +1], NULL); //create
a[i]->data = max(a[i*2]->data, a[i*2+1]->data); //gets max
a[i]->right->parent = a[i];
a[i]->left->parent = a[i];
if(i=1)
root = a[i];
}
}
return *root; }
However, trying to create an object in my main method isn't working like it should.
MaxWinnerTree* tree = new MaxWinnerTree(elements);
Gives a standard x86 architecture error, where as
MaxWinnerTree tree = new MaxWinnerTree(elements);
Gives
main.cpp:22: error: invalid conversion from ‘MaxWinnerTree*’ to ‘int’
main.cpp:22: error: initializing argument 1 of ‘MaxWinnerTree::MaxWinnerTree(int)’
Why does the compiler think that my method is returning an int? What is to correct way to create an object in this fashion? In reality, I just need a pointer to the root node, where all my other methods will begin.
Thanks for any help in advance.
Changes I would make:
Change newNode (which you haven't shown us) to return a Node *. If newNode isn't actually allocating a new Node, then you need to rethink its design. Or, move the arguments to newNode into a constructor for Node, and change your code to read new Node( ... args ... ).
Instead of saying *a[i] = newNode( ... ) say a[i] = newNode( ... ) (or whatever you replace newNode with as per my first bullet). What you have written asks the C++ compiler to invoke a copy constructor to copy whatever newNode returned into the object pointed to by *a[i], but from the snippet you shared with us, *a[i] doesn't point to anything yet.
You've built a heap, but with explicit pointers. If you really wanted a heap, you don't need the explicit pointers...
This next line can just ruin your whole day. i=1 assigns 1 to i and then returns 1 as its value, which doesn't really do the right thing. In your case, it'll make your loop stop iterating as soon as it gets to the part of the heap-building where the elements have children.
if(i=1)
root = a[i];