Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

Преобразование огромных чисел

#cpp


Преобразую значения из string в long long

val = atoll(a[i].c_str());


Как защититься от Васи Пупкина, который записал число, которое большее максимального
(9223372036854775807)?
Нужно приравнивать val к 0.

Программа ошибок не выдаёт, однако наличие такой недоработки меня напрягает.
    


Ответы

Ответ 1



Ну, как вариант - использовать stoll и перехватывать исключения... int main(int argc, const char * argv[]) { string s; cin >> s; long long l; try { l = stoll(s); } catch(out_of_range&) { l = 0; } catch(invalid_argument&) { l = -1; } cout << "s = " << s << endl; cout << "l = " << l << endl; }

Ответ 2



Функции группы ato.. были [полу-]официально "покинуты" стандартом языка С еще в 1995 году (cм. http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf). Они не предоставляют никаких средств для обработки ошибочных ситуаций. В стандартной библиотеке С им на смену пришли функции группы strto..., которые предоставляют такие средства. Эти функции не были официально объявлены obsolescent из-за их широкой распространенности в старом коде. Также они потенциально могу быть реализованы более эффективно, чем функции группы strto.... Однако реальные реализации этим обычно не занимаются, а просто делегируют вызовы ato... в strto... с игнорированием потенциальных ошибок. Поэтому если вы по какой-то причине настаиваете на использовании С-функций для решения подобных задач, забудьте о существовании функций группы ato... - это "мертвые" функции. Пользуйтесь функциями группы strto.... Разумеется, учитывая, что ваш вопрос помечен тегом [C++], вам лучше просто воспользоваться аналогичными средствами стандартной библиотеки С++.

Ответ 3



Это наиболее быстрая реализация приведения, из мне известных. Она да, требует некоторую проверку на этапе компиляции, но работает, как часы. В цикл while (*p >= '0' && *p <= '9') надо добавить проверку на длину строки, соответствующую длине максимального числа. Типом возвращаемого значения можно играть. Должно работать в разы быстрее зачтенного варианта. STATIC_ASSERT(1 == '1' - '0'); STATIC_ASSERT(2 == '2' - '0'); STATIC_ASSERT(3 == '3' - '0'); STATIC_ASSERT(4 == '4' - '0'); STATIC_ASSERT(5 == '5' - '0'); STATIC_ASSERT(6 == '6' - '0'); STATIC_ASSERT(7 == '7' - '0'); STATIC_ASSERT(8 == '8' - '0'); STATIC_ASSERT(9 == '9' - '0'); int to_int(const char *p) { while (*p == ' ') ++p; int r = 0; bool neg = false; if (*p == '-') { neg = true; ++p; } while (*p >= '0' && *p <= '9') { r = (r*10) + (*p - '0'); ++p; } if (neg) { r = -r; } return r; }

Ответ 4



std::string s="922337203685477580712324567878"; size_t index; long long l=std::stoll(s, &index); if(index!=s.size()) throw std::runtime_error("bad number");

Комментариев нет:

Отправить комментарий