string** flowFile() {
string line;
string word[8];
int i=0;
static string flow[23][2];
ifstream myfile ("test.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
strSplit(line,word);
flow[i][0]=word[1];
flow[i++][1]=word[2];
}
myfile.close();
}
else cout << "Unable to open file";
return flow;
}
int main()
{
string **fl=flowFile();
}
I'm getting this error:
error: cannot convert ‘std::string (*)[2] {aka std::basic_string<char> (*)[2]}’
to ‘std::string** {aka std::basic_string<char>**}’
in return
What is wrong with my code?
string flow[23][2] and string ** are two different incompatible types. One cannot convert to another implicitly. Thats all. The solution is to make them compatible, by making the later string [23][2], return reference and accept reference, but that would still be a bad solution, because you're still working with raw arrays.
A good solution is to use std::vector and std::string. Maybe, you need std::pair also, or std::array.
Here is one possible solution:
#include <vector>
#include <array>
#include <string>
//C++11 style typedef
using flow_data_t = std::vector<std::array<std::string,2>>;
//reimplementation of your function
flow_data_t flowFile()
{
std::string line;
std::string word[8];
int i=0;
flow_data_t flow;
std::ifstream myfile ("test.txt");
if ( !myfile )
cout << "Unable to open file";
while ( std::getline (myfile,line) )
{
strSplit(line,word);
flow.push_back({word[0], word[1]});
}
return flow;
}
int main()
{
flow_data_t data=flowFile();
for(auto const & row : data)
for(auto const & col : row)
//work!
}
Hope that helps.
You cannot return array from a function even though you can return a pointer and let your array decay to a pointer: Array Decay
However 2D array can decay to neither T* nor T** because of the memory layout of the array is different from "2D pointer array" (it is actually more like flattened), and you cannot return array from function. However in C++ you can return array reference Full Code:
//This does not work
//typedef string * string2d[2];
//typedef string *(&string2d)[2];
typedef string (&string2d)[23][2];
string2d flowFile() {
static string flow[23][2];
return flow;
}
Array reference would even preserve the information of how big each row and columns are and no array decaying happen.
Of course, a more suggested "C++ way" to do this is using std::vector (as always).
In C++, arrays have type std::vector. You should use these, not low-level builtin arrays declared with [].
In C++, string [23] is sometimes interchangeable with string*, but string[23][2] is never interchangeable with string**. That's one reason you should not use builtin arrays.
In C++, you cannot return a local builtin array variable. It will compile but then your program will probably crash. This is another reason you should not use builtin arrays. (Returning a static array should be OK though).
There are many more reasons.
There is nothing wrong with returning a pointer to a static variable. It's just that the return type must be declared properly. It kind of makes sense if you try to reproduce what the declarations mean, and what the compiler accordingly tries to do. Consider the declaration static string flow[23][2];. It declares 23 rows of strings, each with 2 elements. It helps if you look at it as a one-dimensional array. It just so happens that the array elements are arrays, but that's not so important right now (but we'll come back to it). From this perspective the array has just 23 elements, and each element has the size of 2 strings. Like with all arrays, the elements (here: arrys of 2 strings) are simply lined up in memory.
Like any array, flow will in most contexts decay to a pointer to its first element. Incrementing that pointer will point to the next element, i.e the second row. Numerically the compiler must add 2*sizeof(string) to the address of flow in order to compute the address of flow's next element, which would be flow[1]. (It comes directly behind flow[0]. No magic here.)
Now if you declare string **flowpp, flowpp is a pointer already, no need to decay. If we think it is pointing to the first element in an array, what type would the elements have? Sure enough: plain pointers. Incrementing flowpp would let it point to the next element. My pointers are 4 bytes large, so that numerically adding just 4 to flowpp would be enough to access flowpp's next element. Compared to what needs to be added to flow (remember, 2*sizeof(string)), that's completely different. The compiler computes the offsets of elements depending of what the pointers point to! Which is very different in the two cases.
So what can your function return? What does flow decay to when you return it? It decays to a pointer to its first element. The elements are arrays of two strings. It must be string xxx[2], with xxx being a pointer: hence string (*p)[2]. If the pointer is actually returned by a function, we have a function call instead of plain p, so it's (*f())[2].
Here is a complete example:
#include<iostream>
using namespace std;
const int numFlowElems = 3, numArrElems = 2;
/** #return a pointer to the first element of a static array
of string[numArrElems]s.
*/
string (*flowFile())[numArrElems]
{ // init so that we see something below.
static string flow[numFlowElems][numArrElems]
= {{"1","2"},
{"3","4"},
{"5","6"}
};
// your function code ...
return flow;
}
int main()
{
// array decays to ptr, like usual. Ptr elems are string[numArrElems].
// ptrToArr is a pointer to arrays of two strings.
string (*ptrToArr)[numArrElems] = flowFile();
for( int flowInd= 0; flowInd<numFlowElems; ++flowInd )
{
for(int strInd = 0; strInd<numArrElems; ++strInd)
{
cout << ptrToArr[flowInd][strInd] << ' ';
}
cout << endl;
}
return 0;
}
How do you parse string (*flowFile())[numArrElems]? I needed two attempts to get the declaration right, if that's any consolation. The key is that in C and C++ (not in C#, mind you!) a declaration has the shape of an expression.
You can do it from the inside to the outside: flowFile() is a function. The result is dereferenced because the function call has higher precedence than the star: *flowFile() is the dereferenced result. Apparently that result is an array of size numArrElems, with elements which are strings.
You can do it outside in: The result of (*flowFile())[numArrElems] is declared as a string. (*flowFile()) is an array of strings with numArrElems elements. Apparently flowFile() must be dereferenced to obtain that array so that flowfile is a function which returns a pointer to an array of numArrElems strings. That's true! It returns the first element of flow, which is exactly an array of strings.
Vectors of vectors might indeed be easier; if you want to retain the semantics you should pass references, as others mentioned: After all, all functions in your original program will operate on the same static array. If you pass vectors by value that will not be the case any longer. But then, that may actually be beneficial.
Related
Given to functions void main() and void hello(byte* a[4]). Main function has an array of four bytes. The array's reference needs to be passed to the function hello for manipulation. I would expect the right syntax to be:
void hello(byte* a[4]){
// Manipulate array
a[0] = a[0]+1;
}
void main(){
byte stuff[4] = {0,0,0,0};
hello(&stuff);
// hopefully stuff is now equal {1,0,0,0}
}
Alternatively I see others using this form of decaration:
void hello(byte (&a)[4])
Is this the right way to do it?
There are many different options here depending on what you want to do here.
If you have a raw array of byte objects, you can pass it into a function like this:
void hello(byte arr[]) {
// Do something with arr
}
int main() {
byte arr[4];
hello(arr);
}
The mechanism by which the array is passed into the function (a pointer to the first element of the array is passed to the function) functions similarly to pass-by-reference: any changes you make to arr in hello will stick in main even though you didn't explicitly pass in a reference to it. However, the hello function won't check whether the array has size four or not - it'll take in as input an array of any number of bytes.
You can also write
void hello(byte (&arr)[4]) {
// ...
}
int main() {
byte arr[4];
hello(arr);
}
The syntax byte (&arr)[4] means "a reference to an array of four bytes." This explicitly passes the array by reference into hello, and it will check the size of the array to make sure it's correct. However, this is very unusual syntax and rarely seen in practice.
But perhaps the best idea is to not use raw arrays and to use std::array instead:
void hello(std::array<byte, 4>& arr) {
// Do something with arr
}
int main() {
std::array<byte, 4> arr;
hello(arr);
}
Now, there's no weirdnesses about strange parentheses in the syntax for arrays of bytes and there's no worries about size checking. Everything is handled properly because std::array is an object type that has all the advantages of regular object types. I'd recommend going with this last approach above all the other ones.
Arrays are already passed by pointer.
So this:
int a(int array[]) {
}
Is the same as doing this:
int a(int * array) {
}
Doing this:
void hello(byte (&a)[4])
only allows arrays with a length of 4 to be passed in.
byte* a[4] is an array of four pointers to byte, except in a parameter list.
In a parameter list, it is a pointer to a pointer to a byte – i.e. it is equivalent to byte**.
byte (*a)[4] is a pointer to a four-element array.
byte (&a)[4] is a reference to a four-element array.
In your case, &stuff is a pointer to a four-element array, so your parameter should be byte (*a)[4].
Hoping for a little C++ assistance - I'm very new to the topic. I'm attempting to dynamically create an array based on user input with a pointer, then pass the array to a function. But the pointer (and thus array) pass feels a little wrong because there is no dereferencing that occurs.
During/after passing, do we just treat the pointer as if it were any normally declared-and-passed array, without the need to dereference (*) anything? Or am I applying this incorrectly?
Pseudocode follows:
#include<iostream>
using namespace std;
void arrayFunc(int [], int); // << Note no indication of pointer pass
int main()
{
int *arrayPtr = 0; // Array pointer
int arrayElem = 0; // Number of elements in array
cout << "\nPlease enter the number of elements: ";
cin >> arrayElem;
arrayPtr = new int[arrayElem]; // Dynamically create the new array
arrayFunc(arrayPtr, arrayElem); // << Note no dereferencing or other indication of pointer
return 0;
}
void arrayFunc(int array[], int arrayElem) // << Same here - now it's just a plain old array
{
// All the functiony-bits go here, referencing array without the need to dereference
}
[EDIT] While the above code works, the following includes the fixes determined in the discussion below:
#include<iostream>
using namespace std;
void arrayFunc(int*, int); // Changed to pointer pass instead of []
int main()
{
int *arrayPtr = 0; // Array pointer
int arrayElem = 0; // Number of elements in array
cout << "\nPlease enter the number of elements: ";
cin >> arrayElem;
arrayPtr = new int[arrayElem]; // Dynamically create the new array
arrayFunc(arrayPtr, arrayElem);
return 0;
}
void arrayFunc(int* array, int arrayElem) // Passing a pointer now instead of []
{
// All the functiony-bits go here, referencing array without the need to dereference
}
You should pass the pointer in your function, because it describes the situation accurately i.e. you are passing a dynamically allocated memory. arrayPtr is essentially a pointer to the first element of the array. As a result, you do not need to worry about dereferencing it.
Change the function signature to:
void arrayFunc(int*, int);
Your attempt is correct. You are passing the array pointer by value. You can then dereference it as normal within arrayFunc
C is designed to pretend a pointer and an array are the mostly same thing. Lots of simple uses are easier because of that. But the concept gets much more confusing when you think about a pointer to an array. It feels like it shouldn't be the same thing as a pointer to the first element of that array, but in the common methods for allocating memory and using pointers, a pointer to an array really is just a pointer to the first element of the array.
I find it best to think of "pointer to first element of array of" as the normal meaning of * in C. The special case of pointing to a scalar object is effectively treating the scalar as the first (and only) element of an array of length 1.
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 declare the following array:
char* array [2] = { "One", "Two"};
I pass this array to a function. How can I find the length of this array in the function?
You can't find the length of an array after you pass it to a function without extra effort. You'll need to:
Use a container that stores the size, such as vector (recommended).
Pass the size along with it. This will probably require the least modification to your existing code and be the quickest fix.
Use a sentinel value, like C strings do1. This makes finding the length of the array a linear time operation and if you forget the sentinel value your program will likely crash. This is the worst way to do it for most situations.
Use templating to deduct the size of the array as you pass it. You can read about it here: How does this Array Size Template Work?
1 In case you were wondering, most people regret the fact that C strings work this way.
When you pass an array there is NOT an easy way to determine the size within the function.
You can either pass the array size as a parameter
or
use std::vector<std::string>
If you are feeling particularly adventurous you can use some advanced template techniques
In a nutshell it looks something like
template <typename T, size_t N>
void YourFunction( T (&array)[N] )
{
size_t myarraysize = N;
}
C is doing some trickery behind your back.
void foo(int array[]) {
/* ... */
}
void bar(int *array) {
/* ... */
}
Both of these are identical:
6.3.2.1.3: Except when it is the operand of the sizeof operator or the unary & operator,
or is a string literal used to initialize an array, an expression that has type
‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’
that points to the initial element of the array object and is not an lvalue. If
the array object has register storage class, the behavior is undefined.
As a result, you don't know, inside foo() or bar(), if you were
called with an array, a portion of an array, or a pointer to a single
integer:
int a[10];
int b[10];
int c;
foo(a);
foo(&b[1]);
foo(&c);
Some people like to write their functions like: void foo(int *array)
just to remind themselves that they weren't really passed an array,
but rather a pointer to an integer and there may or may not be more
integers elsewhere nearby. Some people like to write their functions
like: void foo(int array[]), to better remind themselves of what the
function expects to be passed to it.
Regardless of which way you like to do it, if you want to know how long
your array is, you've got a few options:
Pass along a length paramenter too. (Think int main(int argc, char
*argv)).
Design your array so every element is non-NULL, except the last
element. (Think char *s="almost a string"; or execve(2).)
Design your function so it takes some other descriptor of the
arguments. (Think printf("%s%i", "hello", 10); -- the string describes
the other arguments. printf(3) uses stdarg(3) argument handling, but
it could just as easily be an array.)
Getting the array-size from the pointer isn't possible. You could just terminate the array with a NULL-pointer. That way your function can search for the NULL-pointer to know the size, or simply just stop processing input once it hits the NULL...
If you mean how long are all the strings added togather.
int n=2;
int size=0;
char* array [n] = { "One", "Two"};
for (int i=0;i<n;++i)
size += strlen(array[i];
Added:
yes thats what im currently doing but i wanted to remove that extra
paramater. oh well –
Probably going to get a bad response for this, but you could always use the first pointer to store the size, as long as you don't deference it or mistake it for actually being a pointer.
char* array [] = { (char*)2,"One", "Two"};
long size=(long)array[0];
for(int i=1; i<= size;++i)
printf("%s",array[i]);
Or you could NULL terminate your array
char* array [] = { "One", "Two", (char*)0 };
for(int i=0;array[i]!=0;++i)
{
printf("%s",array[i]);
}
Use the new C++11 std::array
http://www.cplusplus.com/reference/stl/array/
the standard array has the size method your looking for
I have a function declared like so:
unsigned char** Classifier::classify(){
//...
unsigned char **chars = new unsigned char *[H];
for(int i = 0; i < H; i++)
chars[i] = new unsigned char[W*3];
//...
return &chars;
//note: when this is "return chars;" I get the following: cannot convert ‘unsigned char*’ to ‘unsigned char**’ in return
This is giving me the warning:
Classifier.cpp: In member function ‘unsigned char** Classifier::classify()’:
Classifier.cpp:124: warning: address of local variable ‘chars’ returned
Is this ok to ignore? Basically, my question is how do you return a reference to an array that is defined in the function?
I want to be able to do
unsigned char** someData = classify();
Just return the array, not its address:
return chars;
&chars is a pointer to a pointer to a pointer, but chars is a pointer to a pointer (what you want). Also note that chars is not an array. Pointers and arrays are not the same thing, although they are often confused.
This is never okay to ignore. You're returning the address of a local variable. That address will become invalid when you leave classify()'s stack frame, before the caller has a chance to use it.
You only need to return the value of that variable instead:
return chars;
#Adam Rosenfield has got the correct answer and so have some others, (remove that ampersand) but as food for thought, a nice way to do this is to use a std::vector (of std::vectors) and pass it into the function as a reference parameter.
#include <vector>
void Classifier::classify(std::vector<std::vector<unsigned char>> & chars)
{
//construct a vector of W*3 integers with value 0
//NB ( this gets destroyed when it goes out of scope )
std::vector<unsigned char> v(W*3,0);
//push a copy of this vector to the one you passed in - H times.
for(int i = 0; i < H; i++)
chars.push_back(v);
}
chars is populated with the stuff you want and when it comes to deleting the vector, you don't have to worry about how to call the correct delete[] syntax that you would with those two calls to new in your 2D array.
You can still reference items in this vector as you would with your 2D array e.g. chars[5][2] or whatever.
although I can see you want to be able to go:
unsigned char** someData = classify();
So if you wanted to use vectors, you'd have to declare someData as follows:
std::vector<std::vector<unsigned char>> someData;
and to make that clearer perhaps:
typedef std::vector<std::vector<unsigned char>> vector2D;
vector2D someData;
classify(someData);
...
If an array defined in function and if you want to use it outside the function - you should describe it (array) as static or declare an array outside the function and pass it as parameter.
Use "return chars;" only;
No, it's not okay to ignore that warning. The value you're returning is the address of chars on the stack, not the thing it points to. You want to return just chars.
Others have given teh answer; but as a general observation I would recommend you look at the STL. You've tagged the question C and C++, so I'm assuming you're in a C++ environment and the STL is available. You can then use typedefs to define vectors in a readable form , and even vectors of vectors (ie. 2d arrays). You can then return a pointer or reference (as appropriate) to your vector of vectors.