Run time error for dynamic memory allocation in C++ - c++

I am a newbie for OOP concepts and while trying to solve Project Euler Problem 7, to find 10001th prime number, I tried to do it using a class but encountered 2 major errors.
instantiating the class prime_n
initializing its argument
I have posted the code here for reference:
#include<iostream>
#include<cstdio>
using namespace std;
class prime_n
{
int j,k;
int n;
int *store;
public:
prime_n(int num)
{
n=num;
store[n];
}
static int isPrime(int j)
{
for(int i=2;i*i<=j;i++)
{
if(j%i==0) return 0;
}
return 1;
}
void find_n()
{
for(int i=0;i<n;i++)
{
store[i]=0;
}
store[0]=2;
j=3;
k=1;
while(store[n-1]==0)
{
if(isPrime(j)) store[k++]=j;
j+=2;
}
}
int get_num()
{
int value=store[n-1];
return value;
}
};
int main()
{
int num, req_num;
printf("Enter the position at which prime number is to be found ");
scanf("%d",&num);
printf("\nnumber = %d",num);
prime_n p = new prime_n(num);
req_num = p.get_num();
printf("The required prime number is %d\n",req_num);
return 0;
}
It would be a great help if someone could help me figure out where I am actually going wrong. Thanks a lot in advance!

Use
prime_n p(num);
or (not recommended in this particular case)
prime_n * p = new prime_n(num);
// some other code
req_num = p->get_num(); // note the -> operator replacing . in case of pointers
delete p;
The first case declares p on stack and it is automatically deallocated when the program leaves the scope (main function in this case)
The second one allocates space on heap and p is the pointer to it. You have to deallocate the memory manually.
As for your second question, the C++ way would be
#include <iostream>
...
int num;
std::cout << "Enter the position at which prime number is to be found "
std::cin >> num;
std::cout << std::endl << "Number = " << num << std::endl;

You provide a constructor:
prime_n(int num)
{
n=num;
store[n];
}
I think you are under the impression that store[n] creates an array with n elements, but that is not so; it attempts to access the (n+1)th element of an an array. Since store does not point anywhere (we are in the constructor, after all), the program crashes.
You probably want to write store = new int[num] instead.
And then I cannot see any call to find_n() originating from get_num() which is called in main(), so that your program would for now just return a random value.

Related

Unlimited Object Creation in C++

While learning the dynamic object creation in C++ i have encountered a doubt . Here is my code.
And my question is , when the limiting condition in the loop is same as that of the no of objects created it works fine. But what happens when the loop works for more than the size given , it seems printing the values entered , but we have created only 4 objects and changed the condition of loop to more than 4
#include <iostream>
using namespace std;
class item{
int number;
public:
item(){
cout<<"Constructor"<<endl;
}
~item(){
cout<<"Destructor"<<endl;
}
void get_num(int num){
number = num
};
void show_num(){
cout<<"Number is "<<number<<endl;
}
};
const int size=4;
int main() {
item *itemObj = new item[size];
item *d = itemObj; //copy the address of itemObj inorder to access its member functions later
int tempNum;
for (int i = 0; i < size; ++i) {
cout<<"Enter the Number"<<endl;
cin>>tempNum;
itemObj->get_num(tempNum);
itemObj++;
}
//to print the numbers entered
for (int i = 0; i < size; ++i) {
d->show_data();
d++;
cout<<d<<endl;
}
delete itemObj;
return 0;
}
Your code isn't working fine at all. Because you change the value of the pointer that you requested from the new operator. When you call the delete for the itemObj at the last line, it doesn't have its original value.
So, instead of modifying the itemObj, you should modify the copy of it which is the pointer d here. Therefore, the problem isn't about the iteration amount of the loop. It's actually the violation on the heap memory.
Also, if you're creating a dynamic array, you should call delete [] instead of delete.

recursive method for array element printing

I am learning recursive calls implementation. i get stuck with return statements, i am trying to print an array elements by recursive call. though i print but it but i want to return it, can some body help
#include<iostream>
using namespace std;
int recursive_arr_traversal(int *arr, int length_of_array) {
if (length_of_array <= 0) {
return 0;
}
else {
return *arr; //this statement prints only one array element<endl
cout << *arr << endl;//this works fine
}
return recursive_arr_traversal(arr + 1, length_of_array - 1);
}
int main() {
int arr[10] = { 1,2,3,4,56,7,8,9,99,0 };
int length_of_array = 10;
//recursive_arr_traversal(arr,length_of_array);
cout << recursive_arr_traversal(arr, length_of_array);
return 0;
}
As Nathan stated, you do not need to return anything. Have a look at the following code which is your code only slightly modified, as I think you got the main idea of recursion:
#include<iostream>
using namespace std;
void recursive_arr_traversal(int *arr, int length_of_array) {
if (length_of_array <= 0) return;
cout << *arr << endl;//this works fine
recursive_arr_traversal(arr + 1, length_of_array - 1);
}
int main() {
int arr[10] = { 1,2,3,4,56,7,8,9,99,0 };
const int length_of_array = 10;
//recursive_arr_traversal(arr,length_of_array);
recursive_arr_traversal(arr, length_of_array);
return 0;
}
In each call one element is printed and it returns once you have traversed the array. Note that there is an implicit return at the end of recursive_arr_traversal.
A (basic) recursive function should have two parts--the base case, where all the work is already done or almost done and all we have to do is clean up and return, and the recursive case, where we need to do some small part of the work and then pass on the rest to the recusive function.
The base case here is pretty simple, and you already have it right. if(length <= 0), all we have left is an empty array, so we can just return and be done. There's no more work to do.
The recursive case is a little more difficult though and you almost have it!
Our recursive case in this problem should print the first element and then pass on an array that's one shorter and starts one element later. Also note that you never use the return value, and since this is a print function, it should probably be void. With those fixes the code could look like:
int arr_print(int *arr,int len){
//base case: if arr is empty, we're done
if(len <= 0) { return; }
//recursive case: print first element, then pass array along to print rest
cout << *arr << endl;
arr_print(arr + 1, len - 1);
}
If you are saying that you want to return all the values to function like main() so that you have permanent access to your array values, that is not possible just by returning in your recursive function. As said above by others, when you return a value, that value is returned to the function that called it (draw a callstack if you need).
If you just make a global variable to save which ever values you need, that could fix your needs.

mergesort not working in c++

Is there anything wrong with the usage of the "return" values of the three fuction? The values printed out are garbage values with seemingly random numbers as outputs.I would also like to add that i havent made it recursive because i wanted to check whether this would work or not.
Most all of the mergesort implementation I've seen hardly contain any return values, is that something im doing wrong. If you were to go about a similar type of implementation, how would you do it?
#include <iostream>
using namespace std;
int* goleft(int array[], int size)
{
int halved=size/2;
int left[halved];
for(int i=0;i<halved;i++)
{
left[i]=array[i];
}
return left;
}
int* goright(int array[],int size)
{
int halved=size/2;
int right[size-halved];
for(int i=halved,j=0;i<size;i++,j++)
{
right[j]=array[i];
}
return right;
}
int* mergesort(int array[],int size)
{
int *l,*r;
l=goleft(array,size);
r=goright(array,size);
int merger[size];
int halved = size/2;
int i;
for(i=0;i<halved;i++)
cout<<l[i]<<endl;
for(i=0;i<halved;i++)
cout<<r[i]<<endl;
int x=0,y=0,k=0;
while(x+y!=size)
{
if(l[x]<r[y])
{
merger[k]=l[x];
x++;k++;
}
else if(l[x]>=r[y])
{
merger[k]=r[y];
y++;k++;
}
}
return merger;
}
int main()
{
int size;
cin>>size;
int array[size];
for(int i=0;i<size;i++)
cin>>array[i];
int *merged=mergesort(array,size);
cout<<"sorted array"<<endl;
for(int i=0;i<size;i++)
cout<<merged[i]<<endl;
return 0;
}
And when we create variables of same name during loops and recursions, are new variable created for every loop iteration or recursion? or do they overwrite the value for the previous variable. for e.g when we write
while(true)
{
int i=0;
}
would a new variable be made at every iteration
and
genericFunction()
{
int i = SomeRandomValue
genericFunction();
}
similarly would a new variable be made at each recursion?
As you thought, the error is in "scopes". To answer to your questions :
while(true)
{
int i=0;
}
The process is :
//iteration N start
create scope
allocate memory for an int variable named 'i' in the current scope
//statements done
delete current scope //deallocate the variables in the current scope
//iteration N end
//iteration N+1 start
/*...*/
So in each iteration it is a different variable. You can test it with this code :
while (true) {
int i;
std::cout << &i << std::endl; //displays the memory location of i
system("PAUSE"); //waiting user input between each iteration
}
In the example with genericfunction, the process is :
//N call to genericFunction
create scope //scope N
//N+1 call to generic Function
create scope //scope N+1
/* statements */
delete current scope //scope N+1
// exit of call N+1
delete current scope //scope N
//exit of call N
You can test it with this complete code :
#include <iostream>
void genericFunction(int a)
{
int i = 0;
std::cout << "scope " << a << " : " << &i << std::endl;
if (a < 9) { //to prevent infinite call
genericFunction(a + 1);
}
std::cout << "scope " << a << " : " << &i << std::endl;
}
int main() {
genericFunction(0);
system("PAUSE");
return 0;
}
A generic rule is : when you have {, you create a new scope and select it as current scope, when you have }, you delete the current scope and select the previous scope. Some scopes permits access to previous scopes (for example a WHILE LOOP : in the code int a; while(true) {a++;}, it modifies the value of a in the previous scope), but when a function scope is created you have no access to previous scopes.
Now for your specific issue with mergedsort, it is the declaration of your variable merger inside the function mergesort. To see the process :
/* ... */
int *merged=mergesort(array,size);
//Call to mergesort
//Creation of scope A
/* ... */
int merger[size]; //Allocation of memory for 'merger' in scope A
/* ... */
return merger; //Affect the location of 'merger' to location pointed by 'merged' in previous scope
//Deletion of scope A (including deallocation of 'merger')
// Now 'merged' points to location of 'merger' which is a deallocated variable :
//no guarantees of the data stored at this location
So it is why there is a problem in your code. One way to correct it is by allocate manually some space for your variable : variables allocated manually have to be deallocated manually, so they will not be deallocated when destroying a scope. Actually the implementation inside the function is using the c++ keyword new : int *merger = new int[size];.
By replacing this declaration your code will be running : but be careful : here's an other rule, if you're using somewhere the keyword new you have to use delete somewhere else : manual allocation have to be followed by manual deallocation. So at the end of your main function, you have to add delete[] merged;. In this way there's no trouble ;) .

Sending an array between two functions C++

I am trying to send a array of 15 integers between two functions in C++. The first enables the user to enter taxi IDs and the second functions allows the user to delete taxi IDs from the array. However I am having an issue sending the array between the functions.
void startShift ()
{
int array [15]; //array of 15 declared
for (int i = 0; i < 15; i++)
{
cout << "Please enter the taxis ID: ";
cin >> array[i]; //user enters taxi IDs
if (array[i] == 0)
break;
}
cout << "Enter 0 to return to main menu: ";
cin >> goBack;
cout << "\n";
if (goBack == 0)
update();
}
void endShift ()
{
//need the array to be sent to here
cout << "Enter 0 to return to main menu: ";
cin >> goBack;
cout << "\n";
if (goBack == 0)
update();
}
Any help is great valued. Many thanks.
Since the array has been created on the stack, you would just need to pass the pointer to the first element, as an int*
void endshift(int* arr)
{
int val = arr[1];
printf("val is %d", val);
}
int main(void)
{
int array[15];
array[1] = 5;
endshift(array);
}
Since the array is created on the stack, it will no longer exist once the routine in which it was created has exited.
Declare the array outside of those functions and pass it to them by reference.
void startShift(int (&shifts)[15]) {
// ...
}
void endShift(int (&shifts)[15]) {
// ...
}
int main() {
int array[15];
startShift(array);
endShift(array);
}
This isn't exactly pretty syntax or all that common. A much more likely way to write this is to pass a pointer to the array and its length.
void startShift(int* shifts, size_t len) {
// work with the pointer
}
int main() {
int array[15];
startShift(array, 15);
}
Idiomatic C++ would be different altogether and use iterators to abstract away from the container, but I suppose that is out of scope here. The example anyway:
template<typename Iterator>
void startShift(Iterator begin, Iterator end) {
// work with the iterators
}
int main() {
int array[15];
startShift(array, array + 15);
}
You also wouldn't use a raw array, but std::array.
It won't work to use a local array in the startShift() function. You are best off to do one or more of the following:
Use an array in the function calling startShift() and endShift() and pass the array to these functions, e.g.:
void startShift(int* array) { ... }
void endShift(int* array) { ... }
int main() {
int arrray[15];
// ...
startShift(array);
// ...
endShift(array);
// ...
}
Don't use built-in arrays in the first place: use std::vector<int> instead: that class automatically maintains the current size of the array. You can also return it from a function altough you are probably still best off to pass the objects to the function.
void endShift (int* arr)
{
arr[0] = 5;
}

C++: How do you create a return function that returns a vector/array?

This is the motivation behind the code. There is a boy named Bob and its his birthday today. He invites 50 friends over but not all of his friends want to buy him gifts. Bob is presented with 50 presents, though some of them are empty. His good friends tell him to close every 2nd box. For every third box, he is supposed to change every closed to open and every open to closed. He continues to do this for every n-th box where n is less than 50. The open boxes in the end will have the presents.
This is supposed to assist me in figuring out a problem for my math class, but I am not aware of all the complicated aspects of C++ programming. I want my string getValue(vector &arr) to return an array/vector. This code doesn't compile but it shows what I'm trying to do.
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
string getValue(vector<string> &arr);
int main()
{
vector<string> myArr(2);
vector<string> newArr(2);
for(int i=2; i <= 50; i++)
{
if(i%2==0)
{
myArr.push_back("close");
}
else
{
myArr.push_back("open");
}
}
newArr = getValue(myArr);
for(int i=2; i <=50; i++)
{
cout << i << " " << newArr[i] << endl;
}
}
string getValue(vector<string> &arr)
{
for(int i=2; i <=50; i++)
{
if(arr[i]=="close")
{
arr[i]="open";
}
else if(arr[i]=="open")
{
arr[i]="close";
}
}
return arr;
}
You can't make your string getValue(vector<string> &arr) return an array/vector. It can only return a string. If you want a function to return an array/vector, then you have to say so in the function signature.
You're passing the vector into getValue() by reference, which means changes you make to it in that function will affect the original (in other words, you're not operating on a copy of the vector - you're actually operating on the vector).
So you don't need to return anything from getValue() - just make it void and it should do what you want.
string getValue(vector &arr) - the return type is string, not vector. You need to change its return type or set it to none.
PS:
newArr = getValue(myArr);
it's behind the SCOPE and it's wrongly positioned...
damn, third PS, wrong code rules are assigned
For the syntax part :-
The return type of the function is a string. Change it to vector for
your function to work properly.
You can simply declare the vectors globally. This will eliminate the
need to pass it to the function as well as return it.
For the logic part :-
Your question says that Bob toggles every third box but in your program Bob is changing every box to open if it is closed and every box to close if it is open. If what you wrote in the question is correct your code should be like this.
#include <iostream>
#include <vector>
using namespace std;
void getValue();
vector<string> myArr(2);
int main()
{
for(int i=2; i <= 50; i++)
{
if(i%2==0)
{
myArr.push_back("close");
}
else
{
myArr.push_back("open");
}
}
getValue();
for(int i=2; i <=50; i++)
{
cout << i << " " << myArr[i] << endl;
}
}
void getValue()
{
for(int i=3; i <=50; i+=3)
{
if(myArr[i]=="close")
{
myArr[i]="open";
}
else if(myArr[i]=="open")
{
myArr[i]="close";
}
}
}