Консольный ввод-вывод
Функции консольного ввода-вывода не используют входной буфер 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.