Server Help

Non-Subspace Related Coding - returning array of strings in c++

hellzlaker - Mon Dec 01, 2008 2:43 pm
Post subject: returning array of strings in c++
I searched on Google and couldn't find anything i need, i just found how to return an array of integers and etc...

So is there a way for a function to return or return by refference an array of strings?

I tried doing,
Code: Show/Hide

char* GetWords(char* input)
{
      std::stringstream ss(std::stringstream::in|std::stringstream::out);
      ss<<input;
      int words = GetNumberOfWords(input);
      char* wordlist[words];
      for(int i=0;i<words;++i)ss>>wordlist[i];
      return wordlist;
}


But this didn't work
tcsoccerman - Mon Dec 01, 2008 3:06 pm
Post subject:
google search="c++ function array return" first link.

int *foo(int *array)
{
int *start = array;

return start;
}

int main()
{
int myarray[] = {1,2,3,4,5,0};
foo(myarray);
return 0;
}

output="1,2,3,4,5"
hellzlaker - Mon Dec 01, 2008 3:17 pm
Post subject:
tcsoccerman wrote:
google search="c++ function array return" first link.

int *foo(int *array)
{
int *start = array;

return start;
}

int main()
{
int myarray[] = {1,2,3,4,5,0};
foo(myarray);
return 0;
}

output="1,2,3,4,5"


I know that but how would you do that with char* mychar[10][80] ?
Cheese - Mon Dec 01, 2008 6:15 pm
Post subject:
mychar[3][5] = mychar[15]
Bak - Mon Dec 01, 2008 6:42 pm
Post subject:
You don't want to return an array by reference since the memory for an array is allocated on the stack which gets reused once the function returns. Your two options are to declare the array on the heap, or return by value (which you can't really do either). Alternatively, you could pass in a stack array like in tsoccerman's sample code (although you won't be able to resize it based on the number of words).

This is probably the easiest way of doing what you want, although it's definitely not the most efficient
Quote:
vector <string> GetWords(char* input)
{
std::stringstream ss(std::stringstream::in|std::stringstream::out);
ss<<input;
int words = GetNumberOfWords(input);
vector <string> wordlist;
for(int i=0;i<words;++i){ string s; ss>> s; wordlist.push_back(s);
return wordlist;
}


You could be more efficient by using the heap directly, although I'm not sure how good you are with dynamic memory icon_smile.gif.
hellzlaker - Mon Dec 01, 2008 9:29 pm
Post subject:
Bak wrote:

Quote:
vector <string> GetWords(char* input)
{
std::stringstream ss(std::stringstream::in|std::stringstream::out);
ss<<input;
int words = GetNumberOfWords(input);
vector <string> wordlist;
for(int i=0;i<words;++i){ string s; ss>> s; wordlist.push_back(s);
return wordlist;
}


You could be more efficient by using the heap directly, although I'm not sure how good you are with dynamic memory icon_smile.gif.


All I know about dynamic memory is basically to allocate it icon_confused.gif I don't really know what else you could do with it.

And I guess i took a different path in C++, kind of went towards C library and didn't learn anything about vectors icon_cry.gif

EDIT:

Bak could you show me the way with dynamic memory ?

Also Dev-C++ gives me this error
Code: Show/Hide

expected constructor, destructor, or type conversion before '<' token
expected `,' or `;' before '<' token
on this line
Code: Show/Hide
vector <string> GetWords(char* input)

k0zy - Tue Dec 02, 2008 2:00 pm
Post subject:
You missed one * in the function.
The return type has to be char**.
Otherwise it's an array of char, not of strings.
Bak - Tue Dec 02, 2008 3:51 pm
Post subject:
make sure you do "#include <vector>", "#include <string> and "using namespace std;" at the top of your code

With dynamic memory, it's tricky because you need to declare the array dynamically, as well as each string dynamically. At the end you have to remember to free all the data (each string, and then the array) in order to not have a memory leak.

So your function would look like this (using c-style dynamic memory instead of c++):

Code: Show/Hide

char** GetWords(char* input)
{
      std::stringstream ss(std::stringstream::in|std::stringstream::out);
      ss<<input;
      int words = GetNumberOfWords(input);
      char** wordlist = malloc((words + 1) * sizeof(char*));
     wordlist[words] = 0; // so we know when to stop   

      for(int i=0;i<words;++i){ string s; ss >> s; wordlist[i] = malloc(s.length() + 1); strcpy(wordlist[i],s.c_str()); }
      return wordlist;
}


And then remember to free the data after you use it:

Code: Show/Hide

char ** words = GetWords(input);
for (int x = 0; words[x] != 0; ++x)
{
  cout << "word " << x << " is " << words[x] << endl;
  free(words[x]);
}

free(words);

hellzlaker - Tue Dec 02, 2008 9:49 pm
Post subject:
Thanks I get it actually, just one thing confuses me, when you allocated memory for char** wordlist, why did you do words + 1 ? wouldn't it be enough with just char** wordlist = (char**)malloc((words)*sizeof(char*))
k0zy - Wed Dec 03, 2008 11:10 am
Post subject:
Bak did that, so you don't have to keep track of how many items you got inside the arrray.

Otherwise, you'd always have to know the exact amount of words when you want to iterate over it.

With bak's way, you can just stop if you reach 0 (the last word). Take a look at his way to free the array.


Edit: While we are at it.
I think, when you declare a pointer, you should keep the * to the variable name.
I know it's about personal preference here.
What do you think you are declaring when you do:

Code: Show/Hide
int* x, y;


Hint: It's not two pointers.
Cheese - Wed Dec 03, 2008 5:34 pm
Post subject:
it isnt? =(
tcsoccerman - Wed Dec 03, 2008 6:39 pm
Post subject:
x is y isn't. if i remember correctly.
Samapico - Thu Dec 04, 2008 12:05 am
Post subject:
tcsoccerman wrote:
x is y isn't. if i remember correctly.
exactly

you'd need to repeat the * for each if you want 2 pointers

int *x, *y;
Dr Brain - Thu Dec 04, 2008 6:59 am
Post subject:
That's why, style wise, you should always put a space between the type and the *. So int *x; or char *string;. So that you're not confused when declaring multiple pointers on the same line.
k0zy - Thu Dec 04, 2008 12:46 pm
Post subject:
Dr Brain wrote:
That's why, style wise, you should always put a space between the type and the *. So int *x; or char *string;. So that you're not confused when declaring multiple pointers on the same line.


That's what I was trying to say. icon_smile.gif
Dr Brain - Thu Dec 04, 2008 5:42 pm
Post subject:
Yeah, sorry. I tend to only read the last 4-5 posts in a thread. Seemed like everyone was confused on the subject.
hellzlaker - Thu Dec 04, 2008 7:20 pm
Post subject:
Bob Dole.. Bob Dole... Bob Dole...... bob dole.... bob... dole.... wrote:
Bak did that, so you don't have to keep track of how many items you got inside the arrray.

Otherwise, you'd always have to know the exact amount of words when you want to iterate over it.

With bak's way, you can just stop if you reach 0 (the last word). Take a look at his way to free the array.


Edit: While we are at it.
I think, when you declare a pointer, you should keep the * to the variable name.
I know it's about personal preference here.
What do you think you are declaring when you do:

Code: Show/Hide
int* x, y;


Hint: It's not two pointers.

Ah I see, as for the pointer i knew that, while ago i tried doing that icon_rolleyes.gif but I usually use char* just because it looks better and with char* I don't declare more then one on the same line because the code looks nicer.
hellzlaker - Fri Dec 05, 2008 6:19 pm
Post subject:
Ok I made basically same thing as bak showed just used more of a c++ way, (string class and allocating memory)
Code: Show/Hide
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sstream>
using namespace std;

#define ENDOFLIST "54gf54g5sf8^&*78d"

int GetNumberOfWords(string buf)
{
   int words = 0;
   int length = buf.length();

   for(int i=0;i<length;++i)
   {
      if(buf[i]!=' ' && i==0)++words;
      if(buf[i]==' ' && i!=0)
      {
         if(buf[i+1]!=' ')++words;
         if(i>1 && buf[i-1]==' ' && buf[i-2]==' ' && buf[i+1]!=' ' && words==0)++words;
      }
   }
   
   return words;
}

string *GetWords(string input)
{
   std::stringstream ss(std::stringstream::in|std::stringstream::out);
   ss<<input;
   int words = GetNumberOfWords(input);
   string *wordlist = new string[words+1];
   wordlist[words] = ENDOFLIST;
   for(int i=0;i<words;++i)
   {
      string s;
      ss>>s;
      wordlist[i]=s;
   }
   return wordlist;
}

int main()
{
   string buf;
   cout<<"Enter a string: ";
   getline(cin,buf);
   cout<<"Number of words: "<<GetNumberOfWords(buf);

   string *wordlist = GetWords(buf);

   cout<<"\nList of words:";

   {
      int i = 0;
      while(wordlist[i]!=ENDOFLIST)
      {
         cout<<endl<<wordlist[i];
         ++i;
      }
   }

   delete[] wordlist;

   cout<<endl;
   system("pause");
}

All times are -5 GMT
View topic
Powered by phpBB 2.0 .0.11 © 2001 phpBB Group