" предлагаю такое (усовершенствования/замечания — сюда). Рассматривается как исходник :
Имхо много лишних телодвижений
Код
int new_atoi(const char *s)
{
int sign=1, val=0;
if (s) while ((*s == ' ' || *s == '\t') && *(++s)); else return 0;
sign*=(*s == '-' && s++)?-1:((*s == '+' && s++),1);
while (*s>='0' && *s<='9') { val*=10; val+=*s++ - '0'; }
return val*sign;
}
Комментарии:
1. Используется то, что if (a && b) expr; эквивалентно if (a) if (b) expr; т.е. при a==false выражение b не вычисляется
2. Используется то, что if (a || b) expr; эквивалентно if (a) expr; else if (b) expr; т.е. при a==true выражение b не вычисляется
3. Все пишут while (*s) { ... } зачем? Ведь условие *s>='0' && *s<='9' уже обрабатывает такой случай (ибо 0 < '0')
1. Вычисляется *s == '-', если true, то вычисляется s++ (пропускаем '-'), указатель приводится к bool (поскольку он не NULL, то к true), значение && итого true, sign умножается на -1 и получается -1
2. Если не '-', то s++ не вычисляется и переходим ко второй части ?:
3. Аналогично вычисляем надо ли пропускать знак '+', операция запятая всегда даст нам 1, ибо знак положительный по умолчанию
Замеры времени:
Код писался 3 минуты
Пост писался 7 минут
O>Комментарии: O>1. Используется то, что if (a && b) expr; эквивалентно if (a) if (b) expr; т.е. при a==false выражение b не вычисляется O>2. Используется то, что if (a || b) expr; эквивалентно if (a) expr; else if (b) expr; т.е. при a==true выражение b не вычисляется O>3. Все пишут while (*s) { ... } зачем? Ведь условие *s>='0' && *s<='9' уже обрабатывает такой случай (ибо 0 < '0')
O>Подробные комментарии к разбору знака: O>
O>1. Вычисляется *s == '-', если true, то вычисляется s++ (пропускаем '-'), указатель приводится к bool (поскольку он не NULL, то к true), значение && итого true, sign умножается на -1 и получается -1 O>2. Если не '-', то s++ не вычисляется и переходим ко второй части ?: O>3. Аналогично вычисляем надо ли пропускать знак '+', операция запятая всегда даст нам 1, ибо знак положительный по умолчанию
O>Замеры времени: O>Код писался 3 минуты O>Пост писался 7 минут
Здравствуйте orangy, Вы писали:
O>3. Все пишут while (*s) { ... } зачем? Ведь условие *s>='0' && *s<='9' уже обрабатывает такой случай (ибо 0 < '0')
Для лучшего понимания читающими программу, т. к. логически это особый случай. Естественно, любой мало-мальски оптимизирующий компилятор лишнюю проверку отбросит.
Здравствуйте achp, Вы писали:
O>>3. Все пишут while (*s) { ... } зачем? Ведь условие *s>='0' && *s<='9' уже обрабатывает такой случай (ибо 0 < '0')
A>Для лучшего понимания читающими программу, т. к. логически это особый случай. Естественно, любой мало-мальски оптимизирующий компилятор лишнюю проверку отбросит.
Ты не совсем прав. Дело в том, что код годится и для итератора по char (легко изменить и для wchar_t), при этом не факт, что любой компилятор выбросит лишний вызов operator*()
Здравствуйте orangy, Вы писали:
O>Ты не совсем прав. Дело в том, что код годится и для итератора по char (легко изменить и для wchar_t), при этом не факт, что любой компилятор выбросит лишний вызов operator*()
Поправлю сам себя — с итераторами есть проблемка... Не додумал, s++ создаёт лишние временные объекты
для итераторов выглядит так:
template<typename iterator>
int new_atoi(iterator s)
{
int sign=1, val=0;
if (s) while ((*s == ' ' || *s == '\t') && *(++s)); else return 0;
sign*=(*s == '-' && ++s)?-1:((*s == '+' && ++s),1);
while (*s>='0' && *s<='9') { val*=10; val+=*s - '0'; ++s; }
return val*sign;
}
Естественно, этот же шаблон годится и для указателей.
Здравствуйте, Slicer [Wirkwood], Вы писали:
SW>А во что компилится, сравнивали?
да уж наверняка быстрее в пару раз получится. Мы недавно в проекте избавились от большинства CRT-строковых операций. Посмотрите, например, на реализацию isspace из CRT VC7.1 — это просто тихий ужас (времени не хватило, что ли, нормально сделать?). Когда я смотрел на результаты профайлинга — глазам своим не верил, пока не залез в исходники.
Здравствуйте, Andy77, Вы писали:
A>Здравствуйте, Slicer [Wirkwood], Вы писали:
SW>>А во что компилится, сравнивали?
A>да уж наверняка быстрее в пару раз получится. Мы недавно в проекте избавились от большинства CRT-строковых операций. Посмотрите, например, на реализацию isspace из CRT VC7.1 — это просто тихий ужас (времени не хватило, что ли, нормально сделать?). Когда я смотрел на результаты профайлинга — глазам своим не верил, пока не залез в исходники.
A>Извините за оффтоп, накипело :)
А приведенная реализация будет корректно работать со всякими извращенными кодировками, когда на символ может идти больше одного байта?
Такое встречается, если мне не изменяет память, в корейском языке. Так что, если Ваше приложение претендует на корейский рынок, то лучше не тратить время на написание собственных версий isspace. Проверка на пробел как (c == ' ') в любом случае некорректна.
Критика crt от Microsoft неуместна абсолютно, т. к. их crt обрабатывает все возможные варианты.
PS. Для unicode проверка (wc == L' ') также некорректна, т. к. существуют surrogates, когда используется по 4 байта на символ.
]SRC: реализация
dad>вот бы супер быстрый и компактный variant вокруг базовых типов (char, int , long int , etc) dad>и к нему такие же шустрые функции конвертирования..
вот класс value из нашей tool библиотеки (Templated Object Oriented Library)
для хранения строковых значений используется знание того что
tool::string это обертка вокруг ссылки на буфер character c reference counter (string::data) ...
Поэтому операция типа value v = some_string; выполняется тривиальным иннкрементированием счетчика суть быстро.