Int scanf(char*, … );
из файла stdio.h. Обязательным параметром является адрес строковой константы, называемой строкой форматирования. Многоточие означает, что у функции кроме обязательного параметра типа char* могут быть и другие параметры. Клавиатура обеспечивает представление информации в виде групп символов. Строка форматирования содержит указания о типах объектов, в которые следует преобразовать эти группы. Группы называются полями ввода. При вводе нескольких полей они отделяются друг от друга разделительными символами (или кратко разделителями). В качестве разделителей служат пробелы, символы горизонтального табулирования ‘\t’ и символы новой строки ‘\n’. Для каждого поля в строке форматирования должно присутствовать отдельное указание, которое называется командой или спецификацией форматирования. Спецификация форматирования начинается с символа % (процент) и содержит кроме него один обязательный символ, называемый символом форматирования. Именно символ форматирования указывает тип объекта, в который требуется преобразовать соответствующее поле. Объекты сохраняются в переменных, адреса которых перечисляются после запятой, следующей за строкой форматирования. Переменные должны быть определены до вызова функции scanf(). Каждое поле требует собственный адрес. Соответствие между символами форматирования и типами вводимых объектов приведено в нижеследующей таблице 3.2.
Завершение функции fscanf() наступает после выполнения последней команды форматирования или обнаружения противоречия (несоответствия) между командой форматирования и вводимым полем. Ее возвращаемым значением является количество введенных объектов.
Таблица 3.2 - Примеры символов форматирования функции scanf()
Представление вводимых полей |
Символ форматирования |
Тип объекта |
Целое в десятичной системе |
d |
int |
Целое (десятичное, восьмеричное с префиксом 0 или шестнадцатеричное с префиксом 0x) |
i |
|
Целое в восьмеричной системе с префиксом 0 или без |
o |
|
целое в шестнадцатеричной системе с префиксом 0x или без |
x |
|
Число с плавающей точкой (присутствие десятичной точки или экспоненциальной части обязательно) |
e, f или g |
float |
Число с плавающей точкой (присутствие десятичной точки или экспоненциальной части обязательно) |
lf |
double |
Символ в объект типа char |
c |
char |
Последовательность символов |
s |
char* (строковая константа) |
3.6 Область видимости идентификаторов и время жизни объектов
Использование идентификатора начинается с его определения. Оно содержит сведения, которые необходимы компилятору для контроля за правильностью его (идентификатора) использования в программе. В соответствии с правилами языка, определение действительно только в некоторой части программы, называемой областью видимости идентификатора. Для идентификатора, определенного в некотором блоке (фигурных скобках), область видимости начинается от места его определения и простирается до конца этого блока (правой фигурной скобки). Если идентификатор является формальным параметром функции или определяется в заголовке оператора for, то областью его видимости тело функции или тело цикла. Идентификатор, определенный указанными выше способами, называется локальным. Из сказанного следует, что один и тот же идентификатор может определяться в нескольких блоках совершенно по-разному. Рассмотрим пример на эту тему.
Пример 3.6 - Локальные идентификаторы
#include <stdio.h>
void main(void){
// Первый блок
{
…
// Определение переменной i
int i=0;
}
// Второй блок
{
…
// Еще одно определение i
int i=2;
int ii=i+3; // ii=5
// Вложенный блок
{
ii++;
printf("ii=%i\n", ii);
}
}
}
После выполнения этой программы на экране дисплея появится сообщение
ii=6
Если определение идентификатора не входит ни в один из блоков, образующих программу, и если он не является формальным параметром функции, то областью его видимости является вся программа, начиная от места определения. Такие идентификаторы называются глобальными.
В любом блоке программист может использовать глобальный идентификатор в качестве локального, поместив в этот блок соответствующее определение. Такое переопределение глобального идентификатора внутри блока называется его сокрытием. Пример на эту тему.
Пример 3.7 - Сокрытие глобальных идентификаторов
// Глобальная переменная
float x=2.0f;
void main(void){
// Увеличение глобальной переменной
x+=1.1f; // x=3.1
// Определение локальной переменной
int x=2;
// Умножение локальной переменной на десять
x*=10; // x=20
}
В языке Си есть операция с названием “разрешение области видимости”. Она имеет наивысший (первый) приоритет и обозначается знаком “::”. Эта операция позволяет использовать глобальные идентификаторы в области видимости локальных. Пример по этому поводу.
Пример 3.8 - Разрешение области видимости
// Глобальная переменная
int x=0;
void main(void){
// Локальная переменная
int x=1;
// Увеличение глобальной переменной
::x+=2;
// Увеличение локальной переменной
x+=3;
// ...
}
Данные должны находиться в памяти до тех пор, пока в них имеется необходимость. Язык Си предоставляет программисту несколько способов для определения продолжительности хранения данных, которая называется временем жизни.
Для данных с локальными именами память выделяется при их создании. Такие данные хранятся только в течение времени необходимого для выполнения блока, в котором они определены, и называются автоматическими.
Данные, которые хранятся в памяти в течение всего времени выполнения программы, называются статическими. По определению, все данные с глобальными именами являются таковыми. Если данные с локальными именами нужно хранить до конца выполнения программы, то их определение должно начинаться со служебного слова static.
Все статические переменные должны при их определении инициализироваться. Если программист не указывает начальные значения таких переменных, то за него это делает компилятор, присваивая статическим переменным нулевые значения. Такая инициализация называется неявной. Рассмотрим пример.
Пример 3.9 - Время жизни объектов
#include <stdio.h>
int a; // a=0
void f(void){
int b=0;
static int c=1;
a++;
b++;
c++;
printf(“a=%d b=%d c=%d\n”,a,b,c);
}
void main(void){
f(); // a=1, b=1, c=2
f(); // a=2, b=1, c=3
f(); // a=3, b=1, c=4
}
3.6 Проекты
Исходный текст большой программы удобно хранить в нескольких файлах. Совокупность таких файлов называется проектом. Если содержание файлов проекта удовлетворяет определенным требованиям, то их можно компилировать отдельно друг от друга. Это означает, что в случае изменения исходного текста повторно компилировать нужно только измененные файлы.
Каждый глобальный идентификатор должен определяться в программе только один раз. Поэтому его определение может находиться только в одном файле. Во все остальные файлы, в которых он используется, нужно поместить соответствующие предупреждения, называемые объявлениями глобальных идентификаторов. Объявление глобального идентификатора начинается со служебного слова extern. За ним следует тип идентификатора и он сам. Объявление не приводит к повторному выделению памяти для хранения значения глобального идентификатора.
Пример 3.10 - Глобальные идентификаторы и проекты
// Файл №1/2
#include <stdio.h>
// Определение глобальной переменной
int j=1;
// Прототип
int f(int);
void main(){
int r=f(3);
printf("r=%d\n", r);
}
// Файл №2/2
// Глобальная переменная, определенная в другом файле
extern int j;
// Определение функции
int f(int i){
return j+i;
}