Консольный ввод-вывод

 

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

#include<conio.h>

Функция ввода символа (без отображения):

getch ()

прочитывает код символа нажатой клавиши и не отображает символ на экране.

Это свойство можно использовать в двух случаях:

1. Для ввода невидимых символов в память и использования их для проверки пароля программы:

char ch; // описание символьной переменной

puts (“Нажмите любую символьную клавишу.”);

ch = getch(); // ввод кода символа без его отображения

// Символ и его код могут быть выведены на экран:

printf («\nСимвол: %c (код: %d)», ch, ch);

 

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

getch (); /* появляется экран данных */

puts (“После просмотра данных нажмите любую клавишу.”);

 

 

Функция ввода символа (с отображением):

getche ()

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

 

Функция очистки экрана результатов:

clrscr ()

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

Ввод-вывод данных в стиле С++

 

Ввод-вывод в С++, также как и в С, рассматривается как поток данных, управляемый с помощью функций ввода-вывода. В С++ для поддержки ввода-вывода данных используется целая иерархия классов. Двунаправленный поток под­держивается классом iostream, объявление которого помещено в заголовочный файл, подключаемый к программе строкой:

#include<iostream.h>

 

Стандартный ввод-вывод

 

С++ поддерживает два потоковых объекта для ввода/вывода:

1. cin – стандартный ввод, как правило, с клавиатуры (аналог stdin в С).

2. cout – стандартный вывод, как правило, на экран (аналог stdout в C).

Для каждого потока переопределены два оператора:

>>– оператор извлечения (чтения) из потока (для ввода с клавиатуры: "считать из");

<<– оператор записи (вставки) в поток (для вывода на экран: "вывести на").

Функции ввода/вывода способны воспринимать аргументы любых основ­ных типов данных (char, char*(string), int, long, float, double).

Ввод для встроенных типов

 

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

Для ввода-вывода можно строить цепочки операций слева направо. Например, так можно ввести несколько данных в С++:

int i; float f;

cin >> i >> f;

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

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

Для типов с плавающей точкой float иdouble действие операции >> со­стоит в пропуске пробельных символов и преобразовании значения с плаваю­щей точкой до символа, который не может быть частью числа с плавающей точ­кой.

Вывод для встроенных типов

 

Операция <<, называемая вставкой, заменяет функцию вывода printf(). Левый операнд – это объект cout. Правый операнд может иметь любой тип, для которо­го определен вывод потоком для встроенных типов.

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

Например:

int i, k=234; double d ; char ch='A';

cout<<”Значение k=” << k <<’\n’; // в конце символ перевода строки

cin>> i >> d; // ввод данных i, d

cout<<”i=”<< I <<” d=”<< d <<’\n’; // вывод значений i, d

cout<<”ch=”<< ch; // вывод символа A

 

Пример 5.

Потоки ввода-вывода.

 

#include<iostream.h> // подключение библиотек ввода-вывода

void main()

{ int i;

char str[ ]=”Пример вывода в С++\n”;

cout<<”Вывод строки”<< str;

cout<<”Введите целое и длинное целое число: “;

long l; // переменная описывается перед первым использованием

cin >> i >> l; //ввод данных

cout<<”i=” << ” l=” <<’\n;

cout<<”Введите строку: ”;

cin >> str;

cout << ”Введена строка: ”<<str;

}

 

Пример 6.

Встроенные типы вставок (вывода данных). Целые типы преобразуются по правилам (по умолчанию) для printf.

 

#include<iostream.h> // подключение библиотек ввода-вывода

#include<stdio.h> // для printf

#include<conio.h> // для консольных функций

void main()

{ int i=5; int *pi=&i; long l=12345678; double d=345.6789; char ch='A';

clrscr(); // чистка экрана результатов

cout<<”Вывод с помощью функции printf():\n”);

printf(“i=%d адрес i pi=%#x l=%ld d=%.4f ch=%c\n”, i,pi,l,d,ch);

cout<<”Вывод с помощью потока cout:\n”;

cout << ”i=”<< i << ” адрес i=” << &i << ” l =” << l << ” d=” <<d;

cout<<” ch=”<<ch<<'\n';

getch(); // задержка экрана результатов

}

Результаты программы:

Вывод с помощью функции printf():

i=5 адрес i pi=0xfff4 l=12345678 d=345.6789 ch=A

Вывод с помощью потока cout:

i=5 адрес i=0x8f61fff4 l=12345678 d=345.6789 ch=A

Управление вводом-выводом

 

Символьные извлечения.

Для типа char действие операции >> состоит в пропуске пробельных символов и чтения следующего (непробельного) символа. Если требуется про­честь следующий символ (любой), то можно использовать одну из функций-эле­ментов get():

сhar ch;

cin.get(ch); // ch устанавливается на следующий символ потока, даже если это пробельный символ.

Следующий вариант get позволяет управлять числом извлекаемых симво­лов, их размещением и оконечным символом:

get(char* buf, int max, int term=’\n’).

 

Эта функция считывает символы из входного потока в символьный мас­сив buf до тех пор, пока не будет считано max -1символов, либо пока не встре­тится символ, заданный term, в зависимости от того, что будет раньше. Завер­шающий нуль-символ (‘\0’) добавляется автоматически. По умолчанию око­нечным символом, который не требуется задавать, является ‘\n’. Сам око­нечный символ в массив buf не считывается и из входного потока не удаляется. Массив buf должен иметь размер не менее max символов.

 

Пример 7.

Ввод строки цифр и преобразование их в целое число типа int с помощью функции atoi(s) и вывод числа в 10-ом, 16-ом, 8-ом форматах с использованием идентификаторов dec, hex, oct, вставленных в поток вывода для управления форматом выходного потока, endlаналог'\n'. (см. Манипуляторы).

 

#include<iostream.h> // подключение библиотек ввода-вывода

#include<conio.h> // для консольных функций

#include<stdlib.h> // для функции atoi()

const int size=35; // размер буфера строки

void main()

{ clrscr();

int value; // переменная для числа

char s [size]; // буфер строки

cout<<"Value= "; // ввод строки числа

value = atoi(s); // преобразование строки в число

cout<<"Decimal="<<dec<<value<<" Hexadecimal=0x"<<hex<<value

<<" Octal=0"<<oct<<value<<endl;

getch();

}

Результаты программы:

Value=123

Decimal=123 Hexadecimal=0x7b Octal=0173

 

Замечание. Для ввода строки вместо функции cin.get(s, size,'\n');можно использовать cin >> s;. Этот оператор сработает, но если пользователь введет бо­лее 34 символов, оператор ввода продолжит запись за пределами буфера s, при этом, возможно, данные и код, располагающиеся за буфером, будут уничтоже­ны. Такая операция может привести к краху системы!

Пример 8.

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

#include<iostream.h>

void main()

{ char s[35]; // буфер строки

char c; // переменная символа

cout<<"Введите строку не более 34 символов:\n";

cin.get(s, 35); // пропущен 3-й аргумент по умолчанию '\n'

cout<<"Вы ввели строку: "<<s<<endl;

if(cin.get(c) && c!='\n') // если следующий символ не '\n',то вывод

cout<<"Достигнута максимальная длина строки\n";

}

При вводе строки длиной более 34 символов она будет усечена, и ввод бу­дет безопасным. Одна проблема все же остается. Символ '\n' или другой сим­вол, завершающий ввод, остается в потоке и должен быть прочитан еще одним оператором cin.get(), как показано последним оператором if. Если cin.get()не читает символ '\n',ввод будет усечен. Этот факт необходимо учитывать при на­писании программ.

Проблему непрочитанного символа '\n' можно решить с помощью метода cin.getline()с тремя параметрами (совпадет с get()), при этом символ раздели­тель '\n' также помещается в принимающую строку символов (s).

 

Форматирование ввода/вывода

 

Форматирование ввода и вывода определяется флагами состояния форма­та. Их можно изменить с помощью специальных функций.

 

Ширина вывода.

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

int width(int w); // устанавливает поле шириной w символов и воз­вращает предыдущую ширину,

int width(); // возвращает предыдущую ширину, не внося из­менений.

По умолчанию width=0, т.е. вывод выполняется без заполнителей. При w≠0, если длина числа меньше w используются заполнители, иначе выводится фактическое число без усечения.

Например:

int i=123;

int oldw=cout.width(6);

cout << i; // вывод будет 123 (перед числом 3 пробела), затем width=0

cout.width(oldw); // восстановление предыдущей ширины width=6

 

После каждой форматной вставки ширина обнуляется, например:

int i, j;

cout.width(4);

cout << i <<" "<< j <<;

Здесь i будет выведено четырьмя символами, однако пробел и j будут иметь минимально необходимое число символов.

 

Заполнители и дополнение вправо и влево.

Символ-заполнитель и направление дополнения зависят от установок вну­тренних флагов, отвечающих за эти параметры.

По умолчанию символом-заполнителем является пробел. Изменить данное умолчание позволяет функция fill:

int i=123;

cout.fill ("*");

cout.width(6);

cout<< i; // на экран будет выведено ***123

 

По умолчанию устанавливается выравнивание по правому краю (дополне­ние символами-заполнителями). Это можно изменить функциями setf и unsetf:

int i=56;

cout.width(6);

cout.fill ("#");

cout.setf (ios::left, ios::adjustfield);

cout<< i; // на экране: 56####

Второй аргумент сообщает setf, какие биты флага должны быть установ­лены. Первый аргумент сообщает, в какие именно значения устанавливаются эти биты.

Можно также использовать манипуляторы setfill, setiosflags, resetiosflags.

 

Манипуляторы.

Это специальные операции (похожие на функции) для более простого из­менения ширины и других параметров форматирования. Для их использования программа должна иметь строку:

#include<iomanip.h>

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

 

Пример 9.

Применение функций и манипуляторов форматирования вывода в про­грамме.

 

#include<iostream.h>

#include<conio.h>

#include<iomanip.h>

void main()

{ clrscr();

int i=36, j=45;

cout<<"Вывод с установленной шириной поля 5 числа i:\n";

int oldw=cout.width(5); // установка ширины поля вывода

cout<< i <<'\n';

cout<<"После каждой вставки формата ширина поля=0:\n";

cout<< " oldw=" << oldw << '\n';

cout<< i << '\n';

cout<< "Установка поля 5 влияет только на 1-ю переменную:\n";

cout.width(5);

cout<< i << " " << j << '\n';

cout<< "Манипулятор setw(5) упрощает вывод переменных:\n";

cout<< setw(5) << i << setw(5) << j << '\n';

cout<< "Манипуляторы dec, hex, oct изменяют сист. счисл. \n";

cout<< "(оставляя эти изменения в силе) — вывод i:\n";

cout<< dec << i << " " << hex << i << " " << oct << i <<endl;

cout<< "Манипулятор endl аналог '\n' очищает поток"<<endl;

cout<< "i= " << i <<endl;

cout<< "Заполнитель пробел можно заменить на *"<<endl;

cout.fill ( '*' ); // задание символа заполнения функцией fill

cout<< setw(6) << i << endl; // установка ширины поля 6 числа i

cout<< "Выравнивание можно изменить функцией setf:"<<endl;

cout.width(6);

cout.setf(ios::left, ios::adjustfield);

cout<< "i = " << i <<endl;

getch();

}

 

Вывод чисел с плавающей точкой.

Большие и малые числа выводятся в экспоненциальном формате (е, Е), а не фиксированном. Например, число 1234567.8 печатается 1.2345678Е+07.

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

Для вывода десятичных чисел в фиксированном формате можно использо­вать следующие операторы:

cout.setf(ios::fixed, ios::floated);

cout.setf(ios::showpoint);

Первый вызов функции setf обеспечивает печать чисел в фиксированном, а не экспоненциальном представлении. Второй вызов задает печать десятичной точки, даже если дробная часть числа равна 0.

Управление числом десятичных позиций при выводе выполняется с помо­щью манипулятора установки точности:

cout<< setprecision(2) << x;

например, вместо числа 16.38567 печатается 16.39.

Структура программы С/С++

 

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

С-программа оформляется в виде одной или нескольких подпрограмм (вспомогательных программных единиц), называемых функциями. При этом только одна функция является обязательной и за ней закреплено имя main (главная, основная), поскольку с нее начинается выполнение программы. Простая С-программа является описанием главной функции, которое включает заголовок функции и тело функции, заключенное в операторные скобки { } и называемое блоком:

 

тип main (параметры) // заголовок функции

{ // блок – тело функции:

описательная часть; // описания данных

исполняемая часть; // операторы

} , где

 

тип – ключевое слово типа, для возвращаемого функцией значения, либо void (отсутствие типа), если значение не возвращается;

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

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

Исходная С-программа набирается и редактируется в программной среде как текстовый файл, который может содержать дополнительные части и должен сохраняться во внешней памяти с собственным именем и расширением “.cpp” в студенческом каталоге группы по правилам файловой системы компьютера, например, D:\$STUDENT\GR_1006\myprog.cpp.