Name already in use
cpp-docs / docs / c-runtime-library / reference / gets-s-getws-s.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Gets a line from the stdin stream. These versions of gets , _getws have security enhancements, as described in Security features in the CRT.
buffer
Storage location for input string.
sizeInCharacters
The size of the buffer.
Returns buffer if successful. A NULL pointer indicates an error or end-of-file condition. Use ferror or feof to determine which one has occurred.
The gets_s function reads a line from the standard input stream stdin and stores it in buffer . The line consists of all characters up to and including the first newline character (‘ \n ‘). gets_s then replaces the newline character with a null character (‘ \0 ‘) before returning the line. In contrast, the fgets_s function retains the newline character.
If the first character read is the end-of-file character, a null character is stored at the beginning of buffer , and NULL is returned.
_getws_s is a wide-character version of gets_s ; its argument and return value are wide-character strings.
If buffer is NULL or sizeInCharacters is less than or equal to zero, or if the buffer is too small to contain the input line and null terminator, these functions invoke an invalid parameter handler, as described in Parameter validation. If execution is allowed to continue, these functions return NULL and set errno to ERANGE .
In C++, using these functions is simplified by template overloads; the overloads can infer buffer length automatically (eliminating the need to specify a size argument) and they can automatically replace older, non-secure functions with their newer, secure counterparts. For more information, see Secure template overloads.
By default, this function’s global state is scoped to the application. To change this behavior, see Global state in the CRT.
Generic-text routine mappings
| TCHAR.H routine | _UNICODE and _MBCS not defined | _MBCS defined | _UNICODE defined |
|---|---|---|---|
| _getts_s | gets_s | gets_s | _getws_s |
| Routine | Required header |
|---|---|
| gets_s | <stdio.h> |
| _getws_s | <stdio.h> or <wchar.h> |
The console isn’t supported in Universal Windows Platform (UWP) apps. The standard stream handles that are associated with the console, stdin , stdout , and stderr , must be redirected before C run-time functions can use them in UWP apps. For more compatibility information, see Compatibility.
gets, gets_s
str в случае успеха, нулевой указатель в случае неудачи.
Если сбой был вызван состоянием конца файла,дополнительно установите параметр eof индикатор (см. feof() ) на stdin . Если сбой был вызван какой-либо другой ошибкой, устанавливает error индикатор (см. ferror() ) на stdin .
Notes
Функция gets() не выполняет проверку границ, поэтому эта функция чрезвычайно уязвима для атак переполнения буфера. Его нельзя безопасно использовать (если только программа не работает в среде, которая ограничивает то, что может появиться в stdin ) По этой причине эта функция устарела в третьем исправлении к стандарту C99 и вообще удалена в стандарте C11. fgets() и gets_s() — рекомендуемые замены.
Функция gets_s() своими руками
В этой статье мы рассмотрим хорошо известную проблему, связанную с использованием в языке C99 функции gets() . Эта функция считывает строку из стандартного потока и помещает её в заданный буфер в виде C-строки. Проблема заключается в том, что использование этой функции небезопасно, поскольку может привести к переполнению буфера.
В наших программах, которые мы будем писать в дальнейшем, нам придётся считывать строки из стандартного потока очень часто. Мы не будем делать это с помощью функции gets() , а напишем альтернативную ей функцию, которая будет лишена описанного выше недостатка.
Для начала рассмотрим функцию gets() более подробно. gets() — это стандартная библиотечная функция, описанная в заголовочном файле stdio.h . Она имеет следующий прототип:
Функция принимает в качестве параметра адрес массива символов и считывает строку из стандартного потока, помещая её в данный массив. Функция возвращает этот же адрес в случае успеха или нулевой адрес в случае неудачи. Считывание строки заканчивается после того, как встречается символ новой строки (при этом он не записывается в массив) или значение EOF (макрос EOF определён в файле stdio.h ; компилятор MinGW64 «приписывает» EOF значение -1). После завершения считывания в массив записывается завершающий нулевой символ.
При считывании функцией gets() строки, количество символов в которой, увеличенное на единицу, превышает размер массива, символы, «не помещающиеся» в массив, записываются в область памяти, уже «не принадлежащую» массиву. Данные, расположенные в этой области, будут уничтожены, что может привести к непредсказуемым (в общем случае) последствиям. Впрочем, такое переполнение буфера может и не помешать успешному выполнению программы. Однако это не означает, что оно допустимо.
Пользователь программы, считывающей информацию из стандартного потока с помощью функции gets() , всегда может добиться переполнения буфера, введя строку чрезмерной длины. По этой причине данную функцию не рекомендуется использовать. В качестве исключения, её можно вызывать в программах, единственным пользователем которых является их автор.
В языке C99 функция gets() объявлена как «осуждаемая» (deprecated). Она оставлена в стандарте лишь для совместимости с предыдущей версией языка — C89. В стандарте C11 функция gets() уже отсутствует. Она заменена своей безопасной версией — gets_s() .
Функция gets_s() не входит в стандартную библиотеку C99, но мы создадим «свой» вариант этой функции самостоятельно. Наша функция будет иметь следующий прототип:
Отличие этой функции от gets() заключается в том, что в символьный массив, адресуемый параметром str , будет записано не более num — 1 символов из входного потока (последним символом будет записан нулевой завершающий символ). Если в потоке имеется более num — 1 символов, то «лишние» символы будут проигнорированы.
Функция gets_s() будет основана на функции fgets() из стандартной библиотеки stdio.h , имеющей следующий прототип:
Функция принимает в качестве первого параметра адрес массива символов и считывает строку из входного потока, адресуемого третьим параметром, записывая в массив не более num — 1 символов из данного потока. Функция возвращает адрес массива в случае успеха или нулевой адрес в случае неудачи. Считывание строки заканчивается после того, как встречается символ новой строки (при этом он записывается в массив, если его позиция в считываемой строке не превышает num — 1 ) или значение EOF . После завершения считывания в массив записывается завершающий нулевой символ.
Мы вызовем из функции gets_s() функцию fgets() , передав ей в качестве первого и второго аргументов значения первого и второго формальных параметров функции gets_s() соответственно, а в качестве третьего аргумента — стандартный входной поток stdin (макрос, определённый в файле stdio.h ).
Затем мы проверим, не записан ли в массиве, адресуемом указателем str , символ новой строки » \n «. Этот символ может быть записан только перед завершающим нулевым символом. Для выяснения возможной позиции символа » \n » мы найдём длину C-строки, адресуемой переменной str , и вычтем из неё единицу. Длину строки будем находить с помощью функции strlen() из стандартной библиотеки string.h , содержащей функции обработки C-строк. Если символ новой строки обнаружится, то мы запишем на его место завершающий нулевой символ, уменьшив, тем самым, длину C-строки на единицу.
Наконец, функция gets_s() будет возвращать значение, возвращённое функцией fgets() . Ниже приведён код функции gets_s() .
Напишем простую функцию main() для тестирования функции gets_s() :
Тестовая программа считывает из входного потока не более 9 символов и помещает их в символьный массив string , после чего выводит его содержимое на печать. Поместим, в качестве эксперимента, во входной поток (в нашем случае — на консоль) 10 символов:
Как мы видим, программа отработала корректно. Итак, функция gets_s() реализована, и мы сможем смело использовать её в наших будущих программах!
С++ — gets_s() и указатели на символьный массив
Недавно начал изучать C++ по книге Шилдта «С++ базовый курс» и изучая указатели и их взаимодействие с символьными массивами , столкнулся с дикой проблемой. То ли код в книге устарел , то ли VS 2012 подводит но у меня полные разногласия между gets() и любыми символьными массивами а еще большая проблема это полный отказ gets_s() (Которая работает с символьными массивами и является верной функцией) считывать данные в указатель символьного массива. По Шилдту код корректен,заголовочные файлы указаны все что нужно. В чем может быть проблема? В общем вся суть проблемы в том что gets() вовсе не работает и что gets_s() не выполняет все нужные функции. Ниже код из книги Шилдта под копирку.
Попробуйте следующую аналогичную программу
то вывод программы будет выглядеть следующим образом
Функция gets уже не поддерживается стандартом C, так как она небезопасная. Что касается функции gets_s , то перед включением файла <stdio.h> необходимо объявить константу
Тем не менее в C++ это может не сработать.
Поэтому в выше приведенной программе я заменил вызов gets_s на вызов fgets . Разница между функциями состоит в том, что последняя также считывает символ новой строки, генерируемый нажатием клавиши Enter. Поэтому в условии цикла я использую сравнение следующего вида
чтобы исключить из сравнения строк этот символ новой строки (как видно из вывода программы, его код равен 10), присутствующей в переменной s .
Наверное далее в книге вы познакомитесь с функциями ввода для строк, имеющимся в языке C++, как, например, get или getline , которые следует использовать вместо функций C.