Scanf c описание. Форматированный ввод и вывод

Функция printf() позволяет выводить информацию на экран при программировании в консольном режиме. Данная функция определена в библиотеке stdio.h и имеет следующий синтаксис:

int printf(const char *format [, argument]...);

Здесь первый аргумент *format определяет строку, которая выводится на экран и может содержать специальные управляющие символы для вывода переменных. Затем, следует список необязательных аргументов, которые поясняются ниже. Функуция возвращает либо число отображенных символов, либо отрицательное число в случае своей некорректной работы.

В самой простой реализации функция printf() просто выводит заданную строку на экран монитора:

printf(“Привет мир.”);

Однако с ее помощью можно выводить переменные разного типа: начиная с числовых и заканчивая строковыми. Для выполнения этой операции используются специальные управляющие символы, которые называются спецификаторами и которые начинаются с символа %. Следующий пример демонстрирует вывод целочисленной переменной num на экран монитора с помощью функции printf():

int num;
num = 5;
printf(“%d”, num);

В первых двух строках данной программы задается переменная с именем num типа int. В третьей строке выполняется вывод переменной на экран. Работа функции printf() выглядит следующим образом. Сначала функция анализирует строку, которую необходимо вывести на экран. В данном случае это «%d». Если в этой строке встречается спецификатор, то на его место записывается значение переменной, которая является вторым аргументом функции printf(). В результате, вместо исходной строки «%d» на экране появится строка «5», т.е. будет выведено число 5.

Следует отметить, что спецификатор «%d» выводит только целочисленные типы переменных, например int. Для вывода других типов следует использовать другие спецификаторы. Ниже перечислены основные виды спецификаторов:

%с – одиночный символ
%d – десятичное целое число со знаком
%f – число с плавающей точкой (десятичное представление)
%s – строка символов (для строковых переменных)
%u – десятичное целое без знака
%% - печать знака процента

С помощью функции printf() можно выводить сразу несколько переменных. Для этого используется следующая конструкция:

int num_i;
float num_f;
num_i = 5;
num_f = 10.5;
printf(“num_i = %d, num_f = %f”, num_i, num_f);

Результат выполнения программы будет выглядеть так:

num_i = 5, num_f = 10.5

Кроме спецификаторов в функции printf() используются управляющие символы, такие как перевод строки \n, табуляции \t и др. Например, если в ранее рассмотренном примере необходимо вывести значения переменных не в строчку, а в столбик, то необходимо переписать функцию printf() следующим образом:

printf(“num_i = %d,\n num_f = %f”, num_i, num_f);

Аналогично используется и символ табуляции.

Для ввода информации с клавиатуры удобно использовать функцию scanf() библиотеки stdio.h, которая имеет следующий синтаксис:

int scanf(const char *format [,argument]...);

Здесь, как и для функции printf(), переменная *format определяет форматную строку для определения типа вводимых данных и может содержать те же спецификаторы что и функция printf(). Затем, следует список необязательных аргументов. Работа функции scanf() демонстрируется на листинге 1.4.

Листинг 1.4. Пример использования функции scanf().

#include
int main()
{
int age;
float weight;
printf(“Введите информацию о Вашем возрасте: ”);
scanf(“%d”, &age);
printf(“Введите информацию о Вашем весе: ”);
scanf(“%f”, &weigth);
printf(“Ваш возраст = %d, Ваш вес = %f”, age, weigth);

Return 0;
}

Основным отличием применения функции scanf() от функции printf() является знак & перед именем переменной, в которую записываются результаты ввода.

Функция scanf() может работать сразу с несколькими переменными. Предположим, что необходимо ввести два целых числа с клавиатуры. Формально для этого можно дважды вызвать функцию scanf(), однако лучше воспользоваться такой конструкцией:

scanf(“ %d, %d ”, &n, &m);

Функция scanf() интерпретирует это так, как будто ожидает, что пользователь введет число, затем – запятую, а затем – второе число. Все происходит так, как будто требуется ввести два целых числа следующим образом:

Функция scanf() возвращает число успешно считанных элементов. Если операции считывания не происходило, что бывает в том случае, когда вместо ожидаемого цифрового значения вводится какая-либо буква, то возвращаемое значение равно 0.

В то время как функция printf() осуществляет форматированный вывод данных, функция scanf() осуществляет их форматированный ввод. Это значит, что поступающие на ввод данные преобразуются соответственно указанному формату(ам) и записываются по адресу(ам) указанной(ых) переменной(ых):

Scanf(строка_формата, адреса_переменных);

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

Спецификации формата данных, допустимые в строке формата, для scanf() почти идентичны тем, что были описаны для функции printf() . На этом уроке мы подробно не рассмотрим все возможности форматированного ввода с помощью scanf() , зато разберем ряд конкретных примеров.

Ввод чисел, символов и строк

Пример ввода-вывода целого и вещественного чисел, символа и строки:

int a; float b; char ch, str[ 30 ] ; scanf ("%d%f%c%s" , & a, & b, & ch, str) ; printf ("%d %.3f %c %s\n " , a, b, ch, str) ;

Результат:

45 34.3456y hello 45 34.346 y hello

Здесь при выполнении программы все данные были введены в одну строку. Разделителем между числами и строками является пробел, а также любой другой символ пустого пространства (например, "\n"). Однако при считывании символа, пробел учитывается как символ; чтобы этого не произошло, в примере букву записали сразу после числа. Данные можно было бы ввести, разделяя их переходом на новую строку (опять же при этом надо иметь ввиду, как считывается символ).

В строке формата функции scanf() между спецификациями вполне допустимо поставить пробелы: %d %f %c %s . Они никакой роли не сыграют. Понятно, что данные можно было получить и так:

scanf ("%d" , & a) ; scanf ("%f" , & b) ; scanf ("%c" , & ch) ; scanf ("%s" , str) ;

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

В функции scanf() в спецификации формата вещественных чисел не указывается точность представления числа. Запись типа %.3f или %.10lf приведет к невозможности получить вещественное число. Чтобы получить число типа double используют формат %lf, для long double - %Lf.

Для целых чисел: длинное целое - %ld, короткое целое - %hd. Кроме того, существуют спецификации для ввода восьмеричных и шестнадцатеричных чисел.

Функция scanf() возвращает количество удачно считанных данных; т.е. значение, возвращаемое функцией, можно проанализировать и таким образом узнать, корректно ли были введены данные. Например:

int a; double b; char ch, str[ 30 ] ; ch = scanf ("%d %lf %s" , & a, & b, str) ; if (ch == 3 ) printf ("%d %.3lf %s\n " , a, b, str) ; else printf ("Error input\n " ) ;

Использование обычных символов

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

int a, b, c; scanf ("%d + %d = %d" , & a, & b, & c) ; printf ("Your answer is %d\n The correct answer is %d\n " , c, a+ b) ;

В данном случае, когда программа выполняется, ввод должен выглядеть примерно так: 342+1024 = 1366. Знаки "+" и "=" обязательно должны присутствовать между числами, наличие пробелов или их отсутствие абсолютно никакой роли не играет:

45 + 839=875 Your answer is 875 The correct answer is 884

Запрет присваивания

Если какие-либо данные, вводимые пользователем, следует проигнорировать, то используют запрет присваивания, ставя после знака %, но перед буквой формата звездочку *. В таком случае данные считываются, но никакой переменной не присваиваются. Это можно использовать, например, когда нет определенной уверенности в том, что поступит на ввод, с одной стороны, и нужды сохранять эти данные, с другой:

float arr[ 3 ] ; int i; for (i = 0 ; i < 3 ; i++ ) scanf ("%*s %f" , & arr[ i] ) ; printf ("Sum: %.2f\n " , arr[ 0 ] + arr[ 1 ] + arr[ 2 ] ) ;

Здесь предполагается, что перед каждым числом будет вводится строка, которую следует проигнорировать, например:

First: 23.356 Second: 17.285 Third: 32.457 Sum: 73.098

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

Для функции scanf() есть пара спецификаций формата, отдаленно напоминающих шаблоны командной оболочки и др. Формат […] позволяет получить строку, содержащую любые символы, указанные в квадратных скобках. Как только на ввод поступает символ, не входящий в указанный набор, считывание данных прекращается. Формат [^…], наоборот, помещает в строку символы, не входящие в указанный набор, до тех пор пока не встретит любой из указанных.

В примере ниже как только поступает не цифра, считывание ввода завершается. При этом если первый символ - не цифра, то в str вообще ничего не записывается:

char str[ 30 ] = "" ; scanf ("%" , str) ; printf ("%s\n " , str) ;

А в этом случае строке будет присвоена последовательность символов до любого из указанных знаков препинания:

scanf ("%[^;:,!?]" , str) ; printf ("%s\n " , str) ;

Результат:

Hello, World! Hello

Некоторые особенности и ограничения функции scanf()

Как только поступают некорректные данные, функция scanf() завершает свою работу. В примере:
scanf ("%d%f" , & a, & b) ;

если переменной a попытаться присвоить символ или строку, что невозможно, то переменная bуже обрабатываться не будет. Можно предположить, что так будет надежнее:

scanf ("%d" , & a) ; scanf ("%f" , & b) ;

Вроде бы неудачное считывание a не должно оказывать никакого влияния на b, т.к. это уже иной вызов scanf() . Но не все так просто: при некорректном вводе данные остаются в буфере и пытаются "навязать" себя последующим вызовам scanf() . Поэтому при использовании scanf() надо думать о том, как в случае некорректного ввода очистить буфер. Например, это можно сделать так, как показано ниже, или путем использования специальных функций (здесь не рассматриваются):

if (scanf ("%d" , & a) != 1 ) // если данные не удалось присвоить переменной, scanf ("%*s" ) ; // то выбросить их в виде строки. scanf ("%f" , & b) ;

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

Таким образом, не смотря на достаточно большие возможности scanf() , эта функция хранит в себе ряд неудобств и опасностей.

Решение задач

  1. На прошлом занятии вы написали программу, содержащую функции, вычисляющие факториал числа и заданный элемент ряда Фибоначчи. Измените эту программу таким образом, чтобы она запрашивала у пользователя, что он хочет вычислить: факториал или число Фибоначчи. Затем программа запрашивала бы у пользователя либо число для вычисления факториала, либо номер элемента ряда Фибоначчи.
  2. Напишите программу, которая запрашивает у пользователя две даты в формате дд.мм.гггг. Дни, месяцы и года следует присвоить целочисленным переменным. Программа должна выводить на экран информацию о том, какая дата более ранняя, а какая более поздняя.
  3. Используя цикл, напишите код, в котором пользователю предлагается вводить данные до тех пор, пока он не сделает это корректно, т.е. пока все указанные в scanf() переменные не получат свои значения. Протестируйте программу.

Теги: Форматированный ввод, форматированный вывод, printf, scanf, fgets, getch, строка формата, спецификатор формата, флаги, управляющие символы.

Форматированный вывод

Сегодня мы рассмотрим две важные функции форматированного ввода и вывода. Устройство и работу этих функций полностью можно понять только после изучения работы с указателями и функций с переменным числом параметров. Но пользоваться этими функциями необходимо уже сейчас, так что некоторые моменты придётся пропустить.

Функция форматированного вывода printf получает в качестве аргументов строку формат и аргументы, которые необходимо вывести в соответствии с форматом, и возвращает число выведенных символов. В случае ошибки возвращает отрицательное значение и устанавливает значение ferror. Если произошло несколько ошибок, errno равно EILSEQ.
int printf (const char * format, ...);

#include #include void main() { //функция не получает никаких аргументов, кроме строки printf("Hello world"); getch(); }

Функция проходит по строке и заменяет первое вхождение % на первый аргумент, второе вхождение % на второй аргумент и т.д. Далее мы будем просто рассматривать список флагов и примеры использования.

Общий синтаксис спецификатора формата
%[флаги][ширина][.точность][длина]спецификатор
Спецификатор – это самый важный компонент. Он определяет тип переменной и способ её вывода.

Таб. 1 Спецификатор типа.
Спецификатор Что хотим вывести Пример
d или i Целое со знаком в в десятичном виде 392
u Целое без знака в десятичном виде 7235
o Беззнаковое в восьмеричном виде 657
x Беззнаковое целое в шестнадцатеричном виде 7fa
X Беззнаковое целое в шестнадцатеричном виде, верхний регистр 7FA
f или F Число с плавающей точкой 3.4563745
e Экспоненциальная форма для числа с плавающей точкой 3.1234e+3
E Экспоненциальная форма для числа с плавающей точкой, верхний регистр 3.1234E+3
g Кратчайшее из представлений форматов f и e 3.12
G Кратчайшее из представлений форматов F и E 3.12
a Шестнадцатеричное представление числа с плавающей точкой -0xc.90fep-2
A Шестнадцатеричное представление числа с плавающей точкой, верхний регистр -0xc.90FEP-2
c Буква a
s Строка (нуль-терминированный массив букв) Hello World
p Адрес указателя b8000000
n Ничего не пачатает. Аргументом должен быть указатель на signed int. По этому адресу будет сохранено количество букв, которое было выведено до встречи %n
% Два идущих друг за другом процента выводят знак процента %

#include #include void main() { int a = 0x77, b = -20; char c = "F"; float f = 12.2341524; double d = 2e8; char* string = "Hello, World!"; printf("%s\n", string); printf("a = %d, b = %d\n", a, b); printf("a = %u, b = %u\n", a, b); printf("a = %x, b = %X\n", a, b); printf("dec a = %d, oct a = %o, hex a = %x\n", a, a, a); printf("floating point f = %f, exp f = %e\n", f, f); printf("double d = %f or %E\n", d, d); printf("not all compiler support %a\n", f); printf("character c = %c, as number c = %d", c, c); printf("address of string is %p", string); getch(); }

Строка формата также может включать в себя следующие необязательные суб-спецификаторы: флаг, ширина, .точность и модификатор (именно в таком порядке).

Таб. 4 Точность.
.Точность Описание
.число Для спецификаторов целых (d, i, o, u, x, X) точность определяет минимальное количество знаков, которое необходимо вывести. Если значение короче, то выводятся нули перед числом. Значение не обрезается, даже если оно длиннее. Точночть 0 означает, что для значения 0 ничего не выводится.
Для спецификаторов чисел с плавающей точкой (a, A, e, E, f, F) это число знаков, которые необходимо вывести после десятичной точки (по умолчанию 6).
Для g и G - это число значащих разрядов, которые необходимо вывести.
Для s - выводится указанное число символов. По умолчанию выводятся все символы до первого нулевого.
Если число не стоит, то по умолчанию точность равна 0
.* Точность не указана в строке формата, она передаётся отдельно в виде аргумента, который должен предшествовать выводимому числу

#include #include void main() { int a = 0x77, b = -20; char c = "F"; float f = 12.2341524; double d = 2e2; char* string = "Hello, World!"; printf("%.3f\n", f); printf("%.*f\n", 2, f); printf("%010.3f\n", d); printf("%*d\n", 6, a); printf("%+d\n", b); printf("%0.6d\n", a); printf("%.f\n", d); printf("%.4s", string); getch(); }

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

Таб. 5 Длина.
спецификаторы
Длина d, i u o x X f F e E g G a A c s p n
(none) int unsigned int double int char* void* int*
hh signed char unsigned char signed char*
h short int unsigned short int short int*
l long int unsigned long int wint_t wchar_t* long int*
ll long long int unsigned long long int long long int*
j intmax_t uintmax_t intmax_t*
z size_t size_t size_t*
t ptrdiff_t ptrdiff_t ptrdiff_t*
L long double

#include #include void main() { long long x = 12300000000579099123; short i = 10; printf("%llu\n", x); printf("%d\n", i); printf("%hd\n", i); getch(); }

Форматированный ввод

Рассмотрим форматированный ввод функцией scanf.
int scanf(const char*, ...)
Функция принимает строку формата ввода (она похожа на строку формата printf) и адреса, по которым необходимо записать считанные данные. Возвращает количество успешно проинициализированных аргументов.
Формат спецификатора ввода
%[*][ширина][длинна]спецификатор

Таб. 6 Спецификатор типа.
Спецификатор Описание Выбранные символы
i, u Целые Произвольное число цифр (0-9), возможно, начинающихся с + или -. Если число начинается с 0, то считывается в восьмеричном формате, если с 0x, то в шестнадцатеричном.
d Десятичное целое Произвольное число цифр (0-9), возможно, начинающихся с + или -.
o восьмеричное целое Произвольное число цифр (0-7), возможно, начинающихся с + или -.
x Шестнадцатеричное целое Произвольное число цифр (0-F), возможно, начинающихся с + или - и префикса 0x или 0X.
f, e, g Число с плавающей точкой Число, состоящее из набора цифр 0-9, возможно с десятичным разделителем (точкой). Возможно также представление в экспоненциальной форме. C99 позволяет также вводить число в шестнадцатеричном формате.
a
c Символ Если ширина не передана, то считывает один символ. Если ширина передана, то считывает нужное количество символов и размещает их в массиве БЕЗ терминального символа на конце.
s Строка Считывает все не пробельные символы. Если указана ширина, то не более n символов. Ставит на место n+1 символа терминальный.
p Адрес указателя Последовательность символов, трактуемая как адрес указателя. Формат зависит от реализации, но совпадает с тем, как выводит printf с ключом p
[символы] Множество символов Считывает только те символы, которые записаны в квадратных скобках, С99
[^символы] Множество символов Считывает только те символы, которые не указаны в квадратных скобках, С99
n Ничего не считывает Сохраняет число уже считанных символов по указанному адресу

Как и в printf, ширина, заданная символом * ожидает аргумента, который будт задавать ширину. Флаг длина совпадает с таким флагом функции printf.

#include #include void main() { int year, month, day; char buffer; int count; //Требует форматированного ввода, например 2013:12:12 printf("Enter data like x:x:x = "); scanf("%d:%d:%d", &year, &month, &day); printf("year = %d\nmonth = %d, day = %d\n", year, month, day); //Считываем строку, не более 127 символов. При считывании в массив писать & не надо, //так как массив подменяется указателем printf("Enter string = "); scanf("%127s", buffer); printf("%s", buffer); getch(); }

Кроме функций scanf и printf есть ещё ряд функций, которые позволяют получать вводимые данные

int getch() - возвращает введённый символ, при этом не выводит его на консоль. #include #include void main() { char c = 0; do { c = getch(); printf("%c", c); } while (c != "q"); }

char * fgets (char * str, int num, FILE * stream) - функция позволяет считывать строку с пробельными символами. Несмотря на то, что она работает с файлом, можно с её помощью считывать и из стандартного потока ввода. Её преимущество относительно gets в том, что она позволяет указать максимальный размер считываемой строки и заканчивает строку терминальным символом.

#include #include #include void main() { char buffer; //Считываем из стандартного потока ввода fgets(buffer, 127, stdin); printf("%s", buffer); //Этим можно заменить ожидание ввода символа scanf("1"); }

Это не полный набор различных функций символьного ввода и вывода. Таких функций море, но очень многие из них небезопасны, поэтому перед использованием внимательно читайте документацию.

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

В версии С99 к параметру format применен квалификатор restrict.

Управляющая строка, задаваемая параметром format, состоит из символов трех категорий:

  • спецификаторов формата;
  • пробельных символов;
  • символов, отличных от пробельных.

Спецификаторы формата - им предшествует знак процента(%) - сообщают, какого типа данное будет прочитано следующим. Например, спецификатор %s прочитает строку, а %d - целое значение. Строка форматирования читается слева направо, и спецификаторы формата по порядку сопоставляются с аргументами, перечисленными в списке аргументов. Эти коды приведены в следующей таблице.

Код Назначение
Читает значение с плавающей точкой(только С99)
Аналогично коду %a (только С99)
Читает один символ
%d Читает десятичное целое
%i Читает целое в любом формате(десятичное, восьмеричное, шестнадцатеричное)
Читает вещественное число
Аналогично коду %е
%f Читает вещественное число
%F Аналогично коду %f(только С99)
%g Читает вещественное число
%G Аналогично коду %g
Читает восьмеричное число
%s Читает строку
Читает шестнадцатеричное число
%X Аналогично коду %х
Читает указатель
%n Принимает целое значение, равное количеству символов, прочитанных до сих пор
%u Читает десятичное целое без знака
% Просматривает набор символов
%% Читает знак процента

По умолчанию спецификаторы а, f, e и g заставляют функцию scanf() присваивать данные переменным типа float. Если поставить перед одним из этих спецификаторов формата модификатор l, функция scanf() присвоит прочитанное данное переменной типа double. Использование же модификатора L означает, что переменная, принимающая значение, имеет тип long double.

Если вы используете современный компилятор, который поддерживает добавленные в 1995 году средства работы с двухбайтовыми символами, можете задействовать модификатор l применительно к спецификатору с, чтобы обозначить указатель на двухбайтовый символ с типом данных whcar_t. Модификатор l можно также использовать с кодом формата s, чтобы обозначить указатель на строку двухбайтовых символов. Кроме того, модификатор l можно использовать для модификации набора сканируемых двухбайтовых символов.

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

Не пробельный символ в строке форматирования заставляет функцию scanf() прочитать и отбросить соответствующий символ. Например, при использовании строки форматирования %d, %d функция scanf() сначала прочитает целое значение, затем прочитает и отбросит запятую и наконец прочитает еще одно целое. Если заданный символ не обнаружится, работа функции scanf() будет завершена.

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

Элементы входного потока должны быть разделены пробелами, символами табуляции или новой строки. Такие символы, как запятая, точка с запятой и т.п., не распознаются в качестве разделителей. Это означает, что оператор

Scanf("%d%d", &r, &c);

примет значения, введенные как 10 20, но наотрез откажется от "блюда", поданного в виде 10,20.

Символ *, стоящий после знака % и перед кодом формата, прочитает данные заданного типа, но запретит их присваивание. Следовательно, оператор

Scanf("%d%*c%d", &х, &у);

при вводе данных в виде 10/20 поместит значение 10 в переменную х, отбросит знак деления и присвоит значение 20 переменной у.

Команды форматирования могут содержать модификатор максимальной длины поля. Он представляет собой целое число, располагаемое между знаком % и кодом формата, которое ограничивает количество символов, читаемых для любого поля. Например, если вы хотите прочитать в переменную address не более 20 символов, используйте следующий оператор.

Scanf("%20s", address);

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

Несмотря на то что пробелы, символы табуляции и новой строки используются в качестве разделителей полей, при чтении одиночного символа они читаются подобно любому другому символу. Например, если входной поток состоит из символов х у, то оператор

Scanf("%с%с%с", &а, &Ь, &с);

поместит символ х в переменную а, пробел - в переменную Ь и символ у - в переменную с.

Помните, что любые другие символы управляющей строки, не являющиеся спецификаторами формата(включая пробелы, символы табуляции и новой строки), используются для установления соответствия и отбрасывания символов из входного потока. Например, если поток ввода выглядит, как 10t20, оператор

Scanf("%st%s", &х, &у);

поместит 10 в переменную х и 20 - в переменную у. Символ t отбрасывается, так как он присутствует в управляющей строке.

Еще один способ использования функции scanf() называется набором сканируемых символов(scanset). В этом случае определяется набор символов, которые могут быть прочитаны функцией scanf() и присвоены соответствующему массиву символов. Для определения такого набора необходимо заключить символы, подлежащие сканированию, в квадратные скобки. Открывающая квадратная скобка должна следовать сразу за знаком процента. Например, следующий набор сканируемых символов говорит о том, что необходимо прочитать только символы А, В и С.

%[АВС]

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

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

Многие компиляторы позволяют с помощью дефиса задать диапазон. Например, следующий оператор заставляет функцию scanf() принимать символы от А до Z.

Важно помнить, что набор сканируемых символов различает прописные и строчные буквы. Следовательно, если вы хотите сканировать как прописные, так и строчные буквы, задайте их отдельно.

Функция scanf() возвращает число, равное количеству полей, для которых были успешно присвоены значения. К этим полям не относятся поля, которые были прочитаны, но присвоение не состоялось в связи с использованием модификатора * для подавления присваивания. При обнаружении ошибки до присвоения значения первого поля функция scanf() возвращает значение EOF.

Модификаторы формата, добавленные к функции scanf() стандартом С99

В версии С99 добавлено несколько модификаторов формата для использования в функции scanf(): hh, ll, j, z и t. Модификатор hh можно применять к спецификаторам d, i, о, и, х и п. Он означает, что соответствующий аргумент является указателем на значение типа signed char или unsigned char. Модификатор ll также можно применять к спецификаторам d, i, о, и, х и п. Он означает, что соответствующий аргумент является указателем на значение типа signed long long int или unsigned long long int.

Модификатор формата j, который применяется к спецификаторам d, i, о, и, х и n, означает, что соответствующий аргумент является указателем на значение типа intmax_t или uintmax_t. Эти типы объявлены в заголовке и служат для хранения целых максимально возможной длины.

Модификатор формата z, который применяется к спецификаторам d, i, о, u, x и n, означает, что соответствующий аргумент является указателем на объект типа size_t. Этот тип объявлен в заголовке и служит для хранения результата операции sizeof.

Модификатор формата t, который применяется к спецификаторам d, i, о, u, x и n, означает, что соответствующий аргумент является указателем на объект типа ptrdiff_t. Этот тип объявлен в заголовке и служит для хранения значения разности между двумя указателями.

Как хорошо когда все данные даны, и ничего вводить не надо. Но, поверьте мне, так практически не бывает. Вспомните школу, когда вы измеряли определенные вещи, а потом полученные значения вставляли в нужные формулы.

scanf

В языке Си кроме функции вывода printf, существует так же функция scanf для ввода. Вот функцию scanf мы щас и рассмотрим подробнее:

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

Вроде очень похоже на функцию printf. Так же есть в двойных кавычках спецификатор формата , но разница как раз находится во второй части функции. Обратили внимание на появление знака (&)? Так вот этот знак означает взятие адреса. Щас объясню для чего это нужно.

Мы должны записывать введенное значение не куда-то там, а именно по адресу, по которому находится наша переменная. Т.е. без знака (&) наше введенное значение попадет во все места, кроме того что нам нужно. Поэтому всегда, когда вам нужно вводить значения с клавиатуры, ставьте перед переменной знак взятия адреса (&).

Спецификаторы формата

Ну теперь пробежимся по спецификаторам формата :
  1. %d - прочитать целое число
  2. int i;
    scanf ("%d", &i);

  3. %o - прочитать восьмеричное число
  4. int i;
    scanf ("%o", &i);

  5. %x - прочитать шестнадцатеричное число
  6. int i;
    scanf ("%x", &i);

  7. %e(%f) - прочитать вещественное число
  8. float t;
    scanf ("%f", &t);

  9. %с - прочитать символ
  10. char ch;
    scanf ("%c", &ch);

  11. %s - прочитать строку
  12. char *str;;
    scanf ("%s", str);

    Пока не вникайте в работу со строками. Почему нету знака взятия адреса? Эту тему мы рассмотрим чуть позднее.

Операции сравнения

В компьютер изначально заложена булева логика, т.е. все построено на 0 и 1. Если не понимаете о чем речь, то пересмотрите фильм Матрица, где каждая зеленая заставка как раз состояла из этих двух магических цифр.

Конечно, 0 и 1 это хорошо, но нам нужен логический смысл, поэтому в логических операциях 0 - это FALSE, а 1 - это TRUE. Эти понятия TRUE и FALSE тесно связанны с операциями сравнения . Для начала приведем всевозможные операции сравнения:

В принципе, самая распространенная ошибка, которую делают новички - это путают операцию присваивания (=) с операцией сравнения (==). Это абсолютно разные вещи. Но у всех на первых порах кодирования возникают ошибки именно на этой почве, поэтому будьте внимательнее.