所以,我们有int32_t,int16_t,uint64_t等。但是在哪里atoi32,atoi16,atoui64等...? [英] So, we have int32_t, int16_t, uint64_t, etc.. But where are the atoi32, atoi16, atoui64, etc...?
问题描述
我想将表示数字的字符串输入转换为相应的数字类型。问题是我有严格的类型要求,例如,我不能接受 x> = 2 ^ 15 其中 int16_t
值
如何处理这种情况,无需从头开始编写所有转换函数?
p> PS请不要建议 boost :: lexical_cast
- 我已经使用它了。我正在说的功能将通过特定的模板特化来替换 lexical_cast
模板的默认实现,即:
模板<>
inline int32_t lexical_cast< int32_t,char const *>(const char * const& arg)
{
}
template<
inline int16_t lexical_cast< int16_t,char const *>(const char * const& arg)
{
}
...
理想情况下,最好拥有函数,例如 atoi32
, atoi16
, atoiu64
等...
/ strong>
我使用的是VS2010,所以没有运气< cinttypes>
。是的,有一个改进的 atoi
函数家族与 strtol具有相同的错误支持将是很好的
。
EDIT2
思考我值得发布我的解决方案:
#pragma once
#include< boost / lexical_cast.hpp>
#include< limits>
命名空间boost {
模板< class TInt,class conv>
TInt atoi(conv f,const char * arg)
{
char * stop;
TInt res = f(arg,& stop,10);
if(* stop)
{
throw_exception(bad_lexical_cast(typeid(TInt),typeid(const char *)));
}
return res;
}
template< class TInt>
typename std :: enable_if< std :: is_signed< TInt> :: value,TInt> :: type atoi(const char * arg)
{
char * stop;
long res = strtol(arg,& stop,10)
if(* stop || std :: numeric_limits< TInt> :: min()> res || std :: numeric_limits< TInt> :: max()< res)
{
throw_exception(bad_lexical_cast(typeid(TInt),typeid(const char *)));
}
return(TInt)res;
}
template< class TInt>
typename std :: enable_if< std :: is_unsigned< TInt> :: value,TInt> :: type atoi(const char * arg)
{
char * stop;
unsigned long res = strtoul(arg,& stop,10);
if(* stop || std :: numeric_limits< TInt> :: max()< res)
{
throw_exception(bad_lexical_cast(typeid(TInt),typeid(const char *) ));
}
return(TInt)res;
}
模板<> inline int8_t lexical_cast< int8_t,char const *>(const char * const& arg)
{
return atoi< int8_t>(arg)
}
模板<> inline uint8_t lexical_cast< uint8_t,char const *>(const char * const& arg)
{
return atoi< uint8_t>(arg)
}
模板<> inline int16_t lexical_cast< int16_t,char const *>(const char * const& arg)
{
return atoi< int16_t>(arg)
}
模板<> inline uint16_t lexical_cast< uint16_t,char const *>(const char * const& arg)
{
return atoi< uint16_t>(arg)
}
模板<> inline int32_t lexical_cast< int32_t,char const *>(const char * const& arg)
{
return atoi< int32_t>(strtol,arg)
}
模板<> inline uint32_t lexical_cast< uint32_t,char const *>(const char * const& arg)
{
return atoi< uint32_t>(strtoul,arg);
}
模板<> inline int64_t lexical_cast< int64_t,char const *>(const char * const& arg)
{
return atoi< int64_t>(_ strtoi64,arg)
}
模板<> inline uint64_t lexical_cast< uint64_t,char const *>(const char * const& arg)
{
return atoi< uint64_t>(_ strtoui64,arg);
}
模板<> inline double lexical_cast< double,char const *>(const char * const& arg)
{
char * stop;
double res = strtod(arg,& stop);
if(* stop)
{
throw_exception(bad_lexical_cast(typeid(double),typeid(const char *)));
}
return res;
}
模板<> inline float lexical_cast< float,char const *>(const char * const& arg)
{
char * stop;
double res = strtod(arg,& stop);
if(* stop || -FLT_MAX> res || FLT_MAX {
throw_exception(bad_lexical_cast(typeid(float),typeid(const char *)));
}
return res;
}
}
使用 strtol
系列函数。不幸的是,建议使用它的人也删除了他的帖子,我不知道为什么...
函数实现所有必需的转换,< cinttypes> c $> cf> scanf
系列
< inttypes.h>
)定义了适当的格式字符串说明符。例如,要从C字符串 s
中读取 int16_t
,请执行
int16_t i;
std :: sscanf(s,%SCNd16,& i);
I would like to convert a string input representing numbers to the respective numeric types. The problem is that I have strict type requirements, so, for instance, I cannot accept an x >= 2^15 where an int16_t
value (signed) is expected.
How can I deal with this scenario, without writing all the conversion functions from scratch?
P.S.
Please, do not suggest boost::lexical_cast
- I am using it already. The functions I am talking about are going to replace the default implementation of the lexical_cast
template by means of the particular template specializations, namely:
template<>
inline int32_t lexical_cast<int32_t,char const *>(const char * const & arg)
{
}
template<>
inline int16_t lexical_cast<int16_t,char const *>(const char * const & arg)
{
}
...
Ideally, it would be nice to have functions, like atoi32
, atoi16
, atoiu64
, etc...
EDIT
I am using VS2010, so no luck with <cinttypes>
.
Yes, it would be nice to have an improved atoi
family of functions having the same error support as strtol
.
EDIT2
Thought it was worthwhile to post my solution:
#pragma once
#include <boost/lexical_cast.hpp>
#include <limits>
namespace boost {
template<class TInt, class conv>
TInt atoi(conv f, const char *arg)
{
char* stop;
TInt res = f(arg, &stop, 10);
if (*stop)
{
throw_exception(bad_lexical_cast(typeid(TInt), typeid(const char *)));
}
return res;
}
template<class TInt>
typename std::enable_if<std::is_signed<TInt>::value, TInt>::type atoi(const char *arg)
{
char* stop;
long res = strtol(arg, &stop, 10);
if (*stop || std::numeric_limits<TInt>::min() > res || std::numeric_limits<TInt>::max() < res)
{
throw_exception(bad_lexical_cast(typeid(TInt), typeid(const char *)));
}
return (TInt)res;
}
template<class TInt>
typename std::enable_if<std::is_unsigned<TInt>::value, TInt>::type atoi(const char *arg)
{
char* stop;
unsigned long res = strtoul(arg, &stop, 10);
if (*stop || std::numeric_limits<TInt>::max() < res)
{
throw_exception(bad_lexical_cast(typeid(TInt), typeid(const char *)));
}
return (TInt)res;
}
template<> inline int8_t lexical_cast<int8_t,char const *>(const char * const & arg)
{
return atoi<int8_t>(arg);
}
template<> inline uint8_t lexical_cast<uint8_t,char const *>(const char * const & arg)
{
return atoi<uint8_t>(arg);
}
template<> inline int16_t lexical_cast<int16_t,char const *>(const char * const & arg)
{
return atoi<int16_t>(arg);
}
template<> inline uint16_t lexical_cast<uint16_t,char const *>(const char * const & arg)
{
return atoi<uint16_t>(arg);
}
template<> inline int32_t lexical_cast<int32_t,char const *>(const char * const & arg)
{
return atoi<int32_t>(strtol, arg);
}
template<> inline uint32_t lexical_cast<uint32_t,char const *>(const char * const & arg)
{
return atoi<uint32_t>(strtoul, arg);
}
template<> inline int64_t lexical_cast<int64_t,char const *>(const char * const & arg)
{
return atoi<int64_t>(_strtoi64, arg);
}
template<> inline uint64_t lexical_cast<uint64_t,char const *>(const char * const & arg)
{
return atoi<uint64_t>(_strtoui64, arg);
}
template<> inline double lexical_cast<double,char const *>(const char * const & arg)
{
char* stop;
double res = strtod(arg, &stop);
if (*stop)
{
throw_exception(bad_lexical_cast(typeid(double), typeid(const char *)));
}
return res;
}
template<> inline float lexical_cast<float,char const *>(const char * const & arg)
{
char* stop;
double res = strtod(arg, &stop);
if (*stop || -FLT_MAX > res || FLT_MAX < res)
{
throw_exception(bad_lexical_cast(typeid(float), typeid(const char *)));
}
return res;
}
}
So, in the end I am using the strtol
family of functions. Unfortunately, the guy who has suggested to use them has also deleted his post, I wonder why...
The scanf
family of <cstdio>
functions implements all the required conversions, and <cinttypes>
(in C++11; <inttypes.h>
in a combined C++98 compiler with C99 library) defines the appropriate format string specifiers. E.g., to read in an int16_t
from the C string s
, do
int16_t i;
std::sscanf(s, "%"SCNd16, &i);
这篇关于所以,我们有int32_t,int16_t,uint64_t等。但是在哪里atoi32,atoi16,atoui64等...?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!