Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I just wrote a simplified implementation of the stack data structure in a class, but the handling of an integer array is behaving in a way that I can't seem to understand.
The same snippet of code as in push() will give the behavior I expect, but in this program assigning a value at a certain array position will assign the value to the index variable>
#include <iostream>
using namespace std;
class stack
{
public:
stack(int size)
{
ar_size = size - 1;
array[ar_size];
index = 0;
}
void push(int value)
{
cout << "index; " << index << endl; //will output 0
cout << "value: " << value << endl; //will output 8
array[index++] = value;
cout << "index; " << index << endl; //will output 8
cout << "value: " << value << endl; //will output 8
cout << "array: " << array[index] << endl; //will output what seems to be a memory address
}
int pop()
{
cout << "index; " << index << endl; //will output 8
return array[index--];
}
private:
int ar_size;
int array[];
int index;
};
int main()
{
stack tower(64);
tower.push(8);
int r = tower.pop();
cout << "pop: " << r << endl; //will output what seemed to be a memory address
return 0;
}
Here is the corrected code of your example:
#include <iostream>
class stack
{
public:
stack(int size)
{
ar_size = size - 1;
array = new int[size];
index = 0;
}
void push(int value)
{
array[index++] = value;
}
int pop()
{
return array[--index];
}
~stack()
{
delete array;
}
private:
int ar_size;
int *array;
int index;
};
int main()
{
stack tower(64);
tower.push(8);
int r = tower.pop();
std::cout << "pop: " << r << std::endl; //Will output 8 :)
return 0;
}
There were several issues with it.
As pointed out in the comments array[ar_size]; in your constructor did not do what you wanted it to. array[ar_size]; accesses the array at the given index, it does not allocate the array for you. I've fixed the problem so that the array is now allocated via new and deleted when the stack is destroyed.
return array[index--]; was not right as well. You need to lower the index before accessing the element. return array[--index]; is now right.
You're missing a BUNCH of checks so that your stack does not cause a segfault or any other undefined behaviour. You need to check if you can still push values or if you can pop values and so on.
I hope it clears things up a bit.
You could use dynamic memory allocation.Something like this
private:
int ar_size;
int *array;//pointer to array
int index;
and then in the constructor
stack(int size)
{
ar_size = size - 1;
array=new int[ar_size];
index = 0;
}
Since this is dynamic memory allocation make sure to free the allocated memory.You can have a destructor
~stack()
{
delete[] array;
}
Another point is after you push an element,you increase the index by 1.So now index does point to the next insertion point in the stack.So if you do a pop operation it will remove an element from index location but there is no element there yet.So you can change your pop function to
int pop()
{
cout << "index; " << index << endl; //will output 8
return array[--index];//now index will point to the top element
}
I think you want array = new int[ar_size]; instead of array[ar_size];. You'll need to make a destructor that does delete [] array; as well then.
Related
Before my program can free up memory and end it crashes. Crashes seem to happen on transition from the function UserDataCollection and back to main. This is only my second program using pointers so I'm still quite the newbie considering the whole point of c++ is to use pointers.
Here is the aforementioned code:
#include <iostream>
//Prototypes
void UserDataCollection(int * &movieData_ptr, int &numSurveyed); // Movie Statistics
void DisplayOutput(int *movieData_ptr, int numSurveyed); //Mean, Median, Mode (Display To Console)
//Global Constants
int main()
{
//Variables
int numSurveyed = 0;
//Pointers
int * movieData_ptr = nullptr;
movieData_ptr = new int[numSurveyed];
//"Program Start"
std::cout << "Program start...\n\n";
UserDataCollection(movieData_ptr, numSurveyed);
DisplayOutput(movieData_ptr, numSurveyed);
//Release Memory
delete[] movieData_ptr;
std::cout << "Memory Cleared.";
return 0;
}
void UserDataCollection(int * &movieData_ptr, int &numSurveyed)
{
//Get Number of Students Surveyed
std::cout << "How many students were surveyed: ";
std::cin >> numSurveyed;
//Student Data Input Loop
for (int i = 0; i < numSurveyed; i++)
{
//Get Student Data
std::cout << "Enter How many movies student " << i + 1 << " has seen in ONE month: ";
std::cin >> *(movieData_ptr + i);
//Validation Check
while (*(movieData_ptr + i) >= 337)
{
std::cout << "\nImpossible value!" << std::endl
<< "Hours in a month: 730. Average movie length: 130 minutes."
<< "Total Possible movies: 337";
std::cout << "\n\nEnter How many movies student " << i + 1 << " has seen in ONE month: ";
std::cin >> *(movieData_ptr + i);
} //end while (Validation Check)
} // end for (Data Input)
}
void DisplayOutput(int *movieData_ptr, int numSurveyed)
{
//Display loop for pointer array
for (int i = 0; i < numSurveyed; i++)
{
std::cout << *(movieData_ptr + i) << " ";
}
//End Message
std::cout << "\n\nProgram end.";
}
You never allocated any memory.
int numSurveyed = 0;
//Pointers
int * movieData_ptr = nullptr;
movieData_ptr = new int[numSurveyed];
This is the equivalent of
int *movieData_ptr = new int[0];
You are allocating size of 0 ints. This is undefined behaviour. You can't do anything useful with that pointer without a segmentation fault. You need to either pre-allocate a certain amount, and make sure you don't overflow, or dynamically allocate every time you plan to add data.
Since this is C++, it's probably better not to use raw pointers, but use vector or something instead.
Sorry:
From 5.3.4/7
When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.
From 3.7.3.1/2
The effect of dereferencing a pointer returned as a request for zero size is undefined.
The issue I'm having is I'm trying to return an array from the function EnterNumber() and display it in the main, but its coming out fairly crazy. I went through with the debugger and the numbers are correct in the debugger, just not correct in once it prints to the screen.
I realize there's a global const int in my program, but it was sanctioned by my professor who wanted us to do it just this time for this program.
Just looking for a nudge on why its printing incorrectly. Thank you.
#include <iostream>
using namespace std;
void EnterNumber(int Number[]);
const int SIZE=20;
int main()
{
int LargeNumber1[SIZE];
int LargeNumber2[SIZE];
for (int Counter1=0; Counter1<=19; ++Counter1)//zeros arrays out
{
LargeNumber1[Counter1]=0;
LargeNumber2[Counter1]=0;
}
EnterNumber(LargeNumber1);
for (int Counter2=0; Counter2<=19; ++Counter2)//display array 1 contents
{
cout << LargeNumber1[SIZE];
}
cout << "\n\n";
EnterNumber(LargeNumber2);
for (int Counter2=0; Counter2<=19; ++Counter2)//display array 2 contents
{
cout << LargeNumber2[SIZE];
}
}
void EnterNumber(int Number[])
{
int TemporaryArray[SIZE];
int PlaceCounter;
char Storage;
PlaceCounter=0;
for (int Counter1=0; Counter1<=19; ++Counter1)//zeros arrays out
{
TemporaryArray[Counter1]=0;
Number[Counter1]=0;
}
cout << "Please enter a large number --> ";
cin.get(Storage);
while (Storage!='\n' && PlaceCounter<SIZE)//puts number in temp array - left aligned
{
TemporaryArray[PlaceCounter]=(Storage-'0');
++PlaceCounter;
cin.get(Storage);
}
--PlaceCounter;//decrement one to get it to work properly with element style counting, else, extra zero at end
for (int A=SIZE-1; PlaceCounter>=0; A--, PlaceCounter--)//transfers old array into new array, right aligned
{
Number[A]=TemporaryArray[PlaceCounter];
}
cout << "\n";
}
This:
for (int Counter2=0; Counter2<=19; ++Counter2)
{
cout << LargeNumber1[SIZE];
}
should be this:
for (int Counter2=0; Counter2<SIZE; ++Counter2)
{
cout << LargeNumber1[Counter2];
}
You were repeatedly printing a number that was just beyond the end of the array.
(Disclaimer: Pointers in C++ is a VERY popular topic and so I'm compelled to believe that someone before me has already raised this point. However, I wasn't able to find another reference. Please correct me and feel free to close this thread if I'm wrong.)
I've come across lots of examples that distinguish between pointer to first element of array and pointer to the array itself. Here's one program and its output:
//pointers to arrays
#include <iostream>
using namespace std;
int main() {
int arr[10] = {};
int *p_start = arr;
int (*p_whole)[10] = &arr;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
cout << "Adding 1 to both . . . " <<endl;
p_start += 1;
p_whole += 1;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
return 0;
}
Output:
p_start is 0x7ffc5b5c5470
P_whole is 0x7ffc5b5c5470
Adding 1 to both . . .
p_start is 0x7ffc5b5c5474
P_whole is 0x7ffc5b5c5498
So, as expected, adding 1 to both gives different results. But I'm at a loss to see a practical use for something like p_whole. Once I have the address of the entire array-block, which can be obtained using arr as well, what can I do with such a pointer?
For single arrays, I don't think there's much point to it. Where it becomes useful is with multi-dimensional arrays, which are arrays of arrays. A pointer to one of the sub-arrays is a pointer to the row, and incrementing it gets you a pointer to the next row. In contrast, a pointer to the first element of the inner array is a pointer to a single element, and incrementing it gets you the next element.
int (*)[10] is a "stronger" type than int* as it keeps size of the array,
so you may pass it to function without passing additional size parameter:
void display(const int(*a)[10]) // const int (&a)[10] seems better here
{
for (int e : *a) {
std::cout << " " << e;
}
}
versus
void display(const int* a, std::size_t size) // or const int* end/last
{
for (std::size_t i = 0; i != size; ++i) {
std::cout << " " << a[i];
}
}
I have two structures in which the second structure has the first structure nested inside of it:
struct first
{
int a;
};
struct second
{
first nested;
};
Now the problem is that the second structure has to be dynamically allocated through a pointer. Also, the nested first structure has to be a dynamically allocated array through a pointer, whose array size has to be read in through an input file.
I know how to read it in but I don't know how to access it. For example lets suppose the size is 8. How would I go about specifying the values for the second structure given the pointer's format?
I tried assuming ptr points to first structure and ptr1 points to second structure ptr1->((ptr+count)->a) where we can process it through a loop. This doesn't work. So I was wondering how you would initialize the values the second structure whose member includes all the n structures in the n element array.
Vector is really easy just stick your struct where type is and use it like any other array. Although what you described really sounds like linked list but hey vector will probably be better for you :)
#include <vector>
//main
vector <Type> myArray(8); //set the number of elements you want
myArray[0] = blablabla
More specific example:
struct first
{
int a;
};
vector <first> myArray(8);
first[0].a = 1; // you get the idea :)
EDIT
From the comments this seems to me more up your alley.
struct bla {
int num;
};
//in main
bla *balBla = NULL;
blaBla = new(bla[8]); //There made on the fly dynamic man
blaBla[0].num = 7;
//Don't forget to delete when done or scary memory leak!!!
delete[] blaBla;
Last Edit If this is not what you want then no one will ever understand what you mean
#include <iostream>
using namespace std;
struct b {
int num;
};
struct a {
b *nested = NULL;
a(){} //Default Constructor
a(int elements) {
nested = new(b[elements]);
} //Lets you add elements to nested at initialization
void addElem(int elements) {
if (nested != NULL) {
delete[] nested;
}
nested = new(b[elements]);
} //Redefine or make new array
~a() {
delete[] nested;
} //destructor
};
int main() {
a myStupidObj(3);
myStupidObj.nested[0].num = 69;
myStupidObj.nested[1].num = 77;
myStupidObj.nested[2].num = 666;
cout << "Struct of one D array of structs" << endl;
cout << myStupidObj.nested[0].num << endl;
cout << myStupidObj.nested[1].num << endl;
cout << myStupidObj.nested[2].num << endl;
//Make 2d version
a *my2DStupidObj = new(a[2]);
my2DStupidObj[0].addElem(3);
my2DStupidObj[0].nested[0].num = 666;
my2DStupidObj[0].nested[1].num = 6969;
my2DStupidObj[0].nested[2].num = 80085;
cout << "array of struct of one D array of structs" << endl;
cout << my2DStupidObj[0].nested[0].num << endl;
cout << my2DStupidObj[0].nested[1].num << endl;
cout << my2DStupidObj[0].nested[2].num << endl;
my2DStupidObj[1].addElem(3);
my2DStupidObj[1].nested[0].num = 11;
my2DStupidObj[1].nested[1].num = 111;
my2DStupidObj[1].nested[2].num = 1111;
cout << my2DStupidObj[1].nested[0].num << endl;
cout << my2DStupidObj[1].nested[1].num << endl;
cout << my2DStupidObj[1].nested[2].num << endl;
delete [] my2DStupidObj;
return 0;
}
In C, you sometimes see something like:
struct second {
int count;
first nested[1];
};
Then, you allocate memory. The amount you allocate is computed as sizeof(struct second) plus the size of first times the number of elements you want in the array minus 1 (since there is already one included).
ptr = (struct second *)malloc(sizeof(struct second) + ((n-1) * sizeof(first)));
Then you can use
ptr->nested[idx].a
or if you have to use pointers,
((ptr->nested)+idx)->a
Of course, you have to do all the housework and cleanup yourself. C++ and its std libraries do most of that for you.
I'm not entirely sure why I'm getting a segfault for this piece of code. I have an array of object pointers I want to create. Here is my code.
edge **test = new edge*[a]; //Edge is a predefined class I have created. a is a my size of my array.
graphCreate2(test, vertices, roads, a); //Note roads is an edge class I have already created also
However, when I try to access edge ** test's elements, I get a segfault. Here's how I accessed it.
void graphCreate2(edge **test, int vertices, edge *roads, int a)
{
for(int i = 0; i < a; i++)
{
e[i]->setEdgeSrc(roads[i].getEdgeSrc());
e[i]->setEdgeDes(roads[i].getEdgeDes());
e[i]->setLength(roads[i].getLength());
cout << e[i]->getLength() << " " << e[i]->getEdgeSrc() << " " << endl;
}
}
Might anyone know why I'm getting this segfault? I thought I allocated memory to it as the constructor is called when creating the array Thanks!
The constructor is not called for each edge. You're only creating the array of pointers, but they point to garbage.
You need to create them all in a loop.
void graphCreate2(edge **test, int vertices, edge *roads, int a)
{
for(int i = 0; i < a; i++)
{
test[i] = new edge(); // create the edge
test[i]->setEdgeSrc(roads[i].getEdgeSrc());
test[i]->setEdgeDes(roads[i].getEdgeDes());
test[i]->setLength(roads[i].getLength());
cout << test[i]->getLength() << " " << test[i]->getEdgeSrc() << " " << endl;
}
}