- •8.Совместимость и преобразование типов. Явное и неявное преобразование.
- •10. Оператор присвоения. Комбинированные операторы присвоения. Математические и логические операции, операции сравнения . Ограничения на применения операторов(несовместимость типов).
- •11.Условная инструкция. Условный оператор. Пример.
- •12. Оператор множественного выбора. Пример. Управление оператором множественного выбора с помощью оператора break.
- •Вопрос 19. Регулярные структурированные типы. Одномерные массивы. Примеры работы с одномерными массивами (инвертирование массива относительно центрального элемента, относительно к-го элемента)
- •Вопрос 20. Регулярные структурированные типы. Одномерные массивы. Примеры работы с одномерными массивами (сложение векторов, скалярное произведение векторов, проверка на равенство)
- •Вопрос 22-24 Сортировка массивов. Методы сортировки (простого выбора, простой вставки, простого обмена). На примере массива структур.
- •Функции
- •39. Текстовые файлы
- •Функции вывода в стандартный и файловые потоки
- •Int printf([строка формата],
- •Функции ввода из стандартного и файловых потоков
- •Int scanf([строка формата],
- •Int fscanf(file*f,[строка формата],
- •40. Бинарные файлы с
- •41. Пользовательские типы данных
- •42. Модульная организация программы
Int scanf([строка формата],
[список адресов вводимых переменных]);
Читает из потока стандартного ввода данные в соответствии с форматом. Второй и последующие параметры должны хранит адреса ячеек памяти, в которые нужно поместить прочитанную информацию. Возвращает количество успешно прочитанных значений. В случае ошибки возвращает константу EOF. Обратите внимание, что если достигнут конец файла, функция scanf может в разных случаях вернуть как EOF, так и неотрицательное число. Если необходимо проверить, что все запрошенные параметры прочитаны, нужно сравнивать значение, которое вернула функция с количеством запрашиваемых параметров.
Int fscanf(file*f,[строка формата],
[список адресов переменных]);
Аналогично функции scanf , но чтение производится из файла f. Возвращает количество успешно прочитанных значений. В случае ошибки возвращает константу EOF.
}
Примеры работы с текстовыми файлами С++
Пример 1. Задан текстовый файл чисел. В новый файл переписать числа, превосходящие среднеарифметическое файла, по m чисел в строку.
#include <fstream>
using namespace std;
ifstream Fin;
ofstream Fout;
int main(){
int m,k=0;
double a, sum=0, sr;
Fin.open("number.txt");
if( Fin.fail()){
cout<<“не найден исходный файл";
return 1;}
Fout.open("best.txt");
if(Fout.fail()){
cout<<"\n не открыт файл результатов";
return 1;
}
while(Fin>>a)){
sum+=a;
k++;
}
sr=sum/k;
Fin.clear();
Fin.seekg(0);
k=0;
while(Fin>>a))
if(a>sr){
Fout<<a<<' ';
k++;
if( k%m==0)
Fout<<endl;
}
Fin.close();
Fout.close();
return 0;
40. Бинарные файлы с
Знакомство с вводом-выводом обычно начинается с текстовых файлов. Однако существует еще одна общая форма представления данных в файлах, на самом деле более многообразная – двоичный файл. Сюда относятся не только файлы с «мультимедийным» содержанием: документы, изображение, звук. Форматы двоичных файлов используются в базах данных и в самой файловой системе.
Модель двоичного файла. Двоичный файл отличается от текстового тем, что данные в нем представлены во внутреннем машинном формате. А поскольку при внутреннем представлении используется двоичная система счисления, то файлы и называются двоичными(бинарными). По существу, бинарный файл является аналогом внутренней (оперативной, физической) памяти – неограниченным массивом байтов с возможностью непосредственного обращения (произвольного доступа) к любой его части.
Такая модель файла полностью совпадает с системой представлений, принятой в С для работы с памятью на низком (физическом уровне):
D878G5A:0O ?0<OBL 8<55B 109B=CN AB@C:BC@C 548=8F59 04@5A0F88 O2;O5BAO 109B;
;N10O ?5@5<5==0O 70=8<05B D8:A8@>20==>5 :>;8G5AB2> 109B>2, >?@545;O5<>5 55 B8?><. ?5@0F8O sizeof возвращает эту размерность;
C:070B5;L =0 ?5@5<5==CN 8=B5@?@5B8@C5BAO :0: 55 04@5A 2 ?0<OB8. @5>1@07>20=85 B8?0 C:070B5;O : void* позволяет интерпретировать его как «чистый» адрес, а преобразование к char* – как указатель на массив байтов (физическое представление памяти).
Исходя из этих принципов, функции двоичного ввода-вывода fread и fwrite переносят содержимое памяти в двоичный файл без каких либо преобразований. Функции используются для перенесения данных из файла в память программы (чтение) и обратно (запись).
Функции для работы с ними
Функции бесформатного ввода-вывода.
Чтение из бинарного файла:
int fread(void *buf, int size, int nrec, FILE *f);
Запись в бинарный файл:
int fwrite (void *buf, int size, int nrec, FILE *f);
Особенностью этих функций является то, что для них безразличен (неизвестен) характер структуры данных в той области памяти, в которую осуществляется ввод-вывод (указатель void* buf). Функция fread читает, а функция fwrite пишет в файл, начиная с текущей позиции, массив из nrec элементов размерностью size байтов каждый, возвращая количество успешно прочитанных (записанных) элементов.
Чтобы воспользоваться этими функциями, необходимо обеспечить преобразования переменных к «массиву байтов», используя указатели для задания адресов и операцию sizeof для вычисления размерности. Например,
// Прочитать целую переменную и следующий за ней
// динамический массив из n переменных типа double
int n; // в целой переменной – размерность массива
fread(&n, sizeof(int),1,f);
// pd – указатель на динамический массив
double *pd = new double[n];
fread(pd, sizeof(double),n,f);// преобразование к
//void* - неявное.
При использовании исключительно функций fread и fwrite данные, записанные в определенной последовательности в файл, хранятся в нем и читаются в том же самом порядке. Этот неизменный порядок извлечения данных называется последовательным доступом, а файл – последовательным двоичным файлом. Естественно, что при этом не важны адреса размещения данных в файле. Однако существует и другой способ, позволяющий извлекать данные в любом порядке – прямой (или произвольный) доступ.
Замечание. Текущая позиция в файле является адресом размещения переменной в нем, но получить этот адрес можно до, а не после ее чтения оттуда.
Текущую позицию можно читать и устанавливать с помощью функций позиционирования, которые превращают последовательный файл в файл произвольного доступа.
Функция long ftell(FILE *f) возвращает текущую позицию в файле. Если по каким-то причинам текущая позиция не определена, функция возвращает −1.Это же самое значение будет использоваться в дальнейшем для представления недействительного значения файлового указателя (файловый NULL). Его можно самостоятельно определить, как
#define FNULL -1L
Функция int fseek(FILE *f, long pos, int mode) устанавливает текущую позицию в файле на байт с номером pos. Параметр mode определяет, относительно чего отсчитывается текущая позиция в файле, и имеет символические (константы) и числовые значения. Они заданы в stdio.h.
#define SEEK_SET 0 // Относительно начала файла, начало файла - позиция 0
#define SEEK_CUR 1 // Относительно текущей позиции(>0-вперед,<0-назад)
#define SEEK_END 2 // Относительно конца файла (значение pos –
// отрицательное)
Функция fseek возвращает значение 0 при успешном позиционировании и −1 (EOF) - при ошибке. Различные значения параметра mode определяют различные способы адресации данных в файле:
7=0G5=85 SEEK_SET определяет абсолютную адресацию данных в файле от его начала. Запомните, что функция ftell возвращает текущую позицию в абсолютном значении;
7=0G5=85 SEEK_END за начало координат берет конец файла (EOF). Адреса уже записанных данных имеют отрицательное значение. Например, если в конце файла находится целая переменная, то ее позиция при адресации от конца файла будет иметь значение 0–sizeof(int). В этом же режиме можно определить текущую длину файла можно простым позиционированием:
long fsize;
fseek(fl,0,SEEK_END);// установить текущую позицию
// на конец файла
fsize = ftell(fl); // узнать значение
// текущей позиции
7=0G5=85 SEEK_CUR дает способ относительной адресации от текущего положения указателя в файле. Таким образом, задается расстояние в байтах от текущей переменной до адресуемой. Если это расстояние само находится в файле, то оно обычно носит название смещения.
Замечание. Когда исследуется понятие произвольного доступа по адресу в файле, необходимо четко знать ответы на главные вопросы: откуда взять эти адреса и как размещаются данные в файле (распределяется память).
При открытии или создании нового файла необходимо указать режим работы с файлом как с двоичным. Среди множества режимов можно выделить два: создание нового файла для записи всех данных, либо начальной структуры данных и открытие существующего файла с уже имеющейся структурой данных для чтения, записи и добавления. Последний режим наиболее точно соответствует модели двоичного файла как неограниченно расширяемого прямо адресуемого массива байтов.
// Открыть существующий двоичный файл для чтения
FILE *f;
f = fopen("a.bin","rb");
// Создать новый как двоичный для записи
FILE *fd = fopen("NEW.bin","wb");
Примеры работы с бинарными файлами С
Пример 1. Дан бинарный файл массивов. Строка файла содержит размер массива n, а затем массив из n компонент. В новый бинарный файл перенести массивы, упорядоченные по возрастанию.
#include <stdio.h>
#include <conio.h>
FILE*Fin,*Fout;
// прототипы функций
// 1. Определение, является ли массив упорядоченным
bool best(int*w,int n);
// 2. Чтение массива из файла
bool input(int *w,int &n);
int main(){
int *a, n;
Fin=fopen("data.bin","rb");
if(!Fin){
printf("\n не найден исходный файл");
return 1;
}
Fout=fopen("sort.bin","wb");
if(!Fout){
printf("\n не открыт файл результатов");
return 1;
}
while(input(a,n)){
if(best(a,n)){
fwrite(&n,sizeof(int),1,Fout);
fwrite(a,sizeof(int),n,Fout);
}
delete []a;
}
fclose(Fin);
fclose(Fout);
return 0;
}
// описание функций
bool best(int*w,int n)){
int i;
for(i=0;i<n-1&&w[i]<w[i+1];i++);
return (i==n-1);
}
bool input(int *w,int &n){
fread(&n,sizeof(int),1,Fin);
int*w=new int [n];
fread(w,sizeof(int),n,Fin);
return !feof(Fin);}
