Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Решение. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include stdafx.h#include






 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include " stdafx.h" #include < iostream> #include < fstream> #include < iomanip> using namespace std; int main() { setlocale (LC_ALL, " RUS"); int i, n; double a; //описывает поток для записи данных в файл ofstream f; //открываем файл в режиме записи, //режим ios:: out устанавливается по умолчанию f.open(" D: \\sites\\accounts.txt", ios:: out); //вводим количество вещественных чисел cout< < " n="; cin> > n; //цикл для ввода вещественных чисел//и записи их в файл for (i=0; i< n; i++) { cout< < " a="; //ввод числа cin> > a; f< < a< < " \t"; } //закрытие потока f.close(); system(" pause"); return 0; }

 

Чтение информации из текстового файла

Для того чтобы прочитать информацию из текстового файла, необходимо описать переменную типа ifstream. После этого нужно открыть файл для чтения с помощью оператора open. Если переменную назвать F, то первые два оператора будут такими:

 

1 2 ifstream F; F.open(" D: \\sites\\accounts.txt", ios:: in);

 

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

Например, для чтения данных из потока F в переменную a, оператор ввода будет выглядеть так:

F> > a;

 

Два числа в текстовом редакторе считаются разделенными, если между ними есть хотя бы один из символов: пробел, табуляция, символ конца строки. Хорошо, когда программисту заранее известно, сколько и какие значения хранятся в текстовом файле. Однако часто известен лишь тип значений, хранящихся в файле, при этом их количество может быть различным. Для решения данной проблемы необходимо считывать значения из файла поочередно, а перед каждым считыванием проверять, достигнут ли конец файла. А поможет сделать это функция F.eof(). Здесь F - имя потока функция возвращает логическое значение: true или false, в зависимости от того достигнут ли конец файла.

Следовательно, цикл для чтения содержимого всего файла можно записать так:

 

//организуем для чтения значений из файла, выполнение
//цикла прервется, когда достигнем конец файла,
//в этом случае F.eof() вернет истину
while (! F.eof())
{
//чтение очередного значения из потока F в переменную a
F> > a;
//далее идет обработка значения переменной a
}

ПРОВЕРКА ПОТОКА

Каждый поток (istream или ostream) имеет ассоциированное с ним состояние, и обработка ошибок и нестандартных условий осуществляется с помощью соответствующей установки и проверки этого состояния.

Поток может находиться в одном из следующих состояний:

enum stream_state (* _good, _eof, _fail, _bad *);

Если состояние _good или _eof, значит последняя операция ввода прошла успешно. Если состояние _good, то следующая опрация ввода может пройти успешно, в противном случае она зкончится неудачей. Другими словами, применение операции ввода к потоку, который не находится в состоянии _good, является пустой операцией. Если делается попытка читать в переменную v, и операция оканчивается неудачей, значение v должно отаться неизменным (оно будет неизменным, если v имеет один из тех типов, которые обрабатываются функциями членами istream или ostream). Отличие между состояниями _fail и _bad очень незначительно и предсавляет интерес только для разработчиков операций ввода. В состоянии _fail предполагается, что поток не испорчен и никакие символы не потеряны. В состоянии _bad может быть все что угодно.

Состояние потока можно проверять например так:

switch (cin.rdstate()) (* case _good: // последняя операция над cin прошла успешно break; case _eof: // конец файла break; case _fail: // некоего рода ошибка форматирования // возможно, не слишком плохая break; case _bad: // возможно, символы cin потеряны break; *)

Для любой переменной z типа, для которого определены операции «„ и “», копирующий цикл можно написать так:

while (cin»»z) cout «„ z «««\n“;

Например, если z – вектор символов, этот цикл будет брать стандартный ввод и помещать его в стандартный вывод по одному слову (то есть, последовательности символов без пробла) на строку.

Когда в качестве условия используется поток, происходит проверка состояния потока, и эта проверка проходит успешно (то есть, значение условия не ноль) только если состояние _good. В частности, в предыдущем цикле проверялось состояние istream, которое возвращает cin»»z. Чтобы обнаружить, почему цикл или проверка закончились неудачно, можно исследовать состояние. Такая проверка потока реализуется операцией преоразования (#6.3.2).

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

 

РАБОТА С БИНАРНЫМИ ФАЙЛАМИ

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

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

 

 

Для записи в файл использован класс ofstream, для чтения из файла использован класс ifstream

· ifstream – класс, функции которого используются для чтения файлов

· ofstream – класс, функции которого используются для записи файлов

Название класса эквивалентно типу переменной, поэтому после названия класса объявляется объект, тип которого будет соответствовать классу.
out – Объект, тип которого есть класс для записи файлов (В коде: ofstream out).
in – Объект, тип которого есть класс для чтения файлов (В коде: ifstream in)
out и in могут быть названы произвольно, а вот ifstream и ofstream аналогично типам данных, как попало не назовешь.
Чтобы созданные объекты сработали, нужно им передать параметры. Первый параметр – путь к файлу, второй параметр – способ обработки файла (способы разные бывают)
Если вы присмотритесь к тому, что внутри скобок, то заметите во время записи в файл и во время чтения из файла там изменилась только одна переменная, над которой проводится действие. (изменился передаваемый в класс объект)
Во время записи в файл, мы записывали в файл значение y и вот этот самый y стоит в первом случае.
Во время чтения информации, мы считывали информацию в x и вот этот самый x стоит во втором случае.

 

1. Связать его с файлом данных и открыть (open) для работы в определенном режиме, с обязательным указанием двоичного режима ios:: binary (по умолчанию потоки открываются в текстовом режиме):

void ifstream:: open(const char *имя_файла, openmode режим=ios:: in| ios:: binary);

void ofstream:: open(const char *имя_файла,
openmode режим=ios:: out|ios:: trunс| ios:: binary);

void fstream:: open(const char *имя_файла,
openmode режим=ios:: in|ios:: out| ios:: binary);

 

где имя_файла – имя файла, в которое может входить спецификатор пути;

режим – задает режим открытия файла (см. лаб. раб. №10).

 

Для записи в поток в C++ используется метод write:

basic_ostream< _Elem, _Tr> & write (const char_type *_Str, streamsize _Count);

 

Для чтения из потока используется метод read:

basic_istream< _Elem, _Tr> & read(const char_type *_Str, streamsize _Count);

_Count число выводимых (вводимых) в поток байт

_Str символы выводимые(вводимые) в (из) поток(а)

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

для потоков открытых на ввод:

basic_istream< _Elem, _Tr> & seekg(pos_type _Pos);

basic_istream< _Elem, _Tr> & seekg(off_type _Off, ios_base:: seekdir _Way);

 

для потоков открытых на вывод в C++ пишется так:

basic_ostream< _Elem, _Tr> & seekp(pos_type _Pos);

basic_ostream< _Elem, _Tr> & seekp(off_type _Off, ios_base:: seekdir _Way);

 

_Pos позиция в потоке для чтения (номер байта)

_Off позиция относительно _Way.

_Way одно из перечислений ios_base (beg, cur, end):

перечисление описание
ios_base:: beg начало файла
ios_base:: end конец файла
ios_base:: cur текущая позиция

 

Например:

ofstream fout(“my.dat”, ios:: ate|ios:: binary);

//устанавливаем указатель на начало потока

fout.seekp(0);

fout.write((char *) & el, sizeof el);

 

ifstream fin(“my.dat”, ios:: ate|ios:: binary);

//передвигаем указатель на 10 байт перед концом потока

fin.seekg(-10, ios_base:: end);

fin.read((char *) & el, sizeof el);

 

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

1. Для закрытия потока используется функция close().

РАБОТА С МАНИПУЛЯТОРАМИ

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

Манипулятор Назначение Ввод/вывод
dec Ввод/вывод данных в десятичной форме ввод и вывод
endl Вывод символа новой строки с передачей в поток всех данных из буфера вывод
ends Вывод нулевого символа вывод
flush Передача в поток содержи­мого буфера вывод
hex Ввод/вывод данных в шест­надцатиричной системе ввод и вывод
oct Ввод/вывод данных в восьме­ричной форме ввод и вывод
resetiosflags(long f) Сбрасывает флаги, указанные в f ввод и вывод
setbase(int base) Устанавливает базу счисле­ния равной параметру base вывод
setfill(int ch) Устанавливает символ заполнения равным ch вывод
setiosflags(long f) Устанавливает флаги, указанные в f ввод и вывод
setprecision(int p) Устанавливает число цифр после запятой вывод
setw(int w) Устанавливает ширину поля равной w вывод
ws Пропускает начальный символ-разделитель ввод
Таблица: Манипуляторы ввода/вывода С++

Для использования манипуляторов с параметрами в программу необходимо вклю­чить заголовочный файл iomanip.h.
Манипуляторы могут использоваться в составе выражений ввода/вывода. Ниже представлен пример программы, использующей манипуляторы для изменения формата вывода:

#include < iostream.h>
#include < iomanip.h>
int main()
{
cout < < setiosflags(ios:: fixed);
cout < < setprecision (2) < < 1000.243 < < endl;
cout < < setw (20) < < " Hello there.";
return 0;
}

Программа выводит следующие данные:

1000.24
Hello there.

 

Обратим внимание, как манипуляторы появляются в последовательности операторов ввода/вывода. Когда манипуляторы не имеют аргументов, как манипулятор endl в этой программе, за ними не следуют скобки. Причина этого в том, что оператору < < передается адрес манипулятора.

Следующая программа использует функции setiosflags() для установки флагов scientific и showpos потока cout:

#include < iostream.h>
#include < iomanip.h>
main ()
{
cout < < setiosflags(ios:: showpos);
cout < < setiosflags(ios:: scientific);
cout < < 123 < < " " < < 123.23;
return 0;
}

Следующая программа использует манипулятор ws для пропуска идущих вначале символов- разделителей при вводе строки в переменную s:

#include < iostream.h>
int main()
{
char s [80];
cin > > ws > > s;
cout < < s;
}

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

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

Флаги форматирования позволяют включить или выключить один из параметров ввода/вывода. Чтобы установить флаг ввода/вывода, необходимо вызвать функцию setf(), если необходимо отключить флаг вывода, то используется функция unsetf(). Далее показаны конструкции установки и снятия флагов вывода.

  // установка флага вывода cout.setf(ios:: /*name_flag*/); // где name_flag - это имя флага
Таблица 2 — Манипуляторы форматирования в С++  
Манипулятор Назначение Пример Результат  
endl Переход на новую строку при выводе cout < < «website:» < < endl < < «cppstudio.com»; website: cppstudio.com  
boolalpha Вывод логических величин в текстовом виде (true, false) bool log_true = 1; cout < < boolalpha < < log_true < < endl; true  
noboolalpha Вывод логических величин в числовом виде (true, false) bool log_true = true; cout < < noboolalpha < < log_true < < endl;    
oct Вывод величин в восьмеричной системе счисления int value = 64; cout < < oct < < value < < endl; 1008  
dec Вывод величин в десятичной системе счисления (по умолчанию) int value = 64; cout < < dec < < value < < endl; 6410  
hex Вывод величин в шестнадцатеричной системе счисления int value = 64; cout < < hex < < value < < endl; 408  
showbase Выводить индикатор основания системы счисления int value = 64; cout < < showbase < < hex < < value < < endl; 0× 40  
noshowbase Не выводить индикатор основания системы счисления (по умолчанию). int value = 64; cout < < noshowbase < < hex < < value < < endl;    
uppercase В шестнадцатеричной системе счисления использовать буквы верхнего регистра (по умолчанию установлены буквы нижнего регистра). int value = 255; cout < < uppercase < < hex < < value < < endl; FF16  
nouppercase В шестнадцатеричной системе счисления использовать буквы нижнего регистра (по умолчанию). int value = 255; cout < < nouppercase < < hex < < value < < endl; ff16  
showpos Вывод знака плюс + для положительных чисел int value = 255; cout < < showpos< < value < < endl; +255  
noshowpos Не выводить знак плюс + для положительных чисел (по умолчанию). int value = 255; cout < < showpos< < value < < endl;    
scientific Вывод чисел с плавающей точкой в экспоненциальной форме double value = 1024.165; cout < < scientific < < value < < endl; 1.024165e+003  
fixed Вывод чисел с плавающей точкой в фиксированной форме (по умолчанию). double value = 1024.165; cout < < fixed < < value < < endl; 1024.165  
setw(int number) Установить ширину поля, где number - количество позиций, символов (выравнивание по умолчанию по правой границе). Манипулятор с параметром. cout < < setw(40) < < «cppstudio.com» < < endl; __cppstudio.com  
right Выравнивание по правой границе(по умолчанию). Сначала необходимо установить ширину поля(ширина поля должна быть заведомо большей чем, длинна выводимой строки). cout < < setw(40) < < right < < «cppstudio.com» < < endl; __cppstudio.com  
left Выравнивание по левой границе. Сначала необходимо установить ширину поля(ширина поля должна быть заведомо большей чем, длинна выводимой строки). cout < < setw(40) < < left < < «cppstudio.com» < < endl; cppstudio.com__  
setprecision(int count) Задаёт количество знаков после запятой, где count - количество знаков после десятичной точки cout < < fixed < < setprecision(3) < < (13.5 / 2) < < endl; 6.750  
setfill(int symbol) Установить символ заполнитель. Если ширина поля больше, чем выводимая величина, то свободные места поля будут наполняться символом symbol- символ заполнитель cout < < setfill(’0′) < < setw(4) < < 15 < < ends < < endl;    

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

 

Ещё один способ форматирования — форматирование с помощью манипуляторов. Манипулятор — объект особого типа, который управляет потоками ввода/вывода, для форматирования передаваемой в потоки информации. Отчасти манипуляторы дополняют функционал, для форматирования ввода/вывода. Но большинство манипуляторов выполняют точно, то же самое, что и функции с флагами форматирования. Есть случаи, когда проще пользоваться флагами или функциями форматирования, а иногда удобнее использовать манипуляторы форматирования. Именно по этому в С++ предусмотрено несколько средств форматирования ввода/вывода. В таблице 2 показаны основные манипуляторы форматирования С++.

МЕХАНИЗМ ОБРАБОТКИ ИСКЛЮЧЕНИЙ

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

Оператор try определяет блок, в котором необходимо отследить исключения.

Оператор throw вызывает исключение указанного типа.

Оператор catch определяет блок обработки исключения указанного типа. Подобных блоков может быть несколько для каждого типа. Если же тип исключения не важен или нужно обработать исключения по умолчанию, то в качестве аргумента используется троеточие.

В современном C++ в большинстве случаев предпочтительный способ уведомления и обработки логических ошибок и ошибок среды выполнения — использование исключений. Это особенно заметно, когда стек может содержать несколько вызовов функции между функцией, которая обнаруживает ошибку и функцией, которая содержит контекст для получения сведений о его обработки. Исключения предоставляют формальный, четко определенный способ для передачи обнаружившим ошибку кодом сведений вверх по стеку вызовов.

Ошибки программы обычно делятся на две категории: логические ошибки, вызванные ошибками программирования (ошибка " индекс вне диапазона"), а также ошибки среды выполнения, которые не может контролировать программист, например ошибка " сетевая служба недоступна". В стиле программирования C и в модели COM отчеты об ошибках управляются возвратом значения, представляющего код ошибки или код статуса для определенной функции, или заданием глобальной переменной, которая может дополнительно извлекаться вызывающим объектом после каждого вызова функций, чтобы посмотреть, был ли составлен отчет об ошибках.

Исключения являются предпочтительными в современном языке C++ по следующим причинам:

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

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

· Механизм освобождения стека исключения уничтожает все объекты в области в соответствии с правилами чётким после создания исключения.

· Исключение обеспечивает четкое разделение между кодом, который обнаруживает ошибку, и кодом, который обрабатывает ошибку.

Давайте же разберем основы обработки исключений в С++. Чтобы комфортно работать с исключениями в С++ вам нужно знать лишь три ключевых слова:

  • try (пытаться) - начало блока исключений;
  • catch (поймать) - начало блока, " ловящего" исключение;
  • throw (бросить) - ключевое слово, " создающее" (" возбуждающее") исключение.
· void func()· {· try· {· throw 1; · }· catch(int a)· {· cout < < " Caught exception number: " < < a < < endl; · return; · }· cout < < " No exception detected! " < < endl; · return; · } · #include < iostream> · using namespace std; · · float divfunc(float a, float b){· if(b==0) throw 1; · return a/b; · }· · int main() {· float a, b, c; · cout< < " input a: "; · cin> > a; · cout< < " input b: "; · cin> > b; · · try {· c=divfunc(a, b); · // если b==0, то следующая строчка · // не выполнится· cout< < " c=" < < c< < endl; · }· catch(...) { · cout< < " exception" < < endl; · }· · return 0; · }





© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.