C Atoi/Atol-结果为0

C Atoi/Atol-结果为0,c,C,我正在构建快速配置阅读器,它可以从文件中读取设置。 问题是,该函数返回800个字符串,而带有该输入的atol返回0。我不确定我做错了什么 所以,它大致看起来是这样的: char *txtval=GetParamFromLine("WINDOW_WIDTH"); val = atol(txtval); char* GetParamFromLine(char*parameter) { char text[16]; // // do the reading procedure a

我正在构建快速配置阅读器,它可以从文件中读取设置。 问题是,该函数返回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;
}
结果:atoltext=0,其中text=800

谢谢你的帮助

将文本设为静态:

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

do something代码应仔细观察该大小。如果实际数据比缓冲区长,则必须决定是否截断参数、返回空字符串、返回空指针或其他任何操作。

您返回的是指向局部范围变量的指针。函数调用后内存文本超出范围,因此指向它的指针没有意义,因为内存将被回收


您需要为文本分配一些长期存储,或者将GetParamFromLine和atol组合到同一个函数中。

您需要将文本存储在堆上而不是堆栈上。否则,当函数结束时,变量将超出作用域,您将有未定义的行为试图访问该内存段。您可以在堆上分配内存,然后在完成后释放内存

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

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

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::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");
....

注意:忽略错误处理。

在GetParamFromLine中终止字符串时是否确实为NULL?您正在从GetParamFromLine返回指向局部变量文本的指针。正如Eugen指出的,您正在返回指向在使用点不再存在的局部变量的指针。您不应提供错误和误导性的信息。文本不是800。在将来使用调试器。C++标签,它有效吗?如果是,则按值返回std::string,问题已解决。不要在C++程序中到处乱窜,没有很好的理由。或者删除C++标签,如果你被限制为C…当然,忘记Atol。如果需要使用C标准库函数,请使用strtol。或者,将目标缓冲区作为参数传递。希望没有人在多线程上下文中调用这些代码。非常感谢Mike,这解决了我的问题:或者确实返回strduptext;或使用std::string@mvp不要那样做!这是教条。不要那样做!SsieZoFar将始终是1。既然这个问题是标记C++,你应该认真考虑返回一个STD::String。@ IcTestTaby:应该是答案,而不是评论。好的,我只是忘记了变量范围…再次感谢:我不确定永久存储是正确的说法。您可以返回strduptext.+1以建议将atol合并到GetParamFromLine中,但我建议为此创建一个新函数:GetLongParamFromLine。是的,这是我的初衷,但我会有很多函数:GetLongFromLine GetStringFromLine GetFloatFromLine,所以我想获取参数值,并对其执行我想要的任何操作。这似乎也是一个好主意。非常感谢您的解答和解释。