strtol的基础知识是什么?

9

我很困惑。我肯定是错过了一些简单的东西,但是我读到的有关strtol()的内容都让我感到迷惑。有人能以非常基础的方式为我解释一下吗?并且给出一个示例,说明我如何使以下内容正常工作?

string input = getUserInput;
int numberinput = strtol(input,?,?);

1
你尝试过 http://stackoverflow.com/search?q=strtol 吗? - Csq
1
还是http://www.cplusplus.com/reference/cstdlib/strtol/? - Csq
使用strtol而不是stringstream读取数字有什么特别的原因吗? - nneonneo
你尝试过使用 int number = strtol(input.**c_str()**, ...); 吗? - Thomas Matthews
2
@nneonneo,我们有std :: stol时就不需要一个stringstream。 - Seth Carnegie
显示剩余2条评论
4个回答

33
第一个参数是字符串。它必须作为C字符串传递,因此如果您有一个std::string,请先使用.c_str()
第二个参数是可选的,并指定要存储数字后面字符的char *指针。当转换包含多个整数的字符串时,这很有用,但如果不需要,请将此参数设置为NULL。
第三个参数是要转换的基数(底数)。strtol可以从二进制(基数2)到36进制做任何事情。如果您希望strtol根据前缀自动选择基数,则传入0。
因此,最简单的用法如下:
long l = strtol(input.c_str(), NULL, 0);

如果您知道您将获得十进制数:

long l = strtol(input.c_str(), NULL, 10);

strtol函数如果在字符串开头没有可以转换的字符,则返回0。如果你想检查strtol是否成功,请使用中间参数:

const char *s = input.c_str();
char *t;
long l = strtol(s, &t, 10);
if(s == t) {
    /* strtol failed */
}

如果您正在使用C++11,使用stol而不是之前的方法:stol
long l = stol(input);

或者,您可以使用 stringstream ,它具有像 cin 一样轻松读取多个项目的优点:

stringstream ss(input);
long l;
ss >> l;

1
@JamesThompson: string (std::string) 是一个表示字符串的 C++ 对象。这是在 C++ 中处理字符串的首选方式。C 字符串是以空终止符(\0)结尾的字符序列,并由指向序列中第一个字符的指针(char *)表示。C 函数(如 strtol)不接受 string 对象作为参数,因此必须传递 C 字符串。 - nneonneo
哦不,那就有问题了。我需要能够捕获当没有输入数字的情况,但是对于我的项目来说0是一个有效的数字,因此我不能只做 if(int = 0) 这样的检查。 - James Thompson
1
strtol 会保存指针指向 t 中第一个非数字字符。如果 s==t,那么意味着字符串的第一个字符就是非数字字符,即该字符串不以数字开头。 - nneonneo
好的,那很有道理。最后一个问题。我实际上需要对双精度浮点数做同样的事情,我知道有一个 strtod 函数,但是使用相同的代码不起作用,strtod 使用不同的参数吗?还是我漏掉了什么? - James Thompson
谷歌搜索该函数。它有不同的参数吗? - nneonneo
显示剩余3条评论

4
假设您有一个字符串char const * str,现在按照以下方式进行转换:
#include <cstdlib>
#include <cerrno>

char * e;
errno = 0;

long n = std::strtol(str, &e, 0);

最后一个参数0决定你想应用的进制数;0表示“自动检测”。其他合理的值为81016
接下来,您需要检查结束指针e。这指向已消耗输入后的字符。因此,如果所有输入都被消耗,则指向空终止符。
if (*e != '\0') { /* error, die */ }

使用e可以允许部分输入消耗,但只有在实际需要时才会理解此类内容。

最后,您应该检查错误,如果输入不能适合目标类型,则基本上只能是溢出错误:

if (errno != 0) { /* error, die */ }

在C++中,使用std::stol可能更好,但这种情况下您无法选择数字基数:

#include <string>

try { long n = std::stol(str); }
catch (std::invalid_argument const & e) { /* error */ }
catch (std::out_of_range const & e)     { /* error */ }

0

引用自C++ 参考文献

long int strtol ( const char * str, char ** endptr, int base );

将字符串转换为长整型

解析C字符串str,将其内容解释为指定基数的整数,并将其作为long int值返回。如果endptr不是空指针,则该函数还将endptr的值设置为指向数字后第一个字符的指针。

因此,可以尝试类似以下的代码:

long l = strtol(pointerToStartOfString, NULL, 0)

我对C++还不熟悉,所以对指针不太习惯,尽管我了解概念。我应该如何找到字符串的指向开头的指针?它应该是怎样的? - James Thompson
在C语言中,它的工作原理是这样的:char是一个包含字符的变量。char*是一个包含指针的变量。当解引用指针时,它指向一个字符(通常是内存中许多字符的开头,称为“字符串”)。因此,如果您有char* MyPointer,那么您可以执行strtol(MyPointer, NULL, 0) - Patashu

0
我总是使用简单的 strol(str,0,0) - 它返回长整型值。基数为 0(最后一个参数)表示自动从输入字符串中检测,因此输入字符串中可以使用十六进制 0x10 和十进制 10

尝试使用strol(input,0,0)时出现了以下错误:“无法将`std :: string'转换为`const char *',用于参数`1'到`long int strtol(const char *,char **,int)'” - James Thompson
是的,C++有std::string,它不是char*。尽管它们都用于保存字符串,但是针对一个的函数不能适用于另一个。 - Patashu
对于std::string,请使用strtol(str.c_str(),0,0) - mvp
True关于0会导致自动检测基数。对于"0109",结果为8,因为8是自动检测的基数。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接