...

View Full Version : Return array from function



satchel
06-09-2009, 09:03 PM
Sorry to have to post this really.. but I've been looking everywhere to a solution to this problem. I wrote a function to read a file (csv) into a bidimensional array, and that works fine... only I can't get the array out XD I've tried everything I can think of, any suggestions?

Fou-Lu
06-09-2009, 11:57 PM
I don't know the language you're using, so I'll assume C.
First, make sure you've allocated up you're space. Otherwise you won't be able to return anything once the stack is popped. An array is locally declared which would put it on the stack memory - you'll need to retreive it from heap instead so use malloc or another similar allocation method.
Next you can't return an array. You can return a pointer though, and being multi-dimensional will require a pointer to a pointer. This will get more complicated as you step through the levels and add things, so I'd probably go with a Matrix struct instead. Gets around the whole int ** return and replaces it with a MATRIX * instead, which does look nicer. Once you've written the necessary functions for it, it will be easier to find what you're looking for in the matrix as well.

satchel
06-10-2009, 09:11 AM
I forgot to put the language in, sorry. Yes, C++. This is the function:


void loadmap() {
string line,item;
int row_count;
int line_count;
ifstream map(map_file.c_str());
if (map.is_open()) {
while (!map.eof()) {
getline(map, line);
istringstream linestream(line);
row_count = 0;
while (getline (linestream, item, ',')){
row_count++;
}
line_count++;
}
string coords[row_count][line_count];
line_count = 0;
row_count = 0;
map.close();
ifstream map(map_file.c_str());
while (!map.eof()) {
getline(map, line);
istringstream linestream(line);
row_count = 0;
while (getline (linestream, item, ',')){
coords[row_count][line_count]=item;
row_count++;
}
line_count++;
}
}
map.close();
}
So I replace void at the beginning with MATRIX *? I've never used malloc before... I'll look it up. Where abouts would that fit in? Could I not just make the array global?

Fou-Lu
06-11-2009, 01:58 AM
You could just globalize, though that is not exactly recommended especially with a compiled language.
You can also take in a pointer to you're function argument or return a pointer that has been allocated.
I don't do C++, but I assume you'll still need to allocate memory for you're pointer. I also believe that 'new' will allocate stack memory resulting in the destruction of the pointer when the function is terminated.
C++ *may* have a built in Matrix to work with. I doubt it, though I would assume that a third party library has been built.

In C, I'd just write a struct for it. All we care about is columns, rows and a pointer pointer to our data. Be a pain since I'd probably use a char *** to the data as a part of my data union. Probably easier to calculate than using a char ** and relying on the rows and columns to calculate the locations needed. Then you need to write all functions required to manipulate the matrix.

So needless to say, you can't just change void to MATRIX * unless you've written it.
You're options (assuming that C++ is the same), is to pass a pointer as an argument (or assuming an object will work as well), return an allocated pointer / object, and globalize.

One of the C++ guys can probably give you a much better idea / solution for this. If you write you're own matrix, a class would be the best route, but I don't trust my C++ skills nearly enough to help you on that, sorry.

satchel
06-11-2009, 08:07 AM
Thanks for your help, I'll give it a go :D

ralph l mayo
06-12-2009, 12:51 AM
Just as you can use an array of arrays to represent a multidimensional structure in C, you can use a vector of vectors in C++.

Some of the advantages of this approach are that you can return a vector because it knows what size it is and doesn't create an ambiguous situation like returning a pointer to an array, and that you don't need to know what the final dimensions of the structure will be when you instantiate it, so you can add to it as you go along. This means that you can condense your function to work using only one loop through the file.

I didn't feel like rewriting your CSV thing, but here is an example of the vector-specific stuff you would have to change to use this approach:



#include <vector>

typedef std::vector<std::string> StringList;
typedef std::vector<StringList> StringMatrix;

StringMatrix loadmap()
{
StringMatrix rv; // size unknown, thus far
for (size_t i = 0; i < 10; ++i)
{
rv.push_back(StringList()); // add a row
for (char j = 'A'; j <= 'Z'; ++j)
rv[i].push_back(std::string(1, j)); // add a column
}
return rv;
}

int main()
{
StringMatrix mat = loadmap();
// Use iterators to traverse the results without running off the end of any rows or columns
for (StringMatrix::const_iterator row = mat.begin(); row != mat.end(); ++row)
{
for (StringList::const_iterator col = row->begin(); col != row->end(); ++col)
std::cout << *col;
std::cout << "\n";
}
}


Which just prints the alphabet 10 times.

(If you're not familiar with typedef, it just creates an alias of a type. You could, if you wanted, change every instance of StringList to std::vector<std::string> and every instance of StringMatrix to std::vector<std::vector<std:: string> > without impacting the functionality of the program.)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum