String NULL?

I'm not sure how to ask the question so I'll let the code do the talking. :P

Example 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Global value
char returnValue[256] = {0};

// foo function to do awesome stuff
char* foo(const std::string& var)
{
    std::string someValue;
    // Do something significant
    if ( it worked )
    {
        memcpy(returnValue, someValue.c_str(), someValue.length());
        return returnValue;
    }
    else
    {
        return 0;
    }
}


Example 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// foo function to do awesome stuff
std::string foo(const std::string& var)
{
    std::string someValue;
    // Do something significant
    if ( it worked )
    {
        return someValue;
    }
    else
    {
        return 0;
    }
}


Oops! Example 2 will not work if it worked is false. That is, you can't pass back a NULL construct with a string type.

Is there something else I can do here? I need to be able to pass something back (other than a "valid" string) but can't seem to find a tool to use. Any suggestions?

Edit: Corrected a spelling problem. Thanks, L B.
Last edited on
I would most likely throw an exception in this case.
What if someValue.length() is greater than 255?
Last edited on
I'd also suggest throwing an exception, as firedraco says, but I think it depends on the situation. For example, in one case for me, returning the string "N/A" made sense. In other cases, returning an empty string was also ok (i.e., string with 0 length). It depends on what the calling function excepts.

With char's is actually no different. You can return NULL, but if the calling function tried to print it, then you're going to get problems. So the calling function has to handle the case of getting a NULL back.

IMHO, throwing an exception is somewhat more universal since the calling function doesn't have to know what a 0-length string means, etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
std::string foo(const std::string &val) {
   std::string str;
   //...
   if( it_worked ) {
      return str;
   } else
      throw std::string("Whoops!"); //or what ever type of exception you want
}

int main() {
   std::string s("Hello."), r;
   try {
      r = foo(s);
   } catch(string &e) {
      cerr << "Something bad happened...";
      return 1; //or recover from the error
   }
   //...
   return 0;
}
You can always pass the string as a parameter to be filled and return err code.
1
2
3
4
5
6
7
8
9
10
11
12
13

int foo(const std::string &val, std::string &stringToBeFilled) {
   std::string str;
   int err  = 0;
   //...
   if( it_worked ) {
      stringToBeFilled = filled with some extra values
   } else
       err = -1

    return err;
}
closed account (S6k9GNh0)
Or you could just pass back "" and test if it's empty or not...
Thank you for your responses. I should have been more verbose about my requirements. I cannot change the interface to how the applications calling this function behave. If I throw an exception they may not handle it.

Currently the application will expect either a character pointer or NULL. I'm updating some legacy code, which was littered with many global variables, to use better techniques and standard containers.

I read values in from a CSV file and report back the corresponding value to the record the application requested. Passing back "" is valid as the CSV file may have "" as the value for the given record. I can't use any valid string as it may be the actual value of the record. "NOT_VALID", "N/A"...all of these are possible REAL values I can have in the CSV file.

I'd love to be able to change the interface or throw an exception (or both) but sadly these are not options for me.

Regarding the length of the character array - based on our technical documents they should never be larger than 19 (maybe it was 26, I forget exactly). In either case there is no threat of a memory issue there.

Does anyone have any suggestions?
Last edited on
In this particular case there isn't much way around it... you'll have to have a static storage space somewhere for the return values. You can keep it in the global space if you like, but you can also put it in the function scope thus:

1
2
#include <algorithm>
#include <string> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
char* foo(const std::string& var)
{
    static char returnValue[256] = {0};

    std::string someValue;
    // Do something...
    if ( it worked )
    {
        return std::char_traits<char>::copy(returnValue, someValue.c_str(), std::min(sizeof(returnValue)-1, someValue.length()));
    }
    else
    {
        return NULL;
    }
}

Hope this helps.
Would it be possible for you to have an error variable (a global one) and return some valid string in the else case ?? The calling function could make a check if the error variable is set and then it might decide if the valid string is actually valid or not ...
Sure. A lot of APIs do that, even. But the OP's API does not.
closed account (S6k9GNh0)
errno is part of C STD isn't it?
It's in POSIX.
Topic archived. No new replies allowed.