Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, vadfromnu, Вы писали:
V>>В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval.
_>Действительно https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c
_>Тогда так:
Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь?
ЗЫ Моя версия, не факт, что рабочая — просто по-человечески переписал даденое. Да, в три раза длиннее получилось, если считать по строчкам
| Скрытый текст |
| #include <stdlib.h>
struct int_parsing_traits
{
// Методы не упаковываем в одну строчку (хотя они очень просятся) чтобы можно было
// остановится в отладчике и посмотреть одновременно на входной параметр, и на условие
bool is_space(char c) const
{
return c>0 && c<=32;
}
bool is_digit(char c) const
{
return c>='0' && c<='9';
}
bool is_sign(char c) const
{
return c=='-' || c=='+';
}
bool is_negate_sign(char c) const
{
return c=='-';
}
int to_digit(char c) const
{
return (c>='0' && c<='9') ? c-'0' : -1;
}
// Решили, что системой счисления управляет ParsingTraits
unsigned get_base() const
{
return 10;
}
}; // struct int_parsing_traits
template<typename ParsingTraits>
inline
int getint( const char *p, int defval = 0, const ParsingTraits &parsingTraits = int_parsing_traits() )
{
// skip leading whitespaces
while( *p && parsingTraits.is_space(*p) )
p++;
// check for leading sign
if (!parsingTraits.is_sign(*p))
return defval;
bool neg = false;
// is negative number?
if (parsingTraits.is_negate_sign(*p))
neg = true;
unsigned resultAbs = 0;
while(*p && parsingTraits.is_digit(*p))
{
int digit = parsingTraits.to_digit();
// Тут можно вставить проверку на систему счисления,
// а можно положится, что ParsingTraits сама знает, что делает
if (digit<0)
break;
// А тут мы уже точно решили, что ParsingTraits знает систему счисления
unsigned newRes = resultAbs * parsingTraits.get_base() + (unsigned)digit;
if (newRes<resultAbs)
return defval; // переполнились
resultAbs = newRes;
p++;
}
// Пробегаем по оставшейся строке, надеясь, что она состоит из пробелов
while(*p && parsingTraits.is_space(*p))
++p;
if ( *p && !parsingTraits.is_space(*p) )
return defval; // стопанули на чём-то, не похожем на цифру или пробел
int result = (int)resultAbs;
if (neg)
result = -result;
if (unsigned(result)!=resultAbs)
return defval; // переполнение при смене знака
return result;
}
|
| |