Как определить функцию, которая будет возвращать указатель на «» значение, когда не найдено ни одного соответствующего данных? - PullRequest
0 голосов
/ 01 мая 2019

Я хочу, чтобы моя функция () всегда возвращала строку "" в условиях ошибки, иначе возвращает строку, которая преобразуется в строку из длинной целой переменной без знака.

Моя первоначальная реализация выглядит следующим образом:

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;
}

Когда функция вызывается в разных экземплярах для получения cfgVariables, я ожидаю, что моя функция getCfgVariable () вернет "" в случае ошибки,когда совпадений не найдено.Где-то в коде:

 const char* CfgValue = NULL;

 CfgValue = getCfgVariable("cfgVariable_1");

Здесь CfgValue указывает на местоположение, которое содержит 4

позже

 const char* CfgValue = NULL;

 CfgValue = getCfgVariable("cfgVariable_3");

Я ожидаю получить "" назад, но я получаю 4вместо этого (CfgValue получает тот же адрес, что и раньше).

Исправление, реализованное мной, работает, но я не могу понять логику, стоящую за ним, исправление:

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;
}

Я вижу во время отладки это defValueи retValue указывают на два разных местоположения, которые не перезаписываются.defValue всегда указывается на один и тот же адрес, когда инициализируется с помощью «», а retValue указывается на другой адрес, когда инициализируется с помощью «\ 0».Кто-нибудь может объяснить логику этого?Есть ли лучшая реализация для моего варианта использования?

Мое решение после рассмотрения комментариев:

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;
}

Спасибо за комментарии, и это решение все еще открыто для дальнейших предложений по улучшению.

1 Ответ

1 голос
/ 01 мая 2019

Строки Constexpr, такие как "\ 0", "", "cfgVariable_1" и т. Д. Это постоянные строки в памяти, скомпилированные в ваш полученный исполняемый файл. Попытка записать значения в эти строки совершенно опасна! В старом стиле C вам пришлось бы использовать malloc, чтобы выделить немного памяти для вашей строки. Это настоящая боль, с которой приходится сталкиваться на практике (и не идеальная для тех, кто изучает C ++).

Гораздо более простое решение - начать использовать строковый объект C ++, std :: string (который обрабатывает все динамическое выделение памяти для вас!). Это должно уменьшить вашу проблему до чего-то более простого (а главное, более безопасного!):

#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();
}

Делая это в C, у вас есть 2 варианта. Выделите память для возвращаемой строки или используйте статический буфер, который всегда доступен (что и делает этот пример).

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;
}

Однако, поскольку теперь retValue является массивом, фиксированным в памяти, возвращаемая строка будет действительной только до следующего вызова getCfgVariable, что может быть немного странно ....

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 ""
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...