a function which convert integer to an array of digits c++ [duplicate] - c++

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
#include<iostream>
using namespace std;
int *Arr(int y,int size){
int arg[size];
for(int i=size-1;i>=0;i--){
arg[i]=y%10;
y=y/10;
}
return arg;
}
int main(){
int *p=Arr(2587,4);
for(int j=0;j<4;j++){
cout<<p[j]<<" ";
}
return 0;
}
> Blockquote
I dont why this isn't working ...I'm trying to back an array but the problem is in the second digits.Can somebody help ;) thanks

The problem is you are putting your result into a local array that is destroyed when the function ends. You need to dynamicaly allocate the array so that its life-span is not limited to the function it was created in:
#include<iostream>
using namespace std;
int *Arr(int y, int size)
{
// This local array will be destroyed when the function ends
// int arg[size];
// Do this instead: allocate non-local memory
int* arg = new int[size];
for(int i = size - 1; i >= 0; i--)
{
arg[i] = y % 10;
y = y / 10;
}
return arg;
}
int main()
{
int *p = Arr(2587, 4);
for(int j = 0; j < 4; j++)
{
cout << p[j] << " ";
}
// You need to manually free the non-local memory
delete[] p; // free memory
return 0;
}
NOTE:
Allocating dynamic memory using new is to be avoided if possible. You may want to study up on smart pointers for managing it.
Also, in real C++ code, you would use a container like std::vector<int> rather than a builtin array

Of course it is not working.
At best, the behaviour is undefined, since Arg() is returning the address of a local variable (arg) that no longer exists for main(). main() uses that returned address when it is not the address of anything that exists as far as your program is concerned.
There is also the incidental problem that int arg[size], where size is not fixed at compile time, is not valid C++. Depending on how exacting your compiler is (some C++ compilers reject constructs that are not valid C++, but others accept extensions like this) your code will not even compile successfully.
To fix the problem, have your function return a std::vector<int> (vector is templated container defined in the standard header <vector>). Then all your function needs to do is add the values to a local vector, which CAN be returned safely by value to the caller.
If you do it right, you won't even need to use a pointer anywhere in your code.

Related

What is the difference between allocating a specific sized array vs declaring a specific sized array in function in cpp? [duplicate]

This question already has answers here:
What is a dangling pointer?
(7 answers)
Closed 5 years ago.
Normally a scope of an array in a function ends with it. But if I allocate beforehand then it perfectly returns the array. So what's the difference between allocating array or declaring array?
I am writing the code and the place where I am confused. Is it because of dynamic memory allocation of the first declaration or something else. Can someone elaborate please?
#include <bits/stdc++.h>
#define N 10
using namespace std;
int * get_array() {
int * p = new int[N];
//|--- by declaring like this, the array was perfectly returned.
int p[N];
//|--- but is case of this declaration the array returned showed garbage value in the main function.
for(int i = 0; i < N; ++i) p[i] = i;
return p;
}
int main(int argc, char const *argv[])
{
int * M = get_array();
for (int i = 0; i < N; ++i) {
cout << M[i] << endl;
}
return 0;
}
In the second case the array is created in the heap of the function, so when you exit the function, that array doesn't exists anymore.
In the first case, you're reserving memory space to put your array, so isn't local to the function per se, and you must handle its destruction

Returning arrays from a function in c++

I am trying to return an array from a function:
#include <iostream>
using namespace std;
int* uni(int *a,int *b)
{
int c[10];
int i=0;
while(a[i]!=-1)
{
c[i]=a[i];
i++;
}
for(;i<10;i++)
c[i]=b[i-5];
return c;
}
int main()
{
int a[10]={1,3,3,8,4,-1,-1,-1,-1,-1};
int b[5]={1,3,4,3,0};
int *c=uni(a,b);
for(int i=0;i<10;i++)
cout<<c[i]<<" ";
cout<<"\n";
return 0;
}
I pass two arrays from my main() into my uni() function. There I create a new array c[10] which I return to my main().
In my uni() function I try to merge the non-negative numbers in the two arrays a and b.
But I get something like this as my output.
1 -1078199700 134514080 -1078199656 -1216637148 134519488 134519297 134519488 8 -1078199700
Whereas when I try to print the values of c[10] in the uni() function it prints the correct values. Why does this happen??
Is this something related to the stack?? Because I have tried searching about this error of mine, and I found a few places on stackoverflow, where it says that do not allocate on stack but I couldn't understand it.
Further it would become very easy if I allocate my array globally, but if this is the case then everything shall be declared globally?? Why are we even worried about passing pointers from functions?? (I have a chapter in my book for passing pointers)
Admittedly, the std::vector or std::array approach would be the way to go.
However, just to round things out (and if this is a school project, where the teacher gives you the obligatory "you can't use STL"), the other alternative that will avoid pointer usage is to wrap the array inside a struct and return the instance of the struct.
#include <iostream>
using namespace std;
struct myArray
{
int array[10];
};
myArray uni(int *a,int *b)
{
myArray c;
int i=0;
while(a[i]!=-1)
{
c.array[i]=a[i];
i++;
}
for(;i<10;i++)
c.array[i]=b[i-5];
return c;
}
int main()
{
int a[10]={1,3,3,8,4,-1,-1,-1,-1,-1};
int b[5]={1,3,4,3,0};
myArray c = uni(a,b);
for(int i=0;i<10;i++)
cout << c.array[i] << " ";
cout << "\n";
return 0;
}
Note that the struct is returned by value, and this return value is assigned in main.
You have the value semantics of returning an instance, plus the struct will get copied, including the array that is internal within it.
Live Example
You're returning a pointer to a local object. In the uni function, the variable c is allocated on the stack. At the end of that function, all of that memory is released and in your for loop you are getting undefined results.
As suggested in the comments, std::array or std::vector will give you copy constructors that will allow you to return the object by value as you're trying to do. Otherwise you'll have to resort to something like passing your output array in as an argument.
You are returning a pointer to an array that is being deallocated at the return statement. It's a dangling pointer. It's UB.
Use an std::vector or std::array and return by value. There are compiler optimizations that will avoid inefficiencies.

Returning an array pointer from a function in C/C++ without static integer

I'm going to write a piece of code (Function) that returns a pointer to an array.
but I don't know how to do that.
The code I wrote is :
int* prime_factor(int temp){
int ctr;
int *ret;
int i = 0;
while (temp != 1){
ctr = 2;
if (temp%ctr != 0){
ctr++;
}
else {
*(ret + i) = ctr;
temp /= ctr;
}
}
return ret;
}
I guess that there's a need to such the thing :
else {
ret = new int[1];
*(ret +i) = ctr;
temp /= ctr;
}
But as you know , implementation of this stuff needs to be deleted the memory that you have allocated , so we have to delete the memory outside of the function , so it going to be nonstandard function.
Indeed, i want to calculate the Prime factors of a number then return them out.
Any idea to do that ? I don't know what should I do to gain the goal.
thank you so much.
I see your question has also the tag C++ so, you could use C++. I don't really know what you mean with without static integer ....
Use vector.
#include <vector>
vector<int> prime_factor(int number)
{
int ctr = 2;
vector<int> factors;
while (number != 1)
{
if (number % ctr != 0)
ctr++;
else
{
factors.push_back(ctr);
number /= ctr;
}
}
return factors;
}
As you will be using the vector with integers it knows how to destroy ("delete") it self.
Example:
int main()
{
for (auto &x : prime_factor(20)) // C++11
{
cout << x << endl;
}
}
Output:
2
2
5
Yes, putting burden of deleting the array on user is not preferable. Here you would be better off using vector instead of plain array.
You can also pass array as an argument(created in the caller so that it would be more intuitive to use delete on that array) to this function.
The line *(ret + i) = ctr; will create a memory violation right away, since your ret pointer has no allocated memory pointing to. You nee do preallocate a memory for it, either statically (array declaration) in the code CALLING this function, and passing it to the function as a parameter, or dynamically (using malloc or similar) and then freeing it in some point. Dynamic allocation can be done either in the function itself or in the calling code. But again, free the memory afterwards.
int *ret;
In your case ret doesn't point to any memory location.You are trying to reference some unallocated memory location which might cause segmentation fault.
Just to show how to return a pointer and free it below is the example:
int *some()
{
int *ret = malloc(sizeof(int));
*ret = 10;
return ret;
}
int main()
{
int *p = some();
printf("%d\n",*p);
free(p);
}
"But as you know , implementation of this stuff needs to be deleted the memory that you have allocated , so we have to delete the memory outside of the function , so it going to be nonstandard function."
To avoid that dilemma c++ has introduced Dynamic memory management support.
Instead of using raw pointers like int* use one appropriate of
std::unique_ptr<int> (to transfer ownership)
std::shared_ptr<int> (to share ownership)
std::weak_ptr<int> (to share ownership, but not count as reference)
std::auto_ptr<int> (to transfer ownership "the old way")
Besides that, it looks like using a std::vector<int> would be much more appropriate, than using a simple int*. The std::vector<int> class also is purposed to release you from getting the dynamic memory management right on your own.

C++ Creating an Array using Pointers

I'm currently learning C++, so sorry if I seem a little silly.
My current exercise, that I'm stuck on, requires me to write a function, IndexArray(int n) that returns a pointer to a dynamically allocated integer array with n elements, each of which is initialised to its own index.
(copied from the worksheet).
I've read this several times and don't fully understand it, but they gave an example:
Assuming that intPtr is declared as
int *intPtr;
the statement
intPtr = IndexArray(10);
should produce the following memory configuration:
intPtr -> 0 1 2 3 4 5 6 7 8 9
From this example I'm guessing my function needs to create an array of size n, with values from 0 to n-1, and then another pointer needs to point to that array.
Here's their test code:
int *values1;
values1 = IndexArray(10);
I know how to easily create the array, but I don't fully understand pointers enough to know really what to do. I figured returning an array would work:
int *IndexArray(int n) {
cout << n << endl;
int arrayTemp[n];
for(int i = 0; i < n; i++) {
arrayTemp[i] = i;
}
return arrayTemp;
}
However when tested, values1 array doesn't contain the values from 0-9 (although arrayTemp does right before it's returned).
Any help would be amazing, and hopefully I've given everything you need to help. Thanks! :D
int arrayTemp[n];
Notice that the statement is in a function, so when the function terminates, the arrayTemp[] will not be available any more, it coule be removed : it is a #local# variable!
So, if you want to do that , you could use :
int * arrayTemp = new int[n];
NOTICE : you must delete it any how to avoid memory leaks.
You cannot do this:
int *IndexArray(int n) {
cout << n << endl;
int arrayTemp[n]; //declare a local array
for(int i = 0; i < n; i++) {
arrayTemp[i] = i;
}
return arrayTemp; //return a pointer to a local
}
You cannot return a pointer to a local. The local ceases to exist once you return. The pointer now points to garbage.
Instead, you have to use malloc (C or C++) or new (C++) to dynamically create storage for 10 ints, and since this is dynamically created on the heap it will persist after returning (and will need to be freed if malloced or delete[]d if it was a an array made with new. For just single objects made with new you just use delete )

C++ Class pointer is not saving anything.

The following is a small scale example of the problem I am facing. In the example below I use int pointers but in my own code I am really using a pointer to another class (a node class).
The problem appears to be that I am using a call by value pointer (if there is such a thing). I don't know, I thought pointers were by reference. I do need to be able to pass multiple pointers to the method and I do not really want to write a specific method for each pointer. When I run the code, of course, I get some kind of error because it is trying to access a pointer that has not been allocated.
I do not understand why it would not initialize the correct pointer if I pass the specific pointer I want.
Any help would be greatly appreciated.
#include <iostream>
using namespace std;
class Test {
private:
int *p1;
int *p2;
int sizeP1;
int sizeP2;
public:
int* getIntPointer() {return p1;}
void initializeP1(int *ip,int n){
sizeP1=n;
ip=new int[n];
for(int i=0;i<n;i++)
p1[i]=i;
}
void printP1() {
for(int i=0;i<sizeP1;i++)
cout<<p1[i]<<" ";
}
};
int main() {
Test t;
t.initializeP1(t.getIntPointer(),10);
t.printP1(); //this fails.. but why? How can I fix it?
return 0;
}
The problem is that you initialize ip and you fill p1
void initializeP1(int **ip,int n){
sizeP1=n;
*ip=new int[n];
for(int i=0;i<n;i++)
*ip[i]=i;
}
//call with p1
initializeP1(&p1, 10); // pass pointer to pointer so you can get return value.
The problem is that your function allocates memory to the copy of the pointer that is the argument - this copy is lost at function exit. Pass the pointer by reference instead by changing the function signature
void initializeP1(int* &ip,int n){
^
This way the allocated memory is still accessible and your pointer will point to it
Would it not simply be easier to change your initializeP1 function to something like:
int * initializeP1(int n)
{
sizeP1 = n;
p1 = new int[n];
for(int i = 0; i < n; ++i)
p1[i] = i;
return ip;
}
There are still problems with this however, such as the fact that you can call it repeatedly and cause big memory leaks.
It might be better to use a proper constructor for your class that does what initializeP1 did, like such:
Test(int n)
{
sizeP1 = n;
p1 = new int[n];
for(int i = 0; i < n; ++i)
p1[i] = i;
return ip;
}
Pointers are not passed by reference, no. Pointers are value types. You'd want to use a reference if you absolutely had to make it look like this, but it's an abuse of syntax and you should do it a different way instead.
The call to t.getIntPointer() returns a pointer that is not initialised to something sensible.
The call to initializeP1() is newing an array of ints.
But be careful, this allocated block of memory will not be freed until you tell it so by writing "delete [] p1;".