Организация ввода-вывода переменных

Рассмотренные операторы позволяют овладеть технологией (методикой) организации ввода-вывода переменных.

ü Внимание! В предлагаемом разделе рассматривается использование спецификаторов классической структуры (длина и точность обязательны).

Организация ввода-вывода с использованием укороченных спецификаторов представлена в разд. 6.2.1.1.

Ввод переменных

Для вводимых переменных численные значения известны. Поэтому методика организации ввода достаточно проста:

· создать идентификаторы переменных для входных данных алгоритма, определив тип каждого;

· сформировать константы из численных значений исходных данных;

· привести типы констант в соответствие с типами их переменных;

· определить длину поля значения каждой вводимой переменной;

· сформировать спецификатор каждой переменной;

· установить желательную последовательность переменных в списке ввода;

· сформировать адрес каждой переменной;

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

Пример 3.1. Осуществить ввод переменных A=13,2 B= -6,8 I=70 PI=3,1416.

Подготовка к вводу представлена в табл. 3.9.

Таблица 3.9

Запись в задаче Обозначение в Си/Си++ Тип переменой Обозначение типа Длина поля Специфи-катор
A=13,2 B= -6,8 I=70 PI=3,1416 a=13.2 b= -6.8 i=70 pi=3.1416 Вещественный Вещественный Целый Вещественный f f d f %4f %4f %2d %6f

Расположение переменных в списке оператора ввода произведем аналогично табличному. При этом фрагмент программы по организации ввода оформится операторами:

float a, b, pi; /* описатели */

int i; /* переменных */

. . .

scanf(“%4f%4f%2d%6f”, &a, &b, &i, &pi );/*оператор ввода*/

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

13.2-6.8703.1416

Следовательно, управляющая строка оператора ввода каждым спецификатором предписывает, какая часть вводимых значений соответствует конкретной переменной (переменной a – первые четыре символа, переменной b – следующие четыре, переменной i – два, переменной pi – шесть).

Пример 3.2. Осуществить ввод переменных для расчёта площади (длины Д=120 м; ширины Ш=3,6 10-3 км; переводного коэффициента K= 0,001 км/м)

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

Методику преобразования представим табл. 3.10.

Таблица 3.10

Запись в задаче Обозначение в Си/Си++ Тип переменой Обозначение типа Длина поля Специ-фикатор
Д=120 Ш=3,6 10-3 K= 0,001 d=120. sh=3.6E-3 k= 0.001 Вещественный Вещественный Вещественный f e f %4f %6e %5f

Расположение переменных в списке оператора ввода произведем аналогично табличному.

При этом фрагмент программы по организации ввода оформится операторами:

float d, sh, k; /* описатели переменных */

. . .

scanf(“%4f%6e%5f”, &d, &sh, &k ); /* оператор ввода */

Строка численных значений, подготовленных к вводу:

120.3.6E-30.001

Вывод переменных

При организации вывода руководствуются следующими положениями:

· численные значения большинства выводимых переменных неизвестны (формируются при решении);

· чтение результатов из сплошной строки (без пробелов) не удобно;

· спецификатор каждой переменной жёстко определяет расположение выводимого численного значения. Для вещественных – относительно точки, для целых – от правого края поля;

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

· если число разрядов дробной части меньше, чем запланировано в спецификаторе, эти лишние разряды заполняются нулями;

· если число разрядов целой переменной или целой части вещественной меньше, чем запланировано в спецификаторе, все оставшиеся свободными левые разряды заполняться не будут;

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

Методика организации вывода:

· уточнить список переменных конкретного блока «вывод» алгоритма;

· определить тип каждой переменной и значение (известно, неизвестно);

· задаться желаемой формой представления численного значения выводимой переменной;

· сформировать (представить) шаблон вывода каждой переменной;

· составить спецификатор вывода в соответствии с указаниями шаблона;

· предусмотреть вид разделителей между выводимыми значениями (пробелы, названия переменных, печать в новой строке);

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

Рассмотрим варианты организации вывода введённых переменных.

Пример 3.3. Организовать вывод введённых переменных A=13,2 B= -6,8 I=70 PI=3,1416 (пример 3.1).

Первый вариант предусматривает организацию пробелов по общей методике – указанием заведомо больших полей при требуемой точности.

Последовательность подготовки к выводу представлена в табл. 3.11.

Таблица 3.11

Переменная Шаблон вывода Разделитель
Обозначение Тип Значение Длина Точность Форма представления Длина Точность Спецификатор
a b i pi Вещ. Вещ. Цел. Вещ. 13,2 -6,8 3,1416 f f d f %7.2f %7.2f %7d %10.4d Нет Нет Нет Нет

Шаблон вывода можно представить следующим образом

_ _ _ _ Ÿ _ _ _ _ _ _ Ÿ _ _ _ _ _ _ _ _ _ _ _ _ _ _ Ÿ _ _ _ _

  a   b   i   pi

Следовательно, фрагмент вывода, с учётом ранее составленных описателей будет иметь вид:

float a, b, pi; /* описатели */

int i; /* переменных */

. . .

printf(“%7.2f%7.2f%7d%10.4f”, a, b, i, pi ); /* оператор вывода */

Оператор printf предписывает вывод на экран значений переменных (a, b, i, pi) в указанном порядке, расположив их в одной строке следующим образом:

– – 13.00 – – -6.80 – – – – – 70 – – – – 3.1416

Второй вариант предусматривает организацию пробелов непосредственным указанием их перед спецификаторами в управляющей строке.

Последовательность подготовки к выводу имеет вид табл. 3.12.

Таблица 3.12

Переменная Шаблон вывода Разделитель
Обозначение Тип Значение Длина Точность Форма представления Длина Точность Спецификатор
a b i pi Вещ. Вещ. Цел. Вещ. 13,2 -6,8 3,1416 f f d f %4.1f %4.1f %2d %6.4f _ _ _ _ _ _ _ _

 

Шаблон вывода можно представить следующим образом

_ _ _ _ Ÿ _ _ _ _ _ Ÿ _ _ _ _ _ _ _ _ Ÿ _ _ _ _

    a     b   i     pi

Следовательно, оператор вывода с учётом ранее составленных описателей имеет вид:

printf(“_ _ %4.1f _ _ %4.1f _ _ %2d _ _ %6.4f ”, a, b, i, pi );

Оператор предписывает вывод на экран значений переменных (a, b, i, pi) в указанном порядке, расположив их в одной строке следующим образом:

– – 13.0– –-6.8– – 70– – 3.1416

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

Третий вариант позволяет выполнить поясняющие надписи в выводимой строке добавлением соответствующего текста в управляющую строку оператора вывода.

Подготовка к выводу имеет вид табл. 3.13.

Таблица 3.13

Переменная Шаблон вывода Разделитель
Обозначение Тип Значение Длина Точность Форма представления Длина Точность Спецификатор
a b i pi Вещ. Вещ. Цел. Вещ. 13,2 -6,8 3,1416 f f d f %4.1f %4.1f %2d %6.4f _ a= _ b= _ i= _ pi=

Шаблон вывода можно представить следующим образом

_ а = _ _ Ÿ _ _b = _ _ Ÿ _ _i = _ _ _ pi = _ Ÿ _ _ _ _

    a     b     i     pi

Оператор вывода с учётом ранее составленных описателей имеет вид

printf(“_ a=%4.1f _ b=%4.1f _ i=%2d _ pi=%6.4f”, a, b, i, pi);

Оператор предписывает вывод на экран значений переменных (a, b, i, pi) в указанном порядке, расположив их в одной строке следующим образом:

– a=13.0 – b=-6.8 – i=70 – pi=3.1416

Рассмотрим варианты организации вывода результатов.

Результаты – переменные, численные значения которых на момент составления программы неизвестны (будут получены в процессе счёта).

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

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

Пример 3.4. Организовать вывод промежуточных и конечных результатов (вещественных переменных) X, Y, Z.

Первый вариант – организация пробелов по общей методике: указанием заведомо больших полей при требуемой точности.

Подготовка к выводу имеет вид табл. 3.14.

Таблица 3.14

Переменная Шаблон вывода Разделитель
Обозначение Тип Значение Длина Точность Форма представления Длина Точность Спецификатор
x y z Вещ. Вещ. Вещ. Не изв. Не изв. Не изв. – – – – – – f f f %10.2f %10.2f %10.2f Нет Нет Нет

Шаблон вывода можно представить следующим образом

_ _ _ _ _ _ _ Ÿ _ _ _ _ _ _ _ _ _ Ÿ _ _ _ _ _ _ _ _ _ Ÿ _ _

  x   y   z

 

Следовательно, оператор вывода:

printf(“%10.2f%10.2f%10.2f”, x, y, z);

если переменные в процессе счёта приняли значения x=265.38, y=1244.5, z=4.7 сформирует строку вида:

– – – – 265.38– – – 1244.50– – – – – – 4.70

В случае, если планируемая длина полей вывода меньше требуемой, произойдёт слияние выводимых значений. Например, выполнение оператора

printf(“%6.2f%6.2f%6.2f”, x, y, z);

(в качестве длины выбраны значения 6) сформирует строку вида

265.381244.50– – 4.70

В выводимой строке произошло слияние значений переменных x и y.

Второй вариант – организация пробелов непосредственным указанием их перед спецификаторами в управляющей строке.

Подготовка к выводу имеет вид табл. 3.15.

Таблица 3.15

Переменная Шаблон вывода Разделитель
Обозначение Тип Значение Длина Точность Форма представления Длина Точность Спецификатор
x y z Вещ. Вещ. Вещ. Не изв. Не изв. Не изв. – – – – – – f f f %6.2f %6.2f %6.2f _ _ _ _ _ _

Шаблон вывода можно представить следующим образом

_ _ _ _ _ Ÿ _ _ _ _ _ _ _ Ÿ _ _ _ _ _ _ _ Ÿ _ _

    x     y     z

Оператор вывода примет вид:

printf(“_ _%6.2f _ _%6.2f _ _.%6.2f”, x, y, z);

и сформирует следующую выводимую строку:

– – 265.38– – 1244.50– – 4.70

ü Внимание! Поле для вывода переменной «y» автоматически увеличилось на один разряд в соответствии с правилами.

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

Третий вариант позволяет выполнить поясняющие надписи в выводимой строке добавлением соответствующего текста в управляющую строку оператора вывода.

Последовательность подготовки к выводу аналогична представленной в табл. 3.15 с указанием в последнем столбце надписей ( _ X= , _ Y= , _ Z=).

В этом варианте вывод переменных оператором:

printf(“_X=%6.2f _ Y=%6.2f _ Z=%6.2f”, x, y, z);

приведёт к индикации в текущей строке экрана информации:

– X=265.38 – Y=1244.50 – Z= – – 4.70

Особенность рассмотренных вариантов – распечатка переменных одной строкой.

Четвёртый вариант – вывод переменных в разных строках. При этом вывод численных значений X и Y выполним в экспоненциальной форме, увеличив точность представления мантиссы.

Подготовка к выводу имеет вид табл. 3.16.

Таблица 3.16

Переменная Шаблон вывода Разделитель
Обозна- чение Тип Значение Длина Точность Форма представ- ления Длина Точность Спецификатор
x y z Вещ. Вещ. Вещ. Не изв. Не изв. Не изв. – – – – – – e e f %9.4e %9.4e %6.2f \nX= \nY= \nZ=

 

Шаблон вывода можно представить следующим образом:

X = _ Ÿ _ _ _ _ E _ _

Y = _ Ÿ _ _ _ _ E _ _

Z = _ _ _ Ÿ _ _

В этом варианте вывод переменных оператором:

printf(“\nX=%9.4e\nY=%9.4e\nZ=%6.2f”, x, y, z);

приведёт к индикации в текущих строках экрана информации:

X=2.6538E+2

Y=1.2445E+3

Z=– –4.70

ü Внимание! Предложенные методики вывода на экран (функцией printf) полностью справедливы для вывода в поток (функцией fprintf).

3.5.5. Структура Си/Си++-программы

Эффективность языка программирования в достаточной степени определяется хорошей его структурированностью. Для языка Си/Си++, в частности, структурированность обусловлена следующими требованиями к отдельным конструкциям и программе в целом:

· использованием составных операторов наряду с простыми;

· применением функций в качестве основной сборной конструкции;

· оформлением максимума возможных расчетов и действий стандартными (системными) функциями;

· формированием аналогичных по назначению системных функций в стандартные блоки (внешние файлы);

· использованием специальной программы (препроцессора) для эффективного подключения стандартных файлов.

Сформулируем, исходя из изложенного, некоторые определения.

Составной оператор– совокупность нескольких простых операторов заключенная в фигурные скобки.

Составной оператор позволяет обозначить (оформить) выполнение конкретного раздела задачи в виде одного блока.

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

По назначению внешние файлы делятся на библиотечные и заголовочные.

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

Заголовочные внешние файлы – хранилища служебной информации, в частности, объявлений функций (структур, аналогичных их заголовкам).

Второе название обусловлено тем, что объявления функций (в частности стандартных) по структуре соответствуют заголовкам. Объявления позволяют определить основные элементы функции (наименование, типы формальных параметров и возвращаемого результата) записанной на языке Си/Си++.

Внешние, как любые файлы, хранятся на магнитных носителях (дисках).

Препроцессор– системная программа для предварительной (до компиляции) машинной обработки программного модуля пользователя.

Основное назначение препроцессора (в большинстве случаев) – включение текстов заголовочных внешних файлов.

Использование препроцессора позволяет облегчить написание Си/Си++-программ, делать их мобильными, легко читаемыми и удобными для отладки.

Исходя из изложенного, можно для языка Си/Си++ дать поясняющее определение программы.

Программа– алгоритм решения, оформленный в виде одной основной (главной) или нескольких функций, одна из которых является главной.

Физически любая Си/Си++-программа реализуется как исходный модуль, состоящий из заголовка программы и её тела, расположенных последовательно (рис. 3.10).

Рис. 3.10. Структура исходного модуля программы

Рассмотрим основные элементы программы.

Заголовок программы

Заголовок (шапка)– начальная часть программы, предназначенная для выполнения некоторых вспомогательных операций до начала основных вычислений.

Заголовок содержит последовательность основных элементов (рис. 3.11).

Рис. 3.11. Структура заголовка программы

Комментарий– строка (строки) символов, подлежащих распечатке в тексте программы (исходном модуле).

Структура комментария:

/* текст */

, где текст – последовательность символов, создающих комментарий;

/* */ – ограничители комментария.

Комментарии могут быть заголовочными и внутренними.

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

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

ü Внимание! Комментарий, в отличие от символьной строки, улучшает понимание текста программы, а не результатов ее выполнения.

Комментарий может содержать любое число строк. Использование вложенных комментариев запрещается.

Рассмотрим варианты выполнения комментариев.

Пример комментария в виде отдельной строки:

/* Это строчный комментарий */

Примеры многострочных комментариев представлены в табл. 3.17.

Таблица 3.17

Трёхстрочный оформленный одним Трёхстрочный неструктурированный Трёхстрочный структурированный
/*Три строки – один комментарий */ /* Три строки */ /* – */ /* один комментарий */ /* Три строки */ /* – */ /* один комментарий */

Первый (левый) вариант может использоваться только в самостоятельных строках (не содержащих операторов).

Третий (второй) универсален, т.к. может применяться как в самостоятельных строках, так и завершать строки с операторами.

На основании изложенного выполним структурированный вариант конкретного заголовочного комментария:

/* Программа расчёта площади прямоугольника */

/* Линейный вычислительный процесс */

/* Разработал студент гр. А031 Юдин С.П. */

/* Дата последней модификации 12.11.2004 */

Его сокращённый вариант может иметь вид:

/* Расчёт площади прямоугольника. Линейный процесс. */

/* Разработал студент гр. А031 Юдин С.П. */

Внутренние комментарии также выполняются несколькими вариантами:

· оформленным отдельной строкой, например

/* Формирование ввода-вывода исходных данных */

scanf(…

printf(…

· записанным после оператора, например

int p; /* счетчик числа посетителей */

· завершающим операторы, например

int k; /* описатели */

float x, y; /* переменных */

Директива препроцессора– указание (команда), предписывающая препроцессору выполнение конкретных действий.

ü Внимание! Область действия директив – от точки их расположения до конца программы (файла).

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

Характерный признак директивы – специальный символ (#), указываемый перед ней. Между знаком # и названием директивы могут располагаться пробелы.

Наиболее распространены два вида директив;

· включающие;

· заменяющие (подставляющие).

Включающая директива– предписание подключения указанного в ней внешнего заголовочного файла в исходный модуль программы пользователя.

Структуры включающей директивы:

# include “СВФ”

# include <СВФ>

, где # – символ директивы;

include – название директивы (ключевое слово «включить»);

СВФ – спецификация внешнего заголовочного файла, включаемого в программу;

“ ” (< >) – ограничители СВФ.

Директива предписывает препроцессору включение в точке её расположения содержимого файла с указанной СВФ.

Ограничители < >, предписывают поиск заголовочного файла в стандартных каталогах. Ограничители “ ”, определяют начало поиска с каталога программ пользователя и продолжение поиска в стандартных каталогах.

В качестве СВФ, в большинстве случаев, используется структура:

имя.h

, где имя – идентификатор заголовочного файла;

h – тип (расширение имени) внешнего файла;

. – разделитель имени и типа.

Например, в качестве директив препроцессора могут использоваться:

Первая директива предписывает в исходный модуль включить файл с именем stdio (объявления функций стандартного ввода-вывода), вторая – stdlib (объявления стандартных функций), третья – math (объявления математических функций).

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

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

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

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

В частности файл stdio.h содержит объявления функций необходимых при решении любых задач:

scanf – форматный ввод с клавиатуры;

printf – форматный вывод на экран;

fprintf – форматный вывод в поток.

Подставляющая директива– предписание заменить какой-либо операнд программы на указанное значение.

Структура директивы:

#define имя значение

, где # – символ директивы;

define – название директивы (ключевое слово «заменить»);

имя – идентификатор переменной;

значение – константа, заменяющая указанную именем переменную.

Представленный вариант структуры является простейшим и используется при необходимости замены поименованной величины её конкретным значением.

Подставляющая директива предписывает во всём диапазоне своего действия заменить имя (указанное слева) на значение (указанное справа).

Например, директива

#define PI 3.1416

предписывает замену идентификатора (PI) указанным значением (3.1416) при выявлении его в теле программы.

Идентификаторы рекомендуется записывать заглавными буквами.

Описатели переменных подробно рассмотрены в разд. 3.5.2.3.

Рассмотрим некоторые дополнительные сведения. В языке Си/Си++ с каждым операндом связывается область действия – часть программы, в которой этот операнд доступен. Область действия зависит от расположения описателя операнда в программе.

Переменные, в зависимости от места описания в программе, делятся на глобальные (внешние) и локальные (внутренние).

Глобальные– переменные, описанные в заголовке программы, т.е. доступные в пределах всей программы (ее исходного модуля).

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

Локальные– переменные, описанные внутри тела функции (блока) и доступные в ее (его) пределах, но совершенно невидимые для других функций (внешних блоков), если они имеются.

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

Идентификаторы локальных переменных рекомендуется записывать строчными буквами.

Тело программы

Тело– основная конструкция программы, реализующая требования алгоритма (взаимосвязанных алгоритмов) решения.

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

В простейшем варианте решение состоит из одного (основного) алгоритма. При этом тело программы есть одна (главная) пользовательская функция.

Структуры возможных вариантов тела программы представлены на рис. 3.12.

Рис. 3.12. Варианты структур тела программы

Заголовок пользовательской функции определяется ее структурой (см. разд. 3.5.2.4).

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

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

Тело главной (дополнительной) функции оформляется в виде составного оператора и объединяет используемые в решении операторы.

Тело функции детализируется последовательностью элементов (рис. 3.13).

Структуры и правила описания переменных, операторов (ввода-вывода, присваивания и т. п.) и комментариев изложены ранее.

 

Рис. 3.13. Структура тела функции