Atoi / Atol - 结果为0

时间:2013-09-05 20:48:19

标签: c

我正在构建快速的“配置阅读器”,它从文件中读取设置。 问题是,该函数返回“800”字符串,atol与该输​​入返回0.我不确定我做错了什么。

所以,这就是它大致的样子:

char *txtval=GetParamFromLine("WINDOW_WIDTH");
val = atol(txtval); 

char* GetParamFromLine(char*parameter)
{
   char text[16];
   //
   // do the reading procedure and fill the text
   //
   return text;
}

结果:atol(文本)= 0(其中text =“800”)

感谢您的帮助!

4 个答案:

答案 0 :(得分:4)

你需要有"文字"存储在堆而不是堆栈中。否则,当函数结束时,变量将超出范围,并且您将尝试访问该段内存时出现未定义的行为。您可以在堆上分配内存,然后在完成后释放它,

char *txtval=GetParamFromLine("WINDOW_WIDTH");
val = atol(txtval); 
free txtval;

// Caller is responsible for freeing returned buffer
char* GetParamFromLine(char*parameter)
{
   char text* = malloc(sizeof(char)*16);
   //
   // do the reading procedure and fill the text
   //
   return text;
}

或者,也可以将指针传递给应该存储结果的缓冲区。

char txtval[16];
GetParamFromLine("WINDOW_WIDTH", txtval);
val = atol(txtval); 

void GetParamFromLine(char *parameter, char *resultBuffer)
{
   //
   // do the reading procedure and fill the text into resultBuffer
   //
}

答案 1 :(得分:3)

您正在返回指向本地范围变量的指针。在函数调用之后,内存text超出了范围,因此指向它的指针没有意义,因为内存将被回收...

您需要为text分配一些长期存储空间,或将GetParamFromLineatol合并到同一个功能中。

答案 2 :(得分:2)

将文字设为静态:

char* GetParamFromLine(char*parameter)
{
    static char text[16];
    ... do something
    return text;
}

您的版本使用的是堆栈驻留版本,在使用之前可能会被覆盖。

确保静态存储类说明符

返回缓冲区只有在下次调用GetParameterFromLine之前才会有效。

通常,调用者最好提供缓冲区和缓冲区大小作为这样的函数的参数。

char *GetParamFromLine(const char *parameter, char *text, size_t text_size)
{
    ... do something
    return text;
}

“做某事”代码应该仔细观察这个大小。您必须决定是否截断参数,返回空字符串,返回NULL指针,或者如果实际数据长于缓冲区,则返回任何内容。

答案 3 :(得分:2)

问题是由返回指向局部变量的指针引起的。当函数GetParamFromLine返回时,变量text超出范围。返回的指针不再有效,导致未定义的行为。您必须以其他方式返回数据,例如:

std::string txtval=GetParamFromLine("WINDOW_WIDTH");
val = atol(txtval.c_str());

std::string GetParamFromLine(char*parameter)
{
   char text[16];
   //
   // do the reading procedure and fill the text
   //
   return std::string(text);
}

将返回类型从指向本地的指针更改为std::string可以缓解返回指向局部变量的指针的问题。 std::string使用的资源由​​对象管理,并自动清理。

作为替代方案,您也可以删除atol来电并改为使用std::istringstream。一个好处是,这可以更好地报告错误:

std::string txtval=GetParamFromLine("WINDOW_WIDTH");
std::istringstream iss(txtval);
int val( 0 );
iss >> val;

现在,如果你真的想要超越顶部,你可以将字符串的检索和转换结合到一个整数数据类型,并参数化这个新函数模板的返回类型:

template<typename T>
T GetValueFromLine(const std::string& param) {
    std::string txtval=GetParamFromLine(param.c_str);
    std::istringstream iss(txtval);
    T val = T();
    iss >> val;
    return val;
}

使用此模板,您可以执行以下操作:

long wndWidth = GetValueFromLine<long>("WINDOW_WIDTH");
bool showInfo = GetValueFromLine<bool>("SHOW_INFO");
....

注意:错误处理已被忽略。