Участник:softwayer/scanf

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

scanf — это функция, читающая данные заданного формата from a given string stream source, originated from Си, and is present in many other programming languages.

Прототип функции scanf:

int scanf(const char *format, ...);

Функция возвращает the total number of items successfully matched, which can be less than the number requested. If the input stream is exhausted or reading from it otherwise fails before any items are matched, EOF is returned.

So far as is traceable, "scanf" stands for "scan format", because it scans the input for valid tokens and parses them according to a specified format.

Использование

[править | править код]

Функция scanf в C считывает числа и другие типы данных из стандартного ввода (часто интерфейс командной строки или аналогичный вид текстового интерфейса пользователя).

Этот код на Си считывает несколько целых чисел из консоли и выводит каждое из них на отдельной строке:

#include <stdio.h>

int main()
{
    int n;
    while (scanf("%d", &n) == 1)
        printf("%d\n", n);
    return 0;
}

После выполнения этой программы нагромождение целых чисел вроде

456 123 789     456 12
456 1
      2378

получится аккуратным:

456
123
789
456
12
456
1
2378

Чтобы вывести слово:

#include <stdio.h>

int main()
{
    char word[20];
    if(scanf("%19s", word) == 1)
        puts(word);
    return 0;
}

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

Так как scanf считывает данные только со стандартного ввода, многие языки программирования с interfaces, такие как PHP, имеют разновидности вроде sscanf или fscanf вместо самого scanf.

Разновидности scanf

[править | править код]

Depending on the actual source of input, программисты могут использовать различные разновидности scanf. Two common examples are sscanf and fscanf.

fscanf считывает данные из заданного файла. Вот её прототипы:

(C или C++)

int fscanf (FILE *file, const char *format, ...);

(PHP)

mixed fscanf (resource file, const string format [, mixed args...])

The fscanf derivative works like the original scanf function - parts of the input, once read, will not be read again until the file is closed and reopened.

sscanf считывает данные из строки символов, заданной в первом аргументе. The prototypes are as follows:

(C or C++)

int sscanf (const char *str, const char *format, ...);

(PHP)

mixed sscanf (const string str, const string format [, mixed args...])

vscanf, vsscanf, and vfscanf

[править | править код]
int vscanf (const char *format, va_list args);
int vsscanf (const char *source, const char *format, va_list args);
int vfscanf (FILE *file, const char *format, va_list args);

These are like the same functions without the v prefix, except they take their arguments from a va_list. (See stdarg.h.) These variants may be used in variable-argument functions.

Format string specifications

[править | править код]

The formatting placeholders in scanf are more or less the same as that in printf, its reverse function.

There are rarely constants (i.e. characters that are not formatting placeholders) in a format string, mainly because a program is usually not designed to read known data. The exception is one or more whitespace characters, which discards all whitespace characters in the input.

Some of the most commonly used placeholders follow:

  • '%d' : Считать целое десятичное число.
  • '%i' : Scan an integer as a signed number. Similar to '%d', but interprets the number as hexadecimal when preceded by "0x" and octal when preceded by "0". For example, the string "031" would be read as 31 using '%d', and 25 using '%i'.
  • '%u' : Scan for decimal unsigned int, unsigned short, and unsigned char (Note that in the C99 standard the input value "-" sign is optional, so if a negative number is read, no errors will arise and the result will be the two's complement. See strtoul()).
  • '%f' : Scan a floating-point number in normal (fixed-point) notation.
  • '%g', '%G' : Scan a floating-point number in either normal or exponential notation. '%g' uses lower-case letters and '%G' uses upper-case.
  • '%x', '%X' : Scan an integer as an unsigned hexadecimal number.
  • '%o' : Scan an integer as an octal number.
  • '%s' : Считать строку. The scan terminates at whitespace. A null character is stored at the end of the string, which means that the buffer supplied must be at least one character longer than the specified input length.
  • '%c' : Считать символ (char). Нулевого символа не добавляется.
  • '(space)': Space scans for whitespace characters.
  • '%lf' : Считать число с плавающей точкой типа double.
  • '%Lf' : Считать число с плавающей точкой типа long double.

The above can be used in compound with numeric modifiers and the 'l', 'L' modifiers which stand for "long" in between the percent symbol and the letter. There can also be numeric values between the percent symbol and the letters, preceding the "long" modifiers if any, that specifies the number of characters to be scanned. An optional asterisk (*) right after the percent symbol denotes that the datum read by this format specifier is not to be stored in a variable. No argument behind the format string should be included for this dropped variable.

The "ll" and "ff" modifiers in printf are not present in scanf, causing differences between modes of input and output.

An example of a format string is

"%7d%s %c%lf"

The above format string scans the first seven characters as a decimal integer, then reads the remaining as a string until a space, new line or tab is found, then scans the first non-whitespace character following and a double-precision floating-point number afterwards.

scanf is usually used in situations when the program cannot guarantee that the input is in the expected format. Therefore a robust program must check whether the scanf call succeeded and take appropriate action. If the input was not in the correct format, the erroneous data will still be on the input stream and must be read and discarded before new input can be read. An alternative method of reading input, which avoids this, is to use fgets and then examine the string read in. The last step can be done by sscanf, for example.

Безопасность

[править | править код]

Как и printf, scanf is vulnerable to format string attacks. Great care should be taken to ensure that the formatting string includes limitations for string and array sizes. In most cases the input string size from a user is arbitrary; it can not be determined before the scanf function is executed. This means that uses of '%s' placeholders without length specifiers are inherently insecure and exploitable for buffer overflows. Another potential problem is to allow dynamic formatting strings, for example formatting strings stored in configuration files or other user controlled files. In this case the allowed input length of string sizes can not be specified unless the formatting string is checked beforehand and limitations are enforced. Related to this are additional or mismatched formatting placeholders which do not match the actual vararg list. These placeholders might be partially extracted from the stack, contain undesirable or even insecure pointers depending on the particular implementation of varargs.

  • scanf(3): input format conversion — страница справки man по библиотечным функциям GNU/Linux  (англ.)

Category:Stdio.h