Как проверить вход с помощью scanf

Вы можете использовать трюк форматирования JSON в SQL Developer.

enter image description here

Полный сценарий:

CREATE TABLE JSON_SO (
    "1"   INTEGER,
    "2"   INTEGER,
    "3"   INTEGER,
    "4"   INTEGER,
    "5"   INTEGER,
    "6"   INTEGER
);

INSERT INTO JSON_SO VALUES (
    40,
    20,
    22,
    10,
    0,
    0
);

select /*json*/ * from json_so;

И вывод при выполнении с F5 (Выполнить как сценарий):

[ 111]

Обратите внимание, что вывод JSON происходит на стороне клиента через SQL Developer (это также работает в SQLcl), и я отформатировал вывод JSON для отображения здесь, используя https://jsonformatter.curiousconcept.com/ ] в JSON для вас.

5
задан Raúl Roa 19 January 2009 в 01:34
поделиться

6 ответов

Используя scanf() обычно плохая идея для ввода данных пользователем, так как отказ уезжает FILE указатель в неизвестном положении. Поэтому scanf обозначает "сканирование, отформатированное", и там является немного более бесформатным, чем ввод данных пользователем.

Я предложил бы использовать fgets() вкладывать строку, сопровождаемую sscanf() на строке, чтобы на самом деле проверить и обработать его.

Это также позволяет Вам проверять строку на те символы, которых Вы требуете (или через цикл или с регулярным выражением), что-то который scanf семейство функций действительно не подходит для.

Как пример, использование scanf() с a "%d" или "%f" остановится в первом несимволе числа, так не зафиксирует запаздывание ошибок как "127hello", который просто даст Вам 127. И использование его с неограниченным %s просто просит о переполнении буфера.

Если действительно необходимо использовать [] спецификатор формата (в scanf или sscanf), я не думаю, что это предназначено, чтобы сопровождаться s.

И для устойчивого входного решения с помощью того совета посмотрите здесь. После того как у Вас есть входная строка как строка, Вы можете sscanf к Вашему содержанию основ.

15
ответ дан 18 December 2019 в 10:49
поделиться

Вы, кажется, хотите проверить строку, как введено. Это зависит от того, хотите ли Вы проверить ту свою строку, содержит двойное или интервал. Следующие проверки на двойное (ведущий и запаздывающий пробел позволяется).

bool is_double(char const* s) {
    int n;
    double d;
    return sscanf(s, "%lf %n", &d, &n) == 1 && !s[n];
}

sscanf возвратит преобразованные объекты (без '%n'). n будет установлен на сумму обработанных вводимых символов. Если весь вход был обработан, s [n] возвратит завершение 0 символов. Пространство между этими двумя спецификаторами формата составляет дополнительный запаздывающий пробел.

Следующие проверки на интервал, те же методы использовали:

bool is_int(char const* s) {
    int n;
    int i;
    return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
}

Был вопрос на том здесь, которые включают также больше C++ 'выход пути к тому, чтобы сделать это, как использование строковых потоков и функций от повышения, как lexical_cast и так далее. Они должны обычно предпочитаться по функциям как scanf, так как очень легко забыть передавать некоторый '%' scanf или некоторый адрес. scanf не распознает, что, но вместо этого сделает произвольные вещи, в то время как lexical_cast, например, выдаст исключение, если что-нибудь не будет правильно.

5
ответ дан 18 December 2019 в 10:49
поделиться

Мой подход должен был бы считать ввод данных пользователем в строку и затем преобразовать его в долгое использование strtol(). strtol() указатель возвратов на первый символ во входной строке, которую этому не удалось обработать так путем проверки этого символа, который Вы будете знать, была ли полная строка проанализирована, как это:

char *string;
char *endptr;
long result;

scanf("%as", string);
errno = 0;
result = strtol(string, &endptr, 10);
if (ERANGE == errno)
    printf("Input number doesn't fit into long\n");
else if (*endptr)
    printf("%s is not a valid long number - it contains invalid char %c\n",
        string, *endptr);
else
    printf("Got %ld\n", result);

В этом отрывке scanf() проинструктирован для автоматического выделения string достаточно большой модификатор формата использования "a" (это - расширение GNU). Если Вы не находитесь на GNU, выделяете string вручную и предел макс. размер в scanf() формат.

Этот подход позволяет лучшую обработку ошибок.

1
ответ дан 18 December 2019 в 10:49
поделиться

При попытке считать число только, используйте:

int i;
scanf( "%d", &i );

Если необходимо сделать более сложную проверку, необходимо будет сделать это сами. Scanf не сделает этого для Вас.

-1
ответ дан 18 December 2019 в 10:49
поделиться

"buf" должен быть указателем. Похоже, что Вы являетесь передающими значением.

-4
ответ дан 18 December 2019 в 10:49
поделиться

Чему Вы указали в первом аргументе scanf спецификаторы преобразования. scanf попытается преобразовать вход в формат, но иногда Вы могли бы быть удивлены, против чего он будет соответствовать :)

Первая проверка, которую необходимо сделать, находится на возвращаемом значении от scanf (это даст Вам количество соответствия исходным данным). Если Вы не получите число, то Вы ожидаете затем, что Вы знаете, что что-то неправильно с входом. В Вашем случае это должно быть 1.

if( scanf("%[0987654321.-]s", buf) == 1 )
{
      if( sanit_check( buf ) ) 
      {
      /* good input */
      }
      else
      {
      /* invalid input */
      }
}
else 
{
/* invalid input */
}

Кроме того необходимо будет сделать Вас собственные проверки работоспособности на преобразовании, которое Вы спросили scanf сделать.

0
ответ дан 18 December 2019 в 10:49
поделиться