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
Related
I am trying to make a void function where it changes the pointer that I pass. The code is throwing an exception on one of the lines and i'm not sure why. Could it be I cannot pass the arrays as pointers then implement math on it? I thought I deallocated the pointers to fix it but this seemed to not work.
Void function:
#include <iostream>
using namespace std;
void* func2(int one, double *value1[], int two, double *value2[], double *final1) {
double testval;
double finalval = 0;
//double *final1;
double final = 0;
for (int i = 1; i < one; i++) {
for (int j = 1; j < two; j++) {
testval = *value1[i] * *value2[j]; //exception thrown (works up to this point)
finalval = testval + finalval;
}
final = finalval + final;
}
*final1 = final;
return 0;
}
Main Function:
int main(){
double *array1 = new double[input1];
double *array2 = new double[input2];
//for loop that takes user input and fills in array1 and array2 with size and a list of values
...
double testval2;
func2(input1, &array1, input2, &array2, &testval2);
cout << testval2 << endl;
delete[] array1;
delete[] array2;
return 0;
I am relatively new to pointers, so my apologies if the code is a little illiterate.
It looks like you want to pass two 1D arrays to func2().
One way to do that is remove the [] from the function signature as
(int one, double *value1, int two, double *value2, double *final1)
Within the function, change *value1[i] to value1[i], and similarly for value2. And remove the & when calling the function from the main().
A couple other thoughts:
I'm not sure how an exception could throw from your code. But *value1[i] is definitely an invalid memory access, so what you may have seen is a segmentation fault message. A helpful tool to troubleshoot these kinds of errors is AddressSanitizer, enabled in clang or gcc by compiling with -fsanitize=address, or if you are using Xcode, there is an option for it. Another great tool is valgrind.
Manually allocating dynamic arrays is a pretty C-like way of using C++. In C++, it is idiomatic to create the arrays as std::vector objects, which under the hood works the same way (it also allocates a dynamic array) but has a more convenient interface. Particularly the vector cleans itself up automatically, so no need to call delete[], and the vector knows its own size, so no need to pass the size around as a separate parameter as with dynamic arrays.
Edit: Here is a note to clarify why the original code manages to compile but fails at runtime.
In the function signature, the combo of both * and [] on double *value1[] makes value1 a pointer to a pointer to double, equivalent to double **value1. In main(), array1 is a double*. When calling the function, &array1 takes the address of that double*, obtaining a double**. So the type matches and the code compiles.
The code fails at runtime on *value1[i]. value1 is a pointer to pointer to doubles, where the inner pointer points to the dynamic array. So what was intended is (*value1)[i] to first dereference the outer pointer, then subscript into the dynamic array. However, in C++, subscripting (a[]) has operator precedence over dereferencing (*a), so it is read in backward order as *(value1[i]). Subscripting the outer pointer value1[i] is invalid for nonzero i, reading memory from somewhere in the stack and arbitrarily interpreting it as a double*. Then the surrounding *( ) attempts to dereference this busted pointer. The machine's memory protection catches this, and the OS sends a "SIGSEGV" signal or similar to the program to kill it.
I want to make a function which takes an existing 9x9 empty array of integers, and inserts values taken from a file (so the function also gets the file name as input). But I cant really figure out how to do this properly, even though I've tried quite a few different methods. Basically, here is what I do:
int board = new int[9][9] //The empty array
int addToArray(int *board, string filename) {
/* Code to insert values in each field is tested and works so
I will just show a quick example. The below is NOT the full code */
int someValue = 5;
board[0][0] = someValue;
/* Return a value depending on whether or not it succeeds. The variable 'succes'
is defined in the full code */
if (succes) {
return 0;
} else {
return -1;
}
}
This is a very reduced example, compared to the actual code, but it is overall function of passing a pointer to a an array into some function, and have that function modifying the array, that I want. Can anyone tell me how to do this?
In case anyone ever ends reading the question, I used method number 3 from Johnny's link. I copy pasted the code and added some comments, for convenience...
// Make an empty, and un-sized, array
int **array;
// Make the arrays 9 long
array = new int *[9];
// For each of the 9 arrays, make a new array of length 9, resulting in a 9x9 array.
for(int i = 0; i < 9; i++)
array[i] = new int[9];
// The function to modify the array
void addToArray(int **a)
{
// Function code. Note that ** is not used when calling array[][] in here.
}
passFunc(array);
It should be simply
int **board
in the function arguments.
The simple rule is that *name = name[ ], so as many [ ] you have in the array, you need to have as many * in the parameters.
I have a method which fills the array with integers:
void fill(int* a[], int dim1, int dim2)
{
int intinArray = 0;
for(int i=0;i<dim1;i++)
{
for(int j=0;j<dim2;j++)
{
cin >> intinArray;
a[i][j] = intinArray;
}
}
}
If I declare array in method main() like this:
int** tab;
fill(tab,3,3);
It crashes when I put the first integer in cin. Why? If there's a problem with this line:
a[i][j] = intinArray;
how should I change it?
The fundamental thing wrong with your code is that you declared pointers, but nowhere do you initialize the pointers to point somewhere. You treat the pointer as if it is a regular old 2 dimensional array of integer. So if it's as easy as that, why use pointers?
Given that this is a fundamental in pointer usage and you plainly aren't doing that, the solution is to review working code that uses pointer.
int main()
{
int *p; // uninitialized -- points to who-knows-where
*p = 10; // this is undefined behavior and may crash
}
Take that code and understand why it also may crash. That pointer points to "we don't know", and then you're assigning 10 to a location that is unknown to you, me, and everyone else reading this answer. See the problem? To fix it, you have to initialize the pointer to point somewhere valid, then you can dereference it and assign to it without error.
int main()
{
int *p; // uninitialized -- points to who-knows-where
int x = 20;
p = &x; // this is now ok, since p points to x
*p = 20; // now x changes to 20
}
Your problem is in this code
int** tab; // <- this one
fill(tab,3,3);
You declared a pointer, and are using it under the assumption that it is pointing to allocated memory. (I guess a source of confusion is that with C++ objects this isn't really the case)
A pointer is a pointer - it points to a location in memory. There's no guarantee that the value it points to is valid unless you explicitly make sure it is yourself.
Read PaulMcKenzie's answer for more about pointers.
Try
int tab[x][y] = {{0}};
fill(tab,3,3);
where x and y define your 2D array's width and height. You're going to have to handle bounds checking for your application.
Note that changing {{0}} to a non zero number will not initialize everything to that number.
I'm studying for an exam in c++ and i have a question on the past papers
"Write a function in C++ that takes as input an array of doubles and the length of the array, and returns an array twice the length. The first half of the returned array should contain a copy of the contents of the original array. The second half of the returned array should contain the contents of the original array in reverse order."
"The function should have the following prototype: double *copy_and_reverse(double *a, int length);"
since im obviously new to c++ i got stuck in my solution, my code so far is:
double *copy_and_reverse(double *a, int length){
double *b[length*2];
for(int i=0;i<length;i++){
*b[i]=a[i];
}
for(int i=length;i<length*2;i++){
int w=length-1;
*b[i]=a[w];
w--;
}
return *b;
}
int main()
{
double nums[2]={1.23,5.364};
double *pnums=nums;
*pnums=*copy_and_reverse(pnums, 2);
I think i got the core of the method correct but i'm just stuck in the syntax of using pointers, any help is appreciated and if possible a reasoning behind it so i can learn for the exam.
You've got a few problems with this code.
First
double *b[length*2];
Here you're declaring an array of pointers to doubles. The array is of size length * 2, however, none of the pointers in this array are valid yet. This is probably not what you intended to do.
You want an array of doubles, of size length * 2. You can't return an array in C++ but you can return a pointer to some memory that contains an array of doubles.
Let's start by allocating enough memory for all those doubles
double *b= new double[length * 2];
In your first for loop you can treat result as an array
for(int i=0;i<length;i++){
b[i]=a[i];
}
Here you're copying the values from a for each index i to be at the same index. I'll let you figure out how to fill in the reverse part for the second half of the array. You're on the right track, however you might want to think about doing it all in one loop ;)
Your return statement just needs to return your variable b, as it's already a double *.
return b;
An important thing to remember is that you're allocating memory in this function with new. You are responsible for deleting this when you're done with it. Also, when you allocate using new and [] you have to delete using [] as well.
delete [] b;
you can call your function just by de-referencing the first item in your array.
int main() {
double nums[2]={1.23,5.364};
double *pnums = copy_and_reverse(&pnums[0], 2);//don't forget to clean up pnums afterwards!
There are quite many errors in your code. The major one is that you need to allocate new array of doubles. And return that array. I'd suggest compare this with your version line by line:
double *copy_and_reverse(double *a, int length){
double *result = new double[length*2];
for(int i=0;i<length;i++) {
result[i]=a[i];
}
int r = length*2;
for(int i=0; i < length;i++){
result[--r]=a[i];
}
return result;
}
And your main() shall look like:
int main()
{
double nums[2]={1.23,5.364};
double *pnums = copy_and_reverse(nums, 2);
...
delete[] pnums;
}
Ok, there are at least two problems with this:
double *b[length*2];
The first problem is that you are declaring a local array (of pointers), which you will then try to return:
return *b;
(You're returning the wrong thing here, too, but that's another story) You can't return a pointer to a locally-allocated thing because as soon as the function returns, the locally-allocated thing will be destroyed. Instead, given that you must return a pointer to the first element of an array, you have to dynamically allocate that thing using new.
Second, you can't declare an array like this using a length which s only known at runtime. But this problem will be obviated when you use new to dynamically allocate the array.
I would normally say that you shouldn't be doing any of this at all, and just use a std::vector -- but clearly a requirement of this assignment is to use a dynamically allocated C-style array. (Which I take great issue with your professor on.)
I would also say that the prototype:
double *copy_and_reverse(double *a, int length);
doesn't declare a function which takes an array, as your professor incorrectly asserts, but a function which takes a pointer to a double. That that pointer is the first element in an array doesn't magically make a an array. In short: an array and a pointer are not the same thing.
These last two observations are just for your benefit.
I assume this is not your homework and I am trying to help you out.
Look at the comment of code.
double *copy_and_reverse(double *a, int length)
{
double * b = new double[length*2]; //create a new array using new[]
for(int i=0;i<length;i++){
b[i]=a[i]; //addressing element with []
}
int w=length-1; //I assume this is what you want
for(int i=length;i<length*2;i++){
b[i]=a[w];
w--;
}
return b;
}
int main()
{
double nums[2]={1.23,5.364};
double *pnums = copy_and_reverse(nums, 2);
delete[] pnums;
}
Also noted the memory is allocated in the function, so in the main, you want to delete it by using [].
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 )