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 )
Related
I've been stuck on this problem and I'm hoping someone can explain where I'm wrong on this. I'm working on an assignment where I need to:
1) Allocate an array that can contain 100 int values by calling allocIntArray and assign the returned pointer to ptr1.
2) Use the new operator to allocate an array of integers using the parameter as the size of the array.
3) Return the pointer that is returned by the new operator.
4) Print out the new array.
I'm trying to print out the array after passing the size I want through the function.
int main() {
int *ptr = NULL;
ptr1 = *allocIntArray(100);
cout << ptr1 << endl;
return 0;
}
//The function I want to call
int *allocIntArray(int size) {
int *newarr = nullptr;
newarr = new int[size];
return newarr;
}
However when I call the function, the output comes out as 00F011E8.
I'm currently trying to understand why this is the output and not the first value in the array. (Just the number 1)
I've been having a lot of trouble grasping pointers any help understanding would be greatly appreciated.
Thanks to everyone who took the time to respond.
From what I understand from assignment directions, I shouldn't need to use vectors. I'm trying to modify my current code to display the array output and this is what currently comes up when I run it.[enter image description hereMy current results
At first, if you're using C++, you should use std::vector/std::array. This avoids a huge amount of possible problems.
It would look like:
#include <iostream>
#include <vector>
int main()
{
// create array of size 10 and initialize it with 0's
std::vector<int> vec(10, 0);
// print array
for(auto a : vec)
std::cout << a << '\t';
std::cout << std::endl;
}
If it's some kind of exercise, you have done four big mistakes:
you dereference the returned pointer to the array. So you get the value of the first element in the array and not the array itself. Simply remove the *.
you print out the address of the first element of the array. To print the array, you have to iterate over each element of the array. This can be done in a for loop:
for(int i = 0; i < 10; ++i)
std::cout << ptr1[i] << '\t';
you want to print out the array uninitialized. In fact, you try to print out some random values which are there in the memory. At first, you have to assign the elements values.
you forget to delete the array by using
delete[] ptr1;
I just have to answer as you seem to be missing some important fundamentals. Either the instructor should be dismissed or you have not paid enough attention in the class. So...
ptr1 = *allocIntArray(100);
You could not have pasted code that compiles, ptr1 is not declared.
You need to understand what the * operator does. What ever value to the right of * must be a pointer. What a pointer is should be fundamental in your understanding. If you had:
int* ptr1 = *allocIntArray(100);
You should have gotten a compiler error, so you must have:
int ptr1;
Somewhere along the line. As allocIntArray(...) returns a pointer, then *allocIntArray(...) gives you an integer.
You would have wanted to:
int* ptr1 = allocIntArray(100);
To get a pointer to the new array. Then you:
std::cout << ptr1 << std::endl;
So, what is ptr1? If it is a pointer then all you are doing is printing the pointer value. Per your stated problem, I'd say ptr1 is in fact a pointer. std::cout has not facility to work with a pointer as you expect. At that, it would have no way of determining the size of your array.
You would want to (And it hurts my fingers to write like this):
for(size_t i= 0; i < 100; ++i)
std::cout << ptr1[i] <<" ";
But!!!
4) Print out the new array.
So what will it print? There was never an instruction to initialize the array. It will print out what ever garbage is sitting in the array when it was created.
Side note, that the instructor has you doing a:
using namespace std;
Says much, as he/she should never have allowed it.
EDIT: Im quite new to c++ and programming as a whole.
I'm supposed to make a program where i use stucts and and an array of structs.
Security council < > Member of Security council
My task was to use the concept of "UML aggregation" to create a program where I use structs and struct arrays. (I hope you understand what I'm trying to say)
Since a Member of a Security council is a part of a Security council, and not the other way around, the struct of Security council must have an array of its members.(bear with me)
//example
struct Member_sc{
char * name;
int age;
};
struct Security_council{
Member_sc members[10];
};
Now, I've created this program and everything works perfectly (according to my teacher), but now she told me create an exact copy, but instead of the "members" array I must use an array of pointers to the Member_sc structs. Since I havent completely figured out how pointers work, I have come across some problems.
I can post the code to the original program if needed, but it contains 4 files(main, header, and some function files) and it would be a pain to try and post it here.
here is the prototype (all in one file, for now)
#include <iostream>
using namespace std;
struct member_sc{
string name;
};
struct security_council{
member_sc *point;
security_council **search; // ignore this for now
int n;
security_council():n(0){}
};
void in_mem( member_sc &x){
getline(cin,x.name);
}
void out_mem(member_sc &x){
cout<<x.name<<endl;
}
void in_SC(security_council &q, member_sc &x){
int num; //number of members
cin>>num;
for(int i=0; i<num; ++i){
in_mem(x);
q.point[q.n]=x;
q.n++;
}
}
void out_SC(security_council &q,member_sc &x){
for(int i=0; i<q.n; ++i){
out_mem(q.point[i]);
}
}
int main(){
member_sc y;
security_council x;
in_mem(y); // works
out_mem(y); // works
in_SC(x,y); // crashes after i input the number of members i want
out_SC(x,y); //
system("pause");
return 0;
}
The program crashes after you input the number of members you want in your Security council.
Is my way of thinking right? or should I use dynamic memory allocation?
in addition to that (my teacher gave me an additional task) create a search function using pointers. i thought that pointer to pointer may be good for that, but im not sure.
Any help or advice would be greatly appreciated.
( i think ill figure out the search thingy once i figure out how pointers to structs work)
The first part of your issue is this:
cin >> num;
this reads only the digits that have been typed and stops at the newline. Then, in in_mem the call to getline immediately reads a newline. You need to do:
cin >> num;
cin.ignore();
this will drain the input stream of any remaining input, or catch up so to speak.
However your core problem is that you don't allocate any memory for "point" to point to.
A pointer is just a variable holding a value that happens to be the address (offset from 0) of a thing in memory. If you are going to the airport and write "Gate 23" on a post-it note, the post it note is a pointer and "Gate 23" is the value.
In your code, that variable is uninitialized and will either be 0, if you are lucky, or some random address in memory if you aren't so lucky.
To the airport analogy: you arrive at the airport and find that your post-it note has "pizza" written on it. Not helpful.
Your teacher has actually specified an "array of pointers". Break that down: pointer to what? member_sc, that's member_sc*. And now make it an array
member_sc* pointers[10];
NOTE: This is not good, modern C++ - in modern C++ you would use something called a smart pointer (std::unique_ptr) probably.
std::unique_ptr<member_sc[]> pointers(new member_sc[10]);
Now you have 10 pointers instead of just one, and all of them will need some allocation to point to. The easiest way to do this is with the new keyword and the copy constructor:
for (int i = 0; i < num; i++) {
in_mem(x);
pointers[q.n] = new member_sc(x); // make a clone of x
q.n++;
}
or in modern C++
for (int i = 0; i < num; i++) {
in_mem(x); // x is temporary for reading in
pointers[q.n] = std::make_unique<member_sc>(x);
q.n++;
}
However there is a limitation with this approach: you can only have upto 10 security council members. How do you work around this? Well, the modern C++ answer would be to use a std::vector
std::vector<member_sc> members;
// ditch n - vector tracks it for you.
// ...
for (int i = 0; i < num; ++i) {
in_mem(x);
q.members.push_back(x);
// q.n is replaced with q.members.size()
// which is tracked automatically for you
}
but I'm guessing your teacher wants you to actually understand pointers before you get to forget about them with modern luxuries.
We need to re-use the pointer stuff we've just used above and change "pointers" to an array of pointers.
Which means we're going to want a pointer to a set of pointer-to-member_sc.
member_sc** pointers;
We'll need to assign some memory for this to point to:
cin >> num;
cin.ignore();
if (num == 0) {
// do something
return;
}
pointers = new member_sc[num];
luckily, using a pointer to an array is as easy as using an array, the only major difference being that you lose the size-of-array information -- all you have is the address, not the dimensions.
for (int i = 0; i < num; i++) {
in_mem(x);
q.pointers[i] = new member_sc(x);
q.n++;
}
I'm deliberately not providing you with a complete working example because this is obviously for a class.
You never initialize the memory that the point member refers to, yet then in statement q.point[q.n]=x; you attempt to use it.
Basically, after you read in the number of members, and before the for loop where you read in the individual members, you need to allocate an array of an appropriate number of member_sc objects and store it in q.point. Don't forget to free this memory when done using it.
Once you do that, you can also remove the member_sc &x argument from both in_SC and out_SC, as that will become unnecessary.
Finally, some validation of your input seems to be in place. Consider what will happen if the user enters a negative number, and you attempt to use that directly to determine the size of memory to allocate.
Here's a simple example showing how to use a dynamically allocated array of structures:
#include <iostream>
#include <string>
struct member_sc {
std::string name;
};
void test_array(int count)
{
if (count <= 0) {
return; // Error
}
// Allocate an array of appropriate size
member_sc* members = new member_sc[count];
if (members == nullptr) {
return; // Error
}
// ... fill in the individual array elements
for(int i(0); i < count; ++i) {
// ... read from input stream
// I'll just generate some names to keep it simple
members[i].name = "User A";
members[i].name[5] += i; // Change the last character, so we have different names
}
// Now let's try printing out the members...
for(int i(0); i < count; ++i) {
std::cout << i << ": " << members[i].name << "\n";
}
delete[] members;
}
int main(int argc, char** argv)
{
for(int count(1); count <= 10; ++count) {
std::cout << "Test count=" << count << "\n";
test_array(count);
std::cout << "\n";
}
return 0;
}
Example on Coliru
Of course, there are many other issues with this style of code, but I believe that's beside the point of this question. For example:
Instead of using bare pointers, it would be more appropriate to use some kind of a smart pointer.
Instead of a simple array, use some kind of collection, such as a vector.
Since you are asked to use an array of pointers, do so: replace
Member_sc members[10];
with
Member_sc* members[10];
Then fill out that array using dynamic memory allocation. As a matter of good form, at the end of the program remember to release the dynamic memory you have used.
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.
I am pretty weak in understanding and working with pointers. So, Please help me here.
My objective is to pass an array pointer's address to a function ,(i.e.) the address the pointer is pointing to, and update the values directly in the address using the '*' operator, in the function, to avoid any return values. Moreover, the length of this array has to be changed dynamically in the function to which it is passed. This is my attempt. If there's a better method to update the value of an variable, without having it returned from a function, please do mention that to help me.
But am getting errors, as I know I am doing it wrong, but still wanted to try with what I know, since I thought the best way to learn is to do and make as many mistakes as possible. Please help me here
This is the main function
int main()
{
double *trans;
int *rots;
readctrls(rots,trans);
for(int i=0;i<trans.size();i++)
{
cout<<trans[i]<<endl<<rots[i];
}
}
Here, am trying to pass the address of the pointer arrays to the function readctrls. then later, print its values. I haven't mentioned a size, cuz it will be determined later in the function.
The function is just to read numbers from a text file, line by line and store these numbers in these 2 arrays. The readctrls function is as follows.
void readctrls(int*& rots,double*& trans)
{
fstream inputs;
inputs.open("input_coods.txt");
int nol = 0,i = 0;
string line,temp,subtemptrans,subtemprots;
while(getline(inputs,line))
{
++nol;
}
cout<<nol<<endl;
inputs.close();
inputs.open("input_coods.txt");
string *lines = new (nothrow) string[nol];
trans = new double[nol];
rots = new int[nol];
for(int i = 0; i<nol ; i++)
{
getline(inputs,lines[i]);
temp = lines[i];
for(int j = 0; j<temp.length() ; j++)
{
if(temp.at(j) == ' ')
{
subtemptrans = temp.substr(0,j);
subtemprots = temp.substr(j+1,temp.length()-j);
trans[j] = ::atof(subtemptrans.c_str());
rots[j] = atoi(subtemprots.c_str());
}
}
}
inputs.close();
}
Thanks a lot for your help guys. I was able to understand a bit and changed the code and was able to compile now without errors. however, the value I read from file and load into the array, doesn't seem to get reflected back in the main. Am getting the correct values from the file when I print the array in the function, but am getting zeros, when I print in the main(). Please help me here.
These are the contents of the file
0.2 0
0.2 0
0.2 0
0.2 0
0.2 0
while print 'trans', which takes the first number every line, in the function, am getting the correct values. But while printing in the main function
0
0
0
0.2.
I changed the pointer to pointer reference while passing to function. Please check edit in the function code. Thanks in advance.
The declaration
void readctrls(int &rots,double &trans)
tells the compiler that rots and trans are references to a single value each. They are not pointers.
To make matters worse, you are actually trying to pass a pointer-to-pointer as arguments when calling this function.
You should change the declaration to actually take pointers:
void readctrls(int* rots, double* trans)
then change your call to not use the address-of operator (as those are already pointers):
readctrls(rots, trans);
Your code has several errors. Here are some of them:
double *trans = new double[];
int *rots = new int[]; //^^You need to give the size
for(int i=0;i<trans.size();i++)
{
cout<<*trans[i]<<endl<<*rots[i];
}
trans and rots are simply array of double and integers, you simply use trans[i] to print the i-th element. Dynamic arrays should be used similarly to static arrays. Take a look at this pointer and arrays for some basic understanding. Meanwhile, look at dynamic memory in C++ for some understanding on this point.
void readctrls(int &rots,double &trans);
//^^expects reference to int and double while you are not passing int and double from main
An array and a pointer can be thought about similarly as a way of referring to a range in memory. If you want to refer to a range of memory via pointers, then just pass the pointer to the function, ie
double pd* = new double[10];
fun(pd);
...
void fun(double* pd, int numDoubles)
{
do {
double d = magicDoubleGenerator();
*pd = d; // read as "the value that pd points to" or "contents of pd"
} while (++pd < pd + numDoubles);
}
Pointers are hard until one day you realize "Ahh! they just point at things!"
There are many errors ...
inputs.open("input_coods.txt"); // second argument is missing
check this fstream open
void readctrls(int &rots,double &trans)
change to
void readctrls(int* rots, double* trans) // this creates pointer rots trans
*trans = new double[nol]; // remove *
*rots = new int[nol]; // remove *
double *trans = new double[]; // not specified the size
int *rots = new int[]; // not specified the size
readctrls(&rots,&trans); // this means you passing address of pointer
trans.size() ; // this is c++ double is not a class
I am recommending you to study c++ from this site C++ Tutorial
I am stuck in this problem: how to resize, inside a function, a dynamically allocated array, which has been passed, to the function, by reference.
I tried this, along with countless variations on this very approach. Of course this is just an example, it should print "john" ten times, expanding an array passed by reference that originally had only size 1 ( ie only 1 name ).
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
int NumLast=-1;
int Surname(string *MyData)
{
for (int i=0; i<10 ; i++)
{
NumLast++;
string *Temp = new string[NumLast+1]; // temporary array
for (int jjj=0; jjj<NumLast; jjj++)
Temp[jjj]=MyData[jjj];
delete[] MyData;
MyData=Temp;
MyData[NumLast]="John";
}
return 0;
}
void main()
{
string *Data = new string[1]; // inizializza l'array
Surname(&*Data);
for (int iii=0; iii<10; iii++)
cout << Data[iii] << endl;
system("pause");
}
You have to pass by reference. You are passing by value. You are getting
&*Data = Data
The value of the address of what is pointed to Data = Data
Then you pass it by value to Surname. Anything Surname does to it won't affect Data in main.
int Surname(string *MyData) // This will take a copy of whatever you passed in to MyData
should be (The reference operator should be on the function definition.)
int Surname(string*& MyData)
^^
And the call will be
void main()
{
string *Data = new string[1];
Surname(Data); // The function will take a reference of data.
Buy may I ask why you are allocating in a loop?
Looks like std::vector is best solution for your case.
If you really need to reallocate manually, think about old school malloc(), free(), realloc() interface. Main thing to remember is to not intermix it with C++ new/delete interface despite usually new / delete is implemented using malloc() / free().
If you need array you should pass not array but pointer (or reference) to array (double pointer). In case of std::vector it is enough to pass reference to it.
Yet another argument to use reference to std::vector - in case of pointer to array caller should be notified somehow what is new array size.
I decided to try and go through your code line by line and point out some of the issues and highlight what's going on. I will start from your main function:
void main()
{
string *Data = new string[1]; // inizializza l'array
Surname(&*Data);
for (int iii=0; iii<10; iii++)
cout << Data[iii] << endl;
}
OK, so what this code does is allocate one string and save the pointer to it in a variable called Data.
Then it dereferences Data, thus, getting back a string and then gets the address of of that string (i.e. gets back the same thing as Data).
In other words this code:
Surname(&*Data);
does exactly the same as this code:
Surname(Data);
So, now let's take a look at Surname:
int Surname(string *MyData)
{
for (int i=0; i<10 ; i++)
{
NumLast++;
string *Temp = new string[NumLast+1]; // temporary array
for (int jjj=0; jjj<NumLast; jjj++)
Temp[jjj]=MyData[jjj];
delete[] MyData;
MyData=Temp;
MyData[NumLast]="John";
}
return 0;
}
This weird function accepts a pointer to a string and loops 10 times doing stuff. Let's see what happens in the first iteration of the loop...
First, it increments NumLast (which goes from -1 to 0). Then it allocate an array of strings, of length NumLast + 1 (i.e. of length 1). So far so good.
Now you might think the function would enter the for loop. But it won't: remember that at that point NumLast and jjj are both 0 and therefore, jjj < NumLast is false.
The code will then delete[] MyData (that is, it will delete whatever MyData points to), set MyData to point to the temporary array allocated earlier in the loop, and then set the first element (at index 0) to the string "John".
In the second iteration of the loop, the function again increments NumLast (which will now be 1). It will again allocate an array of strings, this time of length 2.
The loop will be entered this time. It will copy the first entry from MyData into the first entry from Temp. And it will exit.
Again, MyData will be deleted, and the pointer will be made to point to the newly allocated array.
Rinse. Lather. Repeat.
Finally, the function will exit. We go back to main, which will now execute this bit of code:
for (int iii=0; iii<10; iii++)
cout << Data[iii] << endl;
Wait a second though. Where does Data point to? Well... it points to data that has already been deleted long ago. Why?
Well, Surname received a copy of the Data pointer. When it called delete[] MyData it deleted the array that it MyData pointed to (which was the same array that Data pointed to). When Surname later did MyData=Temp all that changed was MyData (the copy of the pointer local to the function Surname) and Data (the pointer in main) was unaffected and continued to point to the now deleted memory.
Others have explained how you can get the effect you want and I won't repeat what they wrote. But I would urge you to sit down and think about what Surname does and how the code is unclear and confusing and how it can be rewritten so that it's easier to understand and less prone to error.
For those who in the future will need the solution to the same problem here is the amended code:
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
int NumLast=-1;
int Surname(string *&MyData)
{
for (int i=0; i<10 ; i++)
{
NumLast++;
string *Temp = new string[NumLast+1];
for (int jjj=0; jjj<NumLast; jjj++)
Temp[jjj]=MyData[jjj];
delete[] MyData;
MyData=Temp;
MyData[NumLast]="franci";
}
return 0;
}
void main()
{
string *Data = new string[1]; // inizializza l'array
Surname(Data);
for (int iii=0; iii<10; iii++)
cout << Data[iii] << endl;
system("pause");
}