Он разбивает вашу программу в этом случае, потому что scanf()
имеет
неотъемлемо
небезопасный интерфейс для строк. Он не знает, что ваш параметр ch
- это массив, достаточно большой, чтобы содержать 9-символьную строку плюс ее завершающий нуль. В результате, он с удовольствием продолжает читать символы от stdin
и хранить их в памяти уже за конец массива.
Если ваша программа выходит из строя, вам действительно повезло. В худшем случае злоумышленник использовал тщательно обработанную строку для управления содержимым стека таким образом, чтобы получить контроль над вашим компьютером. Это пример атаки переполнения буфера. Это звучит маловероятно, но это было зафиксировано в большом количестве случаев.
Используется только для номеров, scanf
, как правило, достаточно безопасен, но он не очень хорошо справляется с ошибками ввода. В результате обычно рекомендуется использовать что-то вроде fgets()
для чтения ввода (у него есть параметр длины буфера для управления переполнением) и sscanf()
для анализа из этого буфера, проверяя его возвращаемые значения для здравомыслия по мере того, как вы идете.
Edit: Как комментарий от R пунктов, я преувеличила опасности, связанные с интерфейсом scanf
. С осторожностью использовать спецификатор ширины поля для всех строк, scanf
становится более безопасным. Но тогда вы берете на себя ответственность за обеспечение того, чтобы указанная ширина соответствовала содержимому буфера. Например, вы должны написать scanf("%9s",ch);
, потому что ваш буфер был объявлен как десять байтов, и вам нужно место для завершения нулевого.
Обратите внимание, что вы также должны тестировать возвращаемое значение от scanf()
. Он возвращает количество успешно совпадающих полей или EOF
, если произошла ошибка ввода-вывода. Он может вернуть 0, если пользователь ввел «abc», когда он ожидал, например, числа.
Интерфейс безопасен, если вы используете его правильно: '% 9s'. –
спасибо, это помогло – mielacademy
@R., Ну, правда. Обратите внимание, что довольно неудобно поддерживать синхронизацию размера буфера с спецификатором формата. Это одна из причин, по которой настоятельно рекомендуется использовать 'fgets()', за которым следует более сильный синтаксический анализатор. – RBerteig