Страницы

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

воскресенье, 9 февраля 2020 г.

Как определить, является ли заданная строка десятичным представлением натурального числа от 1 до 2^64-1 включительно?

#c #golang


Еще условие: строка не должна начинаться с "0".

Например:


"0" – нет
"1" – да
"07" – нет
"18446744073709551615" (264 − 1) – да
"18446744073709551616" (264) – нет

    


Ответы

Ответ 1



Как вариант: package main import ( "fmt" "strconv" "strings" ) func checkStr(str string) bool { if strings.TrimPrefix(str, "0") != str { fmt.Println("Начинается с 0") return false } if _, err := strconv.ParseUint(str, 10, 64); err != nil { fmt.Println(err) return false } return true } func main() { fmt.Println(checkStr("18446744073709551615")) fmt.Println(checkStr("18446744073709551616")) fmt.Println(checkStr("1b")) fmt.Println(checkStr("-1234567")) fmt.Println(checkStr("07")) }

Ответ 2



Учитывая, что требуется особое поведение для 0, -, пробелов, пределов (264-1), конца строки — не сложнее с нуля распознавание строки как натурального числа реализовать: #include #include bool is_posint64(const char* s) { if (!s || !*s || !('1' <= *s && *s <= '9')) return false; uint64_t n = *s++ - '0'; for ( ; *s; ++s) { if (*s < '0' || *s > '9' || n > UINT64_MAX / 10 || (uint64_t)(*s - '0') > (UINT64_MAX - 10*n)) return false; n = 10*n + (*s - '0'); } return true; } Пример.

Ответ 3



Возможный вариант на си: const static int WIDTH = 21; void f(char *s) { size_t len = strlen(s); if (len == 0) { printf("%*s: empty string\n", WIDTH, s); return; } if (s[0] == '0') { printf("%*s: starts with zero\n", WIDTH, s); return; } if (s[0] == '-') { printf("%*s: negative\n", WIDTH, s); return; } char *last = &s[len]; char *newlast = last; uint64_t n = strtoull(s, &newlast, 10); if (errno != 0) { printf("%*s: error: %s\n", WIDTH, s, strerror(errno)); errno = 0; return; } if (last != newlast) { printf("%*s: extra characters: %s\n", WIDTH, s, newlast); return; } printf("%*s: number %lu\n", WIDTH, s, n); }

Ответ 4



Может кому-то пригодится еще один вариант на C. Число 216 − 1 записано как строка-шаблон. Если в какой-то позиции цифра во входной строке меньше, чем в шаблоне, то приемлемо еще столько же любых цифр, сколько осталось до конца шаблона. Если больше, то на одну меньше. Если равна, то проверяем следующие цифры строки и шаблона. #include #include int validate_index(const char *str) { const char *template = "18446744073709551615"; static int length = 0; if (length == 0) length = strlen(template); int i, length2 = length; // строка пустая или начинается с цифры 0 if (str[0] == '\0' || str[0] == '0') return 0; for (i = 0; i < length; i++) { char c = str[i]; // строка закончена if (c == '\0') return -1; // символ не цифра if (c < '0' || c > '9') return i; // сравнение с шаблоном if (c == template[i]) continue; if (c > template[i]) length2--; break; } for (; i < length2; i++) { char c = str[i]; // строка закончена if (c == '\0') return -1; // символ не цифра if (c < '0' || c > '9') return i; } // строка не закончена if (str[i] != '\0') return i; return -1; } int main() { const char *strs[] = { "0", "1", "07", "1aaa", "12345", "18446744073709551614", "18446744073709551615", "18446744073709551616", "184467440737095516150", "28446744073709551615", "18446744074709551615", }; int i; for (i = 0; i < sizeof strs / sizeof *strs; i++) { int r = validate_index(strs[i]); if (r == -1) printf("\"%s\" - yes\n", strs[i]); else printf("\"%.*s[%c]%s\" - no\n", r, strs[i], strs[i][r], &strs[i][r+1]); } return 0; } Результат: "[0]" - no "1" - yes "[0]7" - no "1[a]aa" - no "12345" - yes "18446744073709551614" - yes "18446744073709551615" - yes "1844674407370955161[6]" - no "18446744073709551615[0]" - no "2844674407370955161[5]" - no "1844674407470955161[5]" - no

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

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