为什么没有std :: stou?


96

C ++ 11添加了一些新的字符串转换功能:

http://en.cppreference.com/w/cpp/string/basic_string/stoul

它包括stoi(字符串到int),stol(字符串到long),stoll(字符串到long long),stoul(字符串到unsigned long),stoull(字符串到unsigned long long)。在没有stou(字符串到无符号)的情况下值得注意。是否有某些原因是不需要的,但所有其他原因都是?

相关:C ++ 11中没有“ sto {short,unsigned short}”函数吗?


6
我的问题旨在更多地遵循“仅使用stoul有一些非显而易见的缺点”的思路。显然,这将与模板实例化混为一谈,但是还有其他我没有考虑的东西吗?关于为什么将其遗漏的评论会很好,但是是次要的。
David Stone

12
@NicolBolas我看不到为什么这没有建设性。这是一个完全正确的问题,因为我看不到这种不一致的任何原因,并且回答者可能会深入了解一些可能存在的有效原因,但不是显而易见的原因。
Christian Rau 2012年

4
@SethCarnegie嗯,您的平台(也许是大多数平台)所做的事情是无关紧要的,因为unsigned long公正是没有的unsigned int
Christian Rau 2012年

4
@SethCarnegie:在我的典型计算机上,unsigned long是64位和unsigned int32 位。它们是不同的类型,不能假定彼此相同。
Mike Seymour 2012年

2
@NicolBolas就像说的那样,OP(和我)并不知道它是投机的,因为它可能完全有一个正当的理由埋在C ++语言的内部。但是由于您说的是推测性的,所以我想没有这样的原因。但同样,也许负责C ++ 11的人仍然可以回答。这不是“哇哇,那该死stou的问题在哪里”,而是一个问题,要求为这种明显的不一致提供可能的肯定原因。如果您知道没有这种原因,那么请将其发布为答案。
Christian Rau 2012年

Answers:


29

最贴切的答案是C库没有相应的“ strtou”,并且C ++ 11字符串函数只是C库函数周围的薄薄包装物:std::sto*函数镜像strto*,而std::to_string函数use sprintf


编辑:作为KennyTM指出,无论是stoistol使用strtol作为底层转换功能,但它仍然是神秘的,为什么而存在stoul使用strtoul,也没有相应的stou


14
您知道C ++委员会为什么决定采用这种C-ish方法吗?类似的东西boost::lexical_cast<>()似乎是一种更C ++的处理方式。
保罗·曼塔2012年

2
这些实施细节真的是标准定义的吗?
Lightness Races in Orbit

4
@LightnessRacesinOrbit:对于sto*,C ++ 11 21.5 / 1:效果:前两个函数调用strtol(str.c_str(),ptr,base),后三个函数调用strtoul(str.c_str(),ptr,base ),strtoll(str.c_str(),ptr,base)和strtoull(str.c_str(),ptr,base)。
Mike Seymour 2012年

12
C ++标准是否说“必须通过调用...来实现”并不重要,因为C ++标准仍然具有全局的as-if规则:如果该标准说std::sto*必须作为C库函数的包装器实现,并且一个有效的程序不能告诉他们没有秘密地实现它们,实现是有效的。

2
我认为完全不合主题的是,不使用像Boost / lexical_cast这样的iostream的实际原因是纯粹的性能。我相信iostream会在相当大的程度上输给strtoul等。
Kerrek SB 2012年

22

我不知道为什么stoi存在,但不知道为什么stou,但是stoul和假设之间的唯一区别stou是检查结果是否在以下范围内unsigned

unsigned stou(std::string const & str, size_t * idx = 0, int base = 10) {
    unsigned long result = std::stoul(str, idx, base);
    if (result > std::numeric_limits<unsigned>::max()) {
        throw std::out_of_range("stou");
    }
    return result;
}

(同样,stoi它也类似于stol,只是具有不同的范围检查;但是由于它已经存在,因此无需担心确切地实现它。)


stoistol,或stol和之间的差异stoll也仅是范围检查。
侯赛因

1
@侯赛因:在stoi和之间stol,是的。但是,stol并且stoll不仅在范围检查方面没有区别,它们调用了不同的库函数。
Ben Voigt 2014年

0
unsigned long ulval = std::stoul(buf);
unsigned long mask = ~0xffffffffl;
unsigned int uival;
if( (ulval & mask) == 0 )
    uival = (unsigned int)ulval;
else {
    ...range error...
}

使用掩码以掩码中表示的位数表示的期望值大小来执行此操作,将使其适用于64位长对32位整数,但也适用于32位长对32位整数。

在64位长的情况下,〜0xffffffffl将变为0xffffffff00000000,因此将查看是否设置了前32位中的任何一位。如果使用32位长,则〜0xffffffffl变为0x00000000,掩码检查将始终为零。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.