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.
Related
Please let me preface this question by stating that I am an absolute C++ novice and I'm only well-versed in R. Also, I'm working within Xcode.
Let's say I create an int object called 'answers'. Initially, it is set as int. After I assign values to answers[0], answers[1], etc., is it still int or has it become something else because I added multiple values?
int answers[4];
answers[0] = 8;
answers[1] = 6;
answers[2] = 7;
answers[3] = 5;
Let's say I want to pass 'answers' to a user-defined function (see code below). My problem is that in the line, cout<<"The first value you entered...", I get an error saying that 'Subscripted value is not an array, pointer, or vector". Then, in the line, showAnswers(answers);, I get the error 'No matching function for call to 'showAnswers''. What am I doing wrong here? My first guess is that 'answers' is no longer an int, but I don't know what it would be.
void playGame(int input){
cout << "The first value you entered was: " << input[0];
}
int main() {
int answers[4];
answers[0] = 8;
answers[1] = 6;
answers[2] = 7;
answers[3] = 5;
showAnswers(answers);
}
Two things to consider:
First, as said in a comment by Igor, answers is not an int but rather an array of 4 int values.
Second, the parameter for playGame is an int not an array of int values, so adding the subscript ([0]) is not valid.
Either you must make a separate call to playGame for each value in your array, or modify the function to accept an array reference, or a pointer to your array.
In the grand scheme of things, neither of those solutions is optimal for larger programs, as they can be prone to problems as described here in the Cpp Core Guidelines: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#a-nameri-arrayai13-do-not-pass-an-array-as-a-single-pointer
I have a function which should modify an array (of floats) in the original parent function. I am using the following code:
void sortFunction(Word**words, int wordCount){ //to sure if two * are correct (pointer to an array..?)
int i = 0;
for(i=0;i<wordCount-1;i++){
Word first = *words[i]; //values fine
Word second = *words[i+1]; //weird values, causes segfault
if(first.data[0] > second.data[0]){
//do stuff
}
}
}
int main(int argc, char ** argv){
Word* words = NULL;
int wordsCount = ...
//filling the array in a loop and using realloc for memory allocation
//Here, the array is filled correctly (verified)
sortFunction(&words, wordsCount);
}
Where Word is a typedef struct and Word.data is the (dynamic) float array. When checking in the parent function, the array is allocated and the values set correctly.
I have tried with about 10 elements in the array, but always only the first ([0]) element is fine in the sortFunction(), second and all others are messed up. I also have an int propery in the struct, and when I try to print it for the second element, I get something over 1 billion.
I assume I am not passing the array correctly - I use the following code (just a sample) to pass regular variables, so I tried to modify it for an array, but apparently, not correctly. What is the right way to do this for an array?
void foo(int*var){
*var=8;
}
int main(){
int var = 5;
changeVar(&var);
}
Thanks in advance for any tips!
Postfix [] has higher precedence than unary *, so *words[i] is parsed as *(words[i]), which isn't what you want.
You need to dereference the words pointer before applying the subscript, so you need to explicitly group the * operator with words using parentheses:
Word first = (*words)[i];
Word second = (*words)[i + 1];
First, you do not need to pass **, just one is enough, because you will be passing the address of your array anyway:
void sortFunction(Word* words, int wordCount)
and call it as:
sortFunction(words, wordsCount);
Second, the Undefined behavior originates in the following statement:
Word first = *words[i]; Word second = *words[i+1];
It should have been (*words)[i] but still, you are copying structs, so your dynamic data array is not copied correctly. avoid this useless copy, and use this instead, AFTER changing the protoype of sortFunction:
Word* first = &words[i];
Word* second = &words[i+1];
if(first->data[0] > second->data[0])
p.s: This does not guarantee that the rest of your code is correct, just comments of the parts you showed of the code.
I have an Eigen matrix to be converted to a C array. I can replicate the issue with the following example.
#include <iostream>
#include <Eigen/Core>
int *test()
{
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
// just to check
arr(4)=3;
arr(5)=19;
return arr.data();
}
int main()
{
int *c_arr;
c_arr = test();
for (int i=0; i<6;++i)
{
std::cout << c_arr[i] << std::endl;
}
return 0;
}
Output:
0
0
1
1
3
19
Now if I print the converted C array values from within the test function the values are correct. However if I print the values from main (as shown above) the first two indices are always garbage. So I am wondering what is happening in the function call? I have tried this with different Eigen matrices (types, sizes) and I get the same result.
I'll start by saying I'm not 100% familiar with the Eigen library (just downloaded it to look at it out of curiosity) and it's documentation is a bit lacking but your problem is a fundamental C problem that can be remedied a few ways.
First we'll start by explaining what's happening in your code to give garbage values:
int *test()
{
/* create an auto scoped variable on the stack;
this variable is only "visible" to this function
and any references to it or it's underlying data
outside the scope of this function will result
in "undefined behaviour" */
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
arr(4)=3;
arr(5)=19;
/* arr.data() is defined as returning a pointer to the scalar underlying type (or
a C-style array in other words). Regardless of the type being returned, it is pointer based
and you are returning a pointer to a location in memory, not the actual data being held in
the memory. */
return arr.data();
} /* the variable arr is destroyed here since we left function scope and the return value (the pointer location)
is put in the return register and "program flow" is returned back to the main function where the pointer being
returned now points to "invalid" memory */
int main()
{
int *c_arr; // create a pointer type that can reference int types
c_arr = test(); // point it to the result of the test function (see notes above)
/* c_arr now points to a memory location returned from test, but since the
arr variable no longer exists here, when you go through and print the values pointed
to at those memory locations you will get what is at those locations and could be "anything"
except a valid reference to the original arr variable and it's underlying data. */
for (int i=0; i<6;++i)
{
std::cout << c_arr[i] << std::endl;
}
return 0;
}
So that's the why, as for how to fix it there are a couple of ways to go about your problem; one is to pass the return array in as a variable in to your test function (e.g. void test(int*& val)), you could then choose to allocate new memory to the variable in the test function, or assume the user has already done so, and must also assume the user will clean up after themselves and call delete[] (not just delete since you're operating on arrays of data).
But this has many caveats of needing to know how much space to allocate and being sure to deallocate when done. I'm not sure why you specifically need a C-style array but since you're using C++, it might be more prudent if you use some of the STL and container functions available to you to help you out, example:
#include <iostream>
#include <vector>
#include <Eigen/Core>
std::vector<int> test()
{
Eigen::MatrixXi arr = Eigen::MatrixXi::Ones(6,1);
arr(4)=3;
arr(5)=19;
// we need the size so we know how big of a container to allocate
std::size_t sz = arr.innerSize() * arr.outerSize();
std::vector<int> ret(sz);
// get a temporary C array pointer so we can reference the data
int* tmp = arr.data();
// copy from tmp[0] to tmp[sz] and insert the data into the first element of ret
std::copy(tmp, tmp+sz, ret.begin());
// return the (copied) data
return ret;
}
int main()
{
std::vector<int> c_arr = test();
// c_arr now points to valid data it holds and can be iterated on
for (std::size_t i = 0; i < c_arr.size(); ++i) {
std::cout << c_arr[i] << std::endl;
}
// if you need a C-style array from here, you can easily copy the data
// from the vector to your C-array
return 0;
}
I looked into using the cast() function of the class, but could not quite figure out the syntax to make it less painful than just copying it the above way since it looks like you'd have to call the cast function to a differnt Eigen type and then cast again from there, but know there is a cast function and other methods to get the underlying data of the MatrixX classes if you need access to it.
I hope that can help.
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
//Prints out a given array
template <typename T>
void print(T t)
{
for(int i = 0; i < t.size(); i++)
{
cout << t[i] << " ";
}
cout << endl;
}
I have an idea but it includes passing the size of the array. Is it possible to avoid this?
*Update
Thanks for all of the answers/ideas but this problem is getting way deeper than my snorkeler can handle. I wanted to rewrite my C++ code in C because it was horribly written and slow. I see now that I have an opportunity to make it even worse in C. I'll rewrite it from the ground up in Python(performance be damned). Thanks again
If you don't have ELEMENTS, it's
#define ELEMENTS(a) (sizeof(a)/sizeof(*a))
Then,
#define print_array(a, specifier) print_array_impl(a, specifier, ELEMENTS(a), sizeof(*a))
void print_array_impl(void* a, char* specifier, size_t asize, size_t elsize)
{
for(int i = 0; i < asize; i++)
{
// corrected based on comment -- unfortunately, not as general
if (strcmp(specifier, "%d") == 0)
printf(specifier, ((int*)a)[i]);
// else if ... // check other specifiers
printf(" ");
}
printf("\n");
}
Use like this
print_array(a, "%d") // if a is a int[]
and, a needs to be an array name, not a pointer (or else ELEMENTS won't work)
You cannot know what is the size of an array without passing the size of that array (except operating with sizeof in static arrays). This is because the a pointer to a block of memory will only point to the base of the block of memory, from which you can know where the array/block of memory starts, but as there is no end defined you cannot determine where it will end.
You either need to set your own length per array and preserve it, and use it with the array like as described:
You can make a new type like:
struct _my_array {
typename arr[MAX];
int n;
} my_array;
OR
struct _my_array {
typename *arr;
int n;
} my_array;
In this case you need to allocate the a block of memory dynamically with new or malloc , and when finished free the memory with delete or free (respectively).
Or you can simply pass the array number of elements through the function.
Another way is to use a special terminator value of your array type which if encountered will be determined as the end of the array. In this case you need not preserve the size. For example a string is '\0' terminated, so all the string functions know that when a '\0' character is encounter in the char array it will consider that the string has end.
UPDATE
Because this is a generic function and the array can be of any type, one thing which you can do is like this:
struct _my_generic_arr {
void *arr;
int n;
int type;
} my_generic_arr;
When populating this array you can use any type. To identify which type, pass an identified in the type component. Each unique value will determine which type does the arr pointer actually points to (was actually the intended type to be pointed). The n will define the length. Now, depending on different values of type make a switch - case or an if - else ladder or nest, and process the array as you need.
It is impossible in c to track the size of an array in other block,,
It would be a better option to pass the size of the array along..
The other option would be to declare a global variable that has the size and using that variable inside the function
Eg,,
int size=<some value>
void main()
{
int arr[<same value>];
}
void print(T t)
{
for(int i = 0; i < size; i++)
{
printf("%d ",t[i]) //assuming T as int
}
printf("\n");
}
In C, you would need to pass two additional parameters: the size of the array (as you mentioned), and some way of indicating how to convert t[i] into a string. To convert t[i] to a string, you could create a custom switch statement to decode possible types, pass a pointer to a function that will return the string pointer, or you could pass the printf format specifier (e.g. "%d" for integer).
The problem is larger than you think. If you have an array of size 12, how do you know what data is held in that array? It could be 3 char*'s (on 32 bit system), 3 int32_t's, or even 12 chars. You have no way of knowing how to interpret the data. The best you could do is to implement your own version of a v-table and putting a print or toString function into it.
typedef struct {
void *array;
size_t length;
int element_width;
printer_t to_string;
} container;
printer_t is a type that describes a function pointer that takes an element pointer and returns a string (or prints it, if you don't want to free the string). This is almost never worth doing in C. That doesn't mean it can't be done. I would emphasize, though, that none of this is intended to imply that it should be done.
The function itself would look something like this:
void print(container *thing)
{
size_t offset;
int width;
char *stringified;
width = thing->element_width;
for (offset = 0; offset * width < thing->length; offset += width)
{
stringified = thing->to_string(thing->array + offset);
printf("%s ", stringified);
free(stringified);
}
}
What this does is essentially turn a struct into a faux class with a function pointer for a method. You could be more object-oriented and put the method in the type being printed and make it an array of those instead. Either way, it's not a good idea. C is for writing C. If you try to write in a different language, you'll end up with all sorts of terrible stuff like this.