简体   繁体   中英

How to define a function to return a pointer to a “” value when no matching data is found?

I want my function() to always return a "" string under error conditions else return a string that is converted to string from an unsigned long integer variable.

My initial implementation is as follows:

uint32 cfgVariable_1 = 4;
uint32 cfgVariable_2 = 1;

const char* getCfgVariable (const char* msg)
{
  char* retValue = "";

  if(strcmp("cfgVariable_1", msg)==0)
  {
    // Since I want my function to return a const char* and returning uint32_t is not an option
    sprintf((retValue), "%lu", cfgVariable_1);
    return (const char*)retValue;
  }
  else if(strcmp("cfgVariable_2", msg)==0)
  {
    // Since I want my function to return a const char* and returning uint32_t is not an option
    sprintf((retValue), "%lu", cfgVariable_2);
    return (const char*)retValue;
  }
  else
 {
  //error
 }
 return (const char*) retValue;
}

When the function is called at different instances to get the cfgVariables, I expect my function getCfgVariable() to return "" on error condition, when no match found. Somewhere in code:

 const char* CfgValue = NULL;

 CfgValue = getCfgVariable("cfgVariable_1");

Here CfgValue gets pointed to location which contains 4

later

 const char* CfgValue = NULL;

 CfgValue = getCfgVariable("cfgVariable_3");

I expect to get a "" back but I get 4 instead (CfgValue gets the same address as before).

Fix implemented by me works, but I fail to understand the logic behind it, fix:

const char* getCfgVariable (const char* msg)
{
  const char* defValue = "";
  char* retValue = "\0";

  if(strcmp("cfgVariable_1", msg)==0)
  {
    // Since I want my function to return a const char* and returning uint32_t is not an option
    sprintf((retValue), "%lu", cfgVariable_1);
    return (const char*)retValue;
  }
  else if(strcmp("cfgVariable_2", msg)==0)
  {
    // Since I want my function to return a const char* and returning uint32_t is not an option
    sprintf((retValue), "%lu", cfgVariable_2);
    return (const char*)retValue;
  }
  else
 {
  //error
 }
 return defValue;
}

I see during debugging that defValue and retValue get pointed to two different locations that do not get overwritten. defValue always gets pointed to the same address when its initialized with "" and retValue gets pointed to a different address when initialized with "\\0". Can anyone explain the logic behind this ? Is there a better implementation for my use case ?

My Solution after considering the comments:

const char* getCfgVariable (const char* msg)
{
  const char* retValue = "";
  std::ostringstream oss;

  if(!strcmp("cfgVariable_1", msg))
  {
    oss << cfgVariable_1;
  }
  else if(!strcmp("cfgVariable_2", msg))
  {
    oss << cfgVariable_2;
  }
  else
  {
    //error
    return retValue;
  }
  const std::string tmp = oss.str();
  retValue = tmp.c_str();

  return retValue;
}

Thanks for the comments so far and this solution is still open to further improvement suggestions.

Constexpr strings such as "\\0", "", "cfgVariable_1", etc. These are constant strings in memory compiled into your resulting executable. Attempting to write values into those strings is downright dangerous! In old style C, you'd have to use malloc to allocate a bit of memory to use for your string. This is a real pain to deal with in practice (and not ideal for someone who's learning C++).

A far simpler solution is to start using the C++ string object, std::string (which handles all of the dynamic memory allocation for you!). This should reduce your problem to something a little simpler (and most importantly, safer!):

#include <string>
#include <sstream>

std::string getCfgVariable (const char* const msg)
{
  std::ostringstream oss;
  if(!strcmp("cfgVariable_1", msg))
  {
    oss << cfgVariable_1;
  }
  else 
  if(!strcmp("cfgVariable_2", msg))
  {
    oss << cfgVariable_2;
  }
  return oss.str();
}

Doing this in C, you have 2 choices. Allocate the memory for the returned string, or use a static buffer that is always available (which is what this example does).

uint32 cfgVariable_1 = 4;
uint32 cfgVariable_2 = 1;

const char* getCfgVariable (const char* msg)
{
  static char retValue[32] = {0};

  if(strcmp("cfgVariable_1", msg)==0)
  {
    // Since I want my function to return a const char* and returning uint32_t is not an option
    sprintf(retValue, "%lu", cfgVariable_1);
    return retValue;
  }
  else if(strcmp("cfgVariable_2", msg)==0)
  {
    // Since I want my function to return a const char* and returning uint32_t is not an option
    sprintf(retValue, "%lu", cfgVariable_2);
    return retValue;
  }
  else
 {
  //error
 }
 return retValue;
}

However, because now the retValue is an array fixed in memory, the string returned would only be valid until the next call to getCfgVariable, which could be a little strange....

const char* A = getCfgVariable("cfgVariable_1");
printf("%s\n", A); // prints '4'

const char* B = getCfgVariable("cfgVariable_2");
printf("%s\n", B); // prints '1'
printf("%s\n", A); // now this will print '1', and not '4'. 

const char* C = getCfgVariable("anythingElse");
printf("%s\n", C); // prints ""
printf("%s\n", B); // prints ""
printf("%s\n", A); // aso prints ""

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM