-2

I would like to ask if someone here tried a function on VC++ that returns multiple data or values. I would like to store values after i tokenize a string. Example value is 00:00-10:00,11:00-14:00,16:00-21:00. As you can see, time are separated on 3 parts separated by a comma (,). Using strtok, i can separate the string.

char *token = strtok(stringabove,",");
while(token)
{
    separatedvalues = token;
    token = strtok(NULL,",");
}
return(separatedvalues);

code using vector.

vector<CString> MyFunction::Scheduler(CString value)
{
    char temp[250];
    sprintf(temp,"%s",value);
    vector<CString> result;
    char *token = strtok(temp,",");
    while(token)
    {
         result.push(token;
         token = strtok(NULL,",");
    }
  return(result);
}

I hope someone can help me with this one.

Thank you very much.

batch 1999
  • 109
  • 9
  • 1
    You need to elaborate your question. As it stands here it's hard to understand what you want. – Jabberwocky May 11 '17 at 07:10
  • 3
    a struct, a container or a tuple can be used, not just separate values. – stefaanv May 11 '17 at 07:10
  • 1
    Normally, you'd make a `class` that encapsulates such data, and return an instance of it (this way scales best). The trendies these days like tuples but don't use those just because they are a new shiny feature. – Bathsheba May 11 '17 at 07:11
  • @MichaelWalz I need to create a function that returns multiple values that have been tokenize. – batch 1999 May 11 '17 at 07:12
  • @Bathsheba: the advantage of using is a tuple is that with `std::tie`, it is closest to separate values. – stefaanv May 11 '17 at 07:13
  • @batch1999 are you writing in C or C++ ? – Jabberwocky May 11 '17 at 07:13
  • 2
    Indeed the advantages of using tuples are practically endless. You also have less refactoring to do if you want to submit your code to an obfuscation contest. – Bathsheba May 11 '17 at 07:13
  • Off topic: C++ offers many better and safer ways to split strings than `strtok`. `std::stringstream` and `std::getline` make up one of the simpler approaches. – user4581301 May 11 '17 at 07:14
  • @stefaanv i want to tried that one but i dont know how to use function using struct. – batch 1999 May 11 '17 at 07:14
  • " I would like to store values after i tokenize a string." is this the question? – Valgrind1691 May 11 '17 at 07:15
  • @batch1999: Really, I think you need to invest much more time in this. Start with this link: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – Bathsheba May 11 '17 at 07:15
  • @batch1999 are you writing in C or in C++? Your code fragment is C but your question is tagged C++. The answer to your question strongly depends on this. – Jabberwocky May 11 '17 at 07:17
  • @user4581301 i am retrieving data from a CListCtrl using for loop. It has 3 columns which consists DaysOfTheWeek,TimeA and TimeB so thats why i use strtok because it is much easier to parse CString to char – batch 1999 May 11 '17 at 07:17
  • CListCtrl, CSting - wow that's a blast from the past. Don't the cool cats use QT these days? – Bathsheba May 11 '17 at 07:18
  • @Bathsheba , actually CSting sounds like a function from the hobbit library. – user4581301 May 11 '17 at 07:22
  • @batch1999 from the types `CListCtrl` and `CString` you mentioned, I suppose you are using MFC? Is that correct? – Jabberwocky May 11 '17 at 07:23
  • How about using `std::vector`? – Barmar May 11 '17 at 07:31
  • @MichaelWalz yes correct. – batch 1999 May 11 '17 at 07:45
  • @Bathsheba I only use this today because the API that i am using only supports this. I can't use any of the .Net or other PL, i have to create or find a wrapper in order to use the API. – batch 1999 May 11 '17 at 07:46
  • 1
    @Bathsheba: It's *"Qt"* with a lower case *"t"*. And there is nothing cool about it. There's just a larger community that's shouting louder, that it's the best since sliced bread. Truth be told: It ain't. It's just as convoluted as MFC, with the advantage, that it can fail on more platforms. – IInspectable May 13 '17 at 18:55

2 Answers2

2

C and C++ don't support returning multiple values.
However, they can be returned when they are combined.

One way of combining them is making a struct with the different variables.

struct Result
{
   std::string res1;
   std::string res2;
   std::string res3;
};

Of course, the results can have different types, but this is the result from the question.

So in this case, you don't do the tokenizing in a loop, but one after the other and you check that the result is valid

Result splitTimeString(const std::string& input)
{
    Result res;
    // do the tokenizing and fill the result
    return res;
}

usage:

Result res = splitTimeString(inp);
std::cout << res.res1;

If you don't know the number of results in advance, but they have the same type, you can use a container (e.g. std::vector) instead of a struct.

Instead of a struct, you can also use a std::tuple or std::pair (sometimes seen as lazy programmer's structs), but this has the advantage of using std::tie to assign directly to separate variables:

std::tuple<std::string, std::string, std::string> splitTimeStringToTuple(const std::String& inp)
{
    std::string res1, res2, res3;
    // tokenize
    return std::make_tuple(res1, res2, res3);
}

std::string res1, res2, res3;
std::tie(res1, res2, res3) = splitTimeStringToTuple(inp);
stefaanv
  • 14,072
  • 2
  • 31
  • 53
  • i tried using vector but it does not work. please see the updated code above, i just modified it from an example on the web – batch 1999 May 11 '17 at 07:41
  • @batch1999 _It did not work_ is not a problem description. – Jabberwocky May 11 '17 at 07:49
  • Sorry, I don't know what a `CString` is, so I can't help you. I'm sure that using `std::vector` and `result.emplace_back(token);` would work. – stefaanv May 11 '17 at 07:51
  • @MichaelWalz what i mean is it shows the whole value even i have used strtok, when i call the function and shows the result using the iterator , it shows the whole value and not the tokenized ones. – batch 1999 May 11 '17 at 07:53
  • Actually as of c++17 you *can* return multiple values in the form of tuples – Passer By May 11 '17 at 08:07
  • @PasserBy: yes, `auto [ res1, res2, res3 ] = splitTimeStringToTuple(inp);` looks nicer than the tuple example in the answer. I'm not up to speed with C++17, so I leave it like it is. – stefaanv May 11 '17 at 08:23
1

You probably want something like this:

vector<CString> Test(CString value)
{
  char temp[250];
  sprintf(temp, "%s", value);
  vector<CString> result;        

  char *token = strtok(temp, ",");

  while (token)
  {
    result.push_back(CString(token));  // We need to push a CString not a char*
    token = strtok_s(NULL, ",");
  }

  return(result);
}

int main()
{
  CString value = "ab,cd,ef";
  vector<CString> result = Test(value);
  ...
}

There are more elegant and more efficient ways, but this is close to your attempt.

Otherwise this is more efficient (see Joe Willcoxson's comment below):

void Test(CString value, vector<CString> & result)
{
  char temp[250];
  sprintf(temp, "%s", value);

  char *token = strtok(temp, ",");

  while (token)
  {
    result.push_back(CString(token));  // We need to push a CString not a char*
    token = strtok_s(NULL, ",");
  }
}

int main()
{
  CString value = "ab,cd,ef";
  vector<CString> result;
  Test(value, result);
  ...
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • Thanks... i will try it. – batch 1999 May 11 '17 at 08:33
  • Yeah, it's what he asked for. I would make the function a void or bool and pass in the vector as a reference so that the code doesn't have to mess with making copies of the vector, etc. It would be more efficient. – Joseph Willcoxson May 11 '17 at 15:39
  • *"Otherwise this is more efficient"* - That's speculation. (N)RVO has been supported in compilers for ages. And C++11 implements move semantics, so returning a `std::vector` will **move** the contents back to the caller, instead of copying them. That's a guarantee, not just a compiler optimization (see [this Q&A](http://stackoverflow.com/q/15704565/1889329)). – IInspectable May 13 '17 at 18:50