Задания для самостоятельного выполнения.

Лабораторная работа 2. Работа с двоичными файлами в ОС Windows на языке С++ Цель работы: изучение методов работы с двоичными файлами и битовой информацией в ОС Windows на языке С++   При записи информации в двоичный файл символы и числа преобразуются в последовательность из байтов. Для того чтобы записать данные в двоичный файл, необходимо: описать файловую переменную типа FAIL * с помощью оператора FILE *filename;. Здесь filename — имя переменной, где будет храниться указатель на файл. открыть файл с помощью функции fopen записать информацию в файл с помощью функции fwrite закрыть файл с помощью функции fclose Для того чтобы считать данные из двоичного файла, необходимо: описать переменную типа FILE * открыть файл с помощью функции fopen считать необходимую информацию из файла с помощью функции fread, при этом следить за тем достигнут ли конец файла. закрыть файл с помощью функции fclose Рассмотрим основные функции, необходимые для работы с двоичными файлами. Для открытия файла в зависимости от используемых библиотек используются функцииfopenилиfopen_s.В них последним параметром является mode - строка, определяющая режим работы с файлом; возможны следующие ее значения: «rb» — открываем двоичный файл в режиме чтения; «wb» — создаем двоичный файл для записи; если он существует, то его содержимое очищается; «ab» — создаем или открываем двоичный файл для дозаписи в конец файла; «rb+» — открываем существующий двоичный файл в режиме чтения и записи; «wb+» — открываем двоичный файл в режиме чтения и записи, существующий файл очищается; «ab+» — двоичный файл открывается или создается для исправления существующий информации и добавления новой в конец файла. Для закрытия файла предназначена функция fclose intfclose(FILE *filename); Возвращает 0 при успешном закрытие файла и NULL в противном случае. Функция remove предназначена для удаления файлов. intremove(constchar *filename); Эта функция удаляет с диска файл с именем filenаmе. Удаляемый файл должен быть закрыт. Функция возвращает ненулевое значение, если файл не удалось удалить. Для переименования файлов предназначена функция rename: int rename(const char *oldfilename, const char *newfilename); Первый параметр — старое имя файла, второй — новое. Возвращает 0 при удачном завершении программы. Чтение из двоичного файла осуществляется с помощью функции fread: fread(void *ptr, size, n, FILE *filename); Функция fread считывает из файла filename в массив ptr n элементов размера size. Функция возвращает количество считанных элементов. После чтения из файла его указатель смещается на n*size байт. Запись в двоичный файл осуществляется с помощью функции fwrite: fwrite(const void *ptr, size, n, FILE *filename); Функция fwrite записывает в файл filename из массива ptr n элементов размера size. Функция возвращает количество записанных элементов. После записи информации в файл указатель смещается на n*size байт. Для контроля достижения конца файла есть функция feof: intfeof(FILE *filename); Она возвращает ненулевое значение если достигнут конец файла. Для просмотра содержимого двоичных (бинарных) файлов необходимы специальные программы. Обычно они представляют двоичную байтовую информацию в шестнадцатеричной системе счисления. В ней каждый байт, состоящий из 8 бит, разбивается на двететрады (части по 4 бита), которые заменяются одной шестнадцатеричной цифрой по правилу: 0) 00002 - 016;                8) 10002 - 816; 1) 00012 - 116;                9) 10012 - 916; 2) 00102 - 216;               10) 10102 - A16; 3) 00112 - 316;                11) 10112 - B16; 4) 01002 - 416;                12) 11002 - C16; 5) 01012 - 516;               13) 11012 - D16; 6) 01102 - 616;               14) 11102 - E16; 7) 01112 - 716;               15) 11112 - F16. Для записи целых шестнадцатеричных чисел в отдельные байты в языке С++ используется шестнадцатеричная форма записи, начинающаяся с Ох. Например, после присваиваний: chars1,s2 s1=OxAB;                 s2=Ox2F; в байтах s1 и s2 будут содержаться шестнадцатеричные числа AB16 и 2F16, которые соответствуют двоичным словам 101010112 и 001011112.        Шестнадцатеричная система счисления позволяет непосредственно записывать двоичные числа в байты. Например, если в байтs1 необходимо записать последовательность значений 8 бит, равную 101011002, то сначала эта последовательность разбивается на две тетрады(10102 и 11002), они переводятся в соответствующие шестнадцатеричные числа (А16 и C16), а затем выполняется присваивание: s1=OxAC; Для считывания отдельных байтов (в переменную типа char) с игнорированием пробелов можно использовать создание потока и обычны й потоковый вывод.   Пример 1. Написать функцию prf(stringf) для вывода на экран содержимого каждого байта файла с именем f в виде символа, шестнадцатеричного числа и двоичного числа. Между выводимыми числами поставить знак “=” (равенство).Для примера вывести на экран содержимое бинарного  файла C:\\TEXT\\d.dat. Решение: #include"stdafx.h" #include<iostream> #include<fstream> #include<iomanip> #include<stdlib.h> #include<string> usingnamespace std; voidprf(string f);   void main(){ string p; p="C:\\TEXT\\d.dat"; prf(p); }   voidprf(stringf) { setlocale (LC_ALL, "RUS"); unsignedint n, i,j,b,b2,st,fc,sc; unsignedchar G[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; unsignedint *d = newunsignedint [8]; unsignedchar *a; charch, F, S; fstreampf; pf.open(f);//открываем файл в режиме чтения a=newunsignedchar[1000]; //выделение памяти для буферного массива а i=0; while (!pf.eof()){ //запись содержимого файла в буферный массив а pf>>ch; a[i]=(unsignedint )ch; i+=1; //чтение очередного байта из файла в массив a }; n=i-1; for (i=0; i<n; i++) { cout<<a[i]<<"=";//выводсимвола a[i] наэкран b=(int)a[i]; //перевод символа в целочисленное представление fc=b/16; sc=b-fc*16; F = G[fc]; S = G[sc];//перевод символа в 16-ричный вид cout<<F<<S<<"=";//вывод 16-ричной кодировки символа a[i] на экран for (j=0; j<8; j++) { b2=b/2; d[j]= b-2*b2; b=b2; };//перевод символа в двоичный вид cout<<d[7]<<d[6]<<d[5]<<d[4]<<d[3]<<d[2]<<d[1]<<d[0];//вывод 2-чной кодировки символа a[i] на экран cout<<endl; // переход на новую строку }; pf.close(); //закрываемфайл system("pause"); } Задания: 1. Модифицировать текст программы таким образом, чтобы на экран каждое новое значение выводилось бы в системе счисления с основанием 4. 2. Модифицировать текст программы таким образом, чтобы на экран каждое новое значение выводилось бы в одной строке в системе счисления с основанием 16 через два пробела.      Для считывания всех подряд байтов (в том числе - пустых) можно использовать функцию fscanf_s. Пример 2. Написать функцию prfp(char * name)для вывода на экран содержимого каждого байта файла с заданным именем в виде символа, шестнадцатеричного числа и двоичного числа. Между выводимыми числами поставить знак “=” (равенство).Для примера вывести на экран содержимое бинарного файла C:\\TEXT\\d.dat.   #include"stdafx.h" #include<iostream> #include<fstream> #include<iomanip> #include<stdlib.h> #include<string> usingnamespace std;   voidprfp(char * name);   void main(){ char * fileName = "C:\\TEXT\\d.dat"; prf(fileName); }   voidprfp(char * name){ setlocale (LC_ALL, "RUS"); int n, i,j,b,b2,fc,sc; unsignedchar G[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; unsignedint *d = newunsignedint [8]; unsignedchar a; unsignedchar F, S; FILE *f; char c; char *mc; mc = newchar[1000]; int err=fopen_s(&f, name, "r"); if(err){return;}; cout<<"FILE = "; i=-1; while(fscanf_s(f,"%c",&c,1)==1) { i=i+1; printf("%c",c); mc[i]=c; }; n=i+1; cout<<endl; for (i=0; i<n; i++) { cout<<mc[i]<<"=";//выводсимволаa[i] наэкран a = (unsignedchar)mc[i]; b=(int)a; //перевод символа в целочисленное представление fc=b/16; sc=b-fc*16; //cout<<"fc="<<fc<<"sc="<<sc; F = G[fc]; S = G[sc];//перевод символа в 16-ричный вид cout<<F<<S<<"=";//вывод 16-ричной кодировки символа a[i] на экран for (j=0; j<8; j++) { b2=b/2; d[j]= b-2*b2; b=b2; };//перевод символа в двоичный вид cout<<d[7]<<d[6]<<d[5]<<d[4]<<d[3]<<d[2]<<d[1]<<d[0];//вывод 2-чной кодировки символа a[i] на экран cout<<endl; // переход на новую строку }; fclose(f); system("pause"); } Рассмотримпримеры записи и чтения содержимого двоичных файлов. Пример 3.Создать двоичный файл D:\\str.dat,записать в него вводимое с клавиатуры целое число n, а затем - nвводимых с клавиатуры вещественных чисел. Решение: #include "stdafx.h" #include <iostream> using namespace std; void main() { setlocale (LC_ALL, "RUS"); int n, i; doublea; FILE *f; //описываем файловую переменную fopen_s(&f,"D:\\str.dat", "wb");//создаем двоичный файл в режиме записи cout<<"n="; cin>>n; //вводчисла n fwrite(&n, sizeof(int), 1, f); // запись целого числаn в файл for (i=0; i<n; i++){//цикл для ввода cклавиатуры в файл n вещественных чисел cout<<"a=";//вывод на экран запроса на ввод очередного веществен.числа cin>>a;//вводочередного вещественного числа с клавиатуры fwrite(&a, sizeof(double), 1, f); //запись вещественного числа в двоичный файл } fclose(f);//закрываемфайл system("pause"); } Задания: 1. Модифицировать текст программы таким образом, чтобы в файл записывались не вещественные, а целочисленные значения. 2. Модифицировать текст программы таким образом, чтобы в файл после каждого вещественного числа записывалось целочисленное значение, равное вещественному с отброшенной дробной частью. 3. Модифицировать текст программы таким образом, чтобы в заданный двоичныйфайл записывались 5 вводимых с экрана логических значений (0 – false, 1 - true).   Пример 4. Вывести на экран содержимое созданного в прошлой задаче двоичного файлаD:\\str.datв виде вещественных чисел. Решение:   #include "stdafx.h" #include <iostream> using namespace std; int main() { setlocale (LC_ALL, "RUS"); int n, i; double *a; FILE *f; //описание файловой переменной fopen_s(&f,"D:\\str.dat", "rb");//открытие двоичного файла в режиме чтения fread(&n, sizeof(int), 1, f); //чтение из файла 1-го целого числа в переменную n cout<<"n="<<n<<endl; //вывод числа n на экран a=newdouble[n]; //выделение памяти для массива а из n вещественных чисел fread(a, sizeof(double), n, f); //чтение n веществен. чисел из файла в массив a for (i=0; i<n; i++) cout<<a[i]<<"\t";//выводмассиваанаэкран cout<<endl; // переход на новую строку fclose(f); //закрываемфайл system("pause"); return 0; }     Задания: 1. Модифицировать текст программы таким образом, чтобы при выводе на экран, каждое новое значение записывалось с новой строки. 2. Модифицировать текст программы таким образом, чтобы вещественные числа выводились на экран трижды подряд.   Двоичный файл — последовательная структура данных, после открытия файла доступен первый байт, хранящийся в нем. Можно последовательно записывать или считывать данные из файла.     В случае объемных файлов удобнее использовать функцию fseek перемещения указателя файла к заданному байту. intfseek(FILE *filename, long int offset, int origin); Функция устанавливает указатель текущий позиции файла F в соответствии со значением начала отсчета origin и смещения offset. Параметр offset равен количеству байтов, на которые будет смещен указатель файла относительно начала отсчета, заданного параметром origin. В качестве значения для параметра origin должно быть взято одно из следующих значений отсчета смещения offset, определенных в заголовке stdio.h: SEEK_SET — с начала файла; SEEK_CUR — с текущей позиции; SEEK_END — с конца файла. Функция возвращает нулевое значение при успешном выполнение операции, ненулевое — при возникновении сбоя при выполнении смещения Функция fseek фактически реализует прямой доступ к любому значению в файле. Необходимо только знать месторасположение (номер байта) значения в файле. Пример 5.Выдать вещественное число с номером 15 из двоичного файла"D:\\num.dat",содержащего вещественные числа,на экран двумя способами: 1) c помощью последовательного доступа (вариант 1); 2) при помощи указателя fseek (вариант 2).. Решение. #include "stdafx.h" #include <iostream> using namespace std; void main(){setlocale (LC_ALL, "RUS"); int n, i; double a; FILE *f; fopen_s(&f,"D:\\num.dat", "rb"); for (i=0; i<14; i++) fread(&a, sizeof(double), 1, f); cout<<"Var1 a="<<a<<"\n"; fseek(f,14*sizeof(double),SEEK_SET); fread(&a,sizeof(double),1,f); cout<<"Var2 a="<<a<<"\n"; fclose(f); system("pause"); } Задания: 1. Модифицировать текст программы для аналогичного считывания из файла, содержащего целые числа типа int. 2. Модифицировать текст программы таким образом, чтобы на экран трижды было выведено последнее число файла, а затем дважды – предпоследнее.   Пример 6.В созданном ранее двоичном файлеD:\\str.datпоменять местами наибольшее и наименьшее из вещественных чисел. Решение. Алгоритм решения задачи состоит из следующих этапов: чтение вещественных чисел из файла в массив a. поиск в массиве а максимального (max) и минимального (min) значения и их номеров (imax, imin). перемещения указателя файла к максимальному значению и запись min. перемещения указателя файла к минимальному значению и запись max. Текст программы решения задачи с комментариями. #include "stdafx.h" #include <iostream> using namespace std; int main() { setlocale (LC_ALL, "RUS"); int n, i, imax, imin; double *a, max, min; FILE *f; //открытие файла в режиме чтения и записи fopen_s(&f,"D:\\str.dat", "rb+"); //считываем из файла в переменную n количество //вещественных чисел в файле fread(&n, sizeof(int), 1, f); cout<<"n="<<n<<endl; a=newdouble[n];//выделение памяти для хранения вещ.чиселв массиве a fread(a, sizeof(double), n, f);//считывание из файла в массив а вещ. чисел //поиск максимального и минимального элементови их индексов в массиве а for (imax=imin=0, max=min=a[0], i=1; i<n; i++){        if (a[i]>max){max=a[i];imax=i;} if (a[i]<min){min=a[i];imin=i;} } //перемещениеуказателякмаксимальномуэлементу fseek(f, sizeof(int)+imax*sizeof(double), SEEK_SET); //запись min вместо максимального элемента файла fwrite(&min, sizeof(double), 1, f); //перемещениеуказателякминимальномуэлементу fseek(f, sizeof(int)+imin*sizeof(double), SEEK_SET); //запись max вместо минимального элемента файла fwrite(&max, sizeof(double), 1, f); fclose(f);//закрытие файла cout<<"Максимальный элемент = "<<max<<"\n"; cout<<"Минимальный элемент = "<<min<<"\n"; delete []a;//освобождениепамяти system("pause"); return 0; } Задания: 1. Модифицировать текст программы таким образом, чтобы на экран дополнительно выводились номера максимального и минимального значения. 2. Модифицировать текст программы таким образом, чтобы максимальный элемент менялся бы местами с начальным элементомфайла, а минимальный – с последним. Байтовые величины, содержащие по 8 бит, имеют тип char. Зачастую требуется определить либо изменить отдельные биты внутри байта. Для этого необходимо использовать двоичную запись целого числа типа int, соответствующего байту. Переход от символьной кодировки к коду целого числа типа intосуществляется путем изменения их типа. Затем для перехода к двоичному представлению полученное число необходимо разложить по степеням числа 2.   Пример 7. Для байта ch, который находится на 8 месте в файле D:\\fсhar.datс символьной информацией,найти двоичные разряды в его двоичном представлении, занести их в массив d[8] и выдать на экран.Для поиска байта использовать указатель fseek. Решение.. #include "stdafx.h" #include <iostream> using namespace std; void main() { setlocale (LC_ALL, "RUS"); intn, i, ost, r; chara;  FILE *f; fopen_s(&f,"D:\\num.dat", "rb"); fseek(f,7*sizeof(char),SEEK_SET); fread(&a,sizeof(char),1,f); cout<<"char  a="<<a<<"\n"; n = (int) a; cout<<"int n="<<n<<"\n"; int d =new int[8]; for (i=0, i<8; i++){d[7-i]=(n mod 2);  n=n/2; cout<<" d["<<7-i<<"]=”<<d[7-i]<<”\n";}; fclose(f); system("pause"); }   Пример8.Логический  массивintd[8] содержит логические значения false(0) иtrue(1). Значения элементов массива инициализируются в программе.Требуется сформировать в файле D:\\fсhar.datбайт ch с номером 5, который в своих разрядах содержит данные логические значения. Например, для массиваd[8] = {1,0,1,1,0,0,1,0} должен быть сформирован байт ch с содержимым 101100102. Все предыдущие байты заполнить нулевыми значениями. Решение.. #include "stdafx.h" #include <iostream> using namespace std; void main() { setlocale (LC_ALL, "RUS"); intn, i, st, b; int d=new int[8]; d= {1,0,1,0,1,0,1,0}; char ch;  FILE *f; fopen_s(&f,"D:\\fсhar.dat", "wb"); for (i=0, i<5; i++) {// записьнулевых значенийвфайл fwrite(0, 1, 1, f); } st=1;b=0; for (i=0, i<8; i++) {// формирование 5-гобайтафайла        b+=d[7-i]*st; st*=2; }; Ch = (char) b; fwrite(ch, 1, 1, f); // запись5-го байтав файл fclose(f); system("pause"); }  

Задания для самостоятельного выполнения.

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

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

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

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

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

6. Ввести в байты массива сh размерности 15 циклически повторяющиеся двоичные слова вида 000001112,000011102, 000111002, 001110002, 011100002, 111000002. Сохранить массив chв исходном файле. Перевести двоичные числа в десятичный вид, прибавить к ним их номер в массиве, преобразовать опять к двоичному виду и записать в новый файл.Вывести содержимое исходного и итогового файлов на экран.

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

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

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

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

11. По двум заданным двоичным файлам создать новый двоичный файл, в котором на нечетных местах (1,3,5,…) стоят байты из первого файла, а на четных местах (2,4,6,…) – байты из второго файла.Вывести содержимое исходных и итогового файлов на экран.

12. Ввести в байты массива сh размерности 20 циклически повторяющиеся двоичные слова вида 010110102, 110011112, 111010012, 110000112. Записать массив в исходный двоичный файл. Инвертировать содержимое всех байтов и записать их в новый двоичный файл.Вывести содержимое исходного и итогового файлов на экран.

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


Дата добавления: 2018-08-06; просмотров: 254; Мы поможем в написании вашей работы!

Поделиться с друзьями:




Мы поможем в написании ваших работ!