Форум программистов, компьютерный форум, киберфорум
Loafer
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Преобразование строки в число

Запись от Loafer размещена 02.10.2020 в 14:42
Показов 2094 Комментарии 5
Метки c++

Функция, проверяющая, что входная строка содержит корректное для заданного целочисленного типа значение в пределах допустимых значений. На вход передается строка, а необходимый целочисленный тип задается как параметр шаблона.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
bool check_is_integral(const std::string& str) {
  // Случай str == ''
  if (str.empty()) {
    return false;
  }
 
  // Случай str == '+' или str == '-'
  if (str.length() == 1 && (str[0] == '-' || str[0] == '+')) {
    return false;
  }
 
  // Случай str == '000' или str == '+000' или str == '-000'
  std::size_t begin = 0;
  if (str[begin] == '-' || str[begin] == '+') {
    begin++;
  }
  while (begin < str.length() && str[begin] == '0') {
    begin++;
  }
  if (begin >= str.length()) {
    return true;
  }
 
  // Основной алгоритм
  begin = 0;
  bool is_negative = false;
 
  if (std::is_signed<T>::value) {
    if (str[begin] == '-') {
      is_negative = true;
    }
    if (str[begin] == '-' || str[begin] == '+') {
      begin++;
    }
  } else if (str[begin] == '+') {
    begin++;
  }
 
  // Убираем ведущие нули
  while (str[begin] == '0') {
    begin++;
  }
 
  // Случай str == '1234a56'
  for (std::size_t i = begin; i < str.length(); ++i) {
    if (!std::isdigit(str[i])) {
      return false;
    }
  }
 
  // Проверка границ
  std::string ref_value =
      is_negative ? std::to_string(std::numeric_limits<T>::min()).substr(1)
                  : std::to_string(std::numeric_limits<T>::max());
 
  if ((str.length() - begin) < ref_value.length()) {
    return true;
  } else if ((str.length() - begin) > ref_value.length()) {
    return false;
  } else {
    for (std::size_t i = begin; i < str.length(); ++i) {
      if (ref_value[i - begin] > str[i]) {
        return true;
      } else if (ref_value[i - begin] < str[i]) {
        return false;
      }
    }
  }
 
  return true;
}
Метки c++
Размещено в C++
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 5
Комментарии
  1. Старый комментарий
    Аватар для Avazart
    Чем это лучше чем использовать std::strtoX...

    Например как я тут https://github.com/Avazart/Arg... ingUtils.h см ф-цию convert
    Запись от Avazart размещена 02.10.2020 в 15:54 Avazart вне форума
  2. Старый комментарий
    Аватар для Loafer
    Цитата Сообщение от Avazart
    Чем это лучше чем использовать std::strtoX...

    Например как я тут https://github.com/Avazart/Arg... ingUtils.h см ф-цию convert
    Функции из разряда std::strtoX, которые работают с беззнаковыми типами, не считают за ошибку, если им на вход приходит строка, представляющая собой отрицательное число.
    Плюс интрейфейс удобный. Если нужно проверить, что значение в строке str лежит в пределах типа int, то функцию надо использоваться следующим способом:
    C++
    1
    
    bool result = check_is_integral<int>(str);
    Запись от Loafer размещена 02.10.2020 в 16:02 Loafer вне форума
  3. Старый комментарий
    Аватар для Avazart
    Да если Вы видели я это в своем коде это учел.
    Запись от Avazart размещена 02.10.2020 в 18:55 Avazart вне форума
  4. Старый комментарий
    Аватар для Loafer
    Цитата Сообщение от Avazart
    Да если Вы видели я это в своем коде это учел.
    Вот в этом месте, наверное:
    C++
    1
    2
    
    if(is_unsigned_v<T> && s[0] == CharT('-'))
        throw out_of_range("out of range");
    Но под каждый целочисленный тип данных у Вас своя функция. А что делать, если надо преобразовать в std::size_t? В зависимости от архитектуры процессора (x86 или amd64) тип имеет разный размер.
    Запись от Loafer размещена 02.10.2020 в 19:41 Loafer вне форума
  5. Старый комментарий
    Аватар для Avazart
    Да наверное под size_t тоже стоило свою ф-цию завести.
    Но если Вы заметили все ф-ции вызывают шаблонную ф-цию convert так что с этим не должно быть проблем.

    Т.е. как то так:

    C++
    1
    2
    3
    4
    5
    
    template<typename CharT>
    auto strToSizeT(const std::basic_string<CharT>& s)
    {
      return detail::convert<unsigned long long,size_t>(s,std::strtoull,std::wcstoull);
    };
    P.S: Смотря на этот случай понял что стоит написать проверку по размерам типов, а не равенству типов.
    Запись от Avazart размещена 03.10.2020 в 11:00 Avazart вне форума
 
Новые блоги и статьи
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru