Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
общая-шпора 37-50.doc
Скачиваний:
17
Добавлен:
15.04.2015
Размер:
128.51 Кб
Скачать

Вопрос № 37

Организация работы с файлами

Язык Си, кроме стандартного ввода данных с клавиатуры и вывода результата на экран, предоставляет также возможность обмена при операциях ввода/вывода с внешними устройствами, в том числе с файлами на диске. В Си не предусмотрены никакие предопределенные структуры файлов (такие как последовательного или прямого доступа). Все файлы рассматриваются как последовательности, потоки байтов. Поток — это источник или приемник данных. Его можно связать с каким-либо внешним устройством, например, с принтером, клавиатурой, диском и т.д. В языке Си определены два вида потоков: текстовый и бинарный. Текстовый поток — это последовательность строк. Каждая строка содержит нуль и более символов и обязательно заканчивается символом-терминатором новая строка ‘\n’. Бинарный или двоичный поток — это последовательность двоичных кодов (байтов), как правило, используемая для запоминания кодов машинного языка. Поток соединяется с файлом или другим устройством посредством его открытия. Эта связь разрывается путем закрытия потока. Открытие потока осуществляется функцией fopen(), а закрытие — функцией fclose().

Когда программа начинает работу, то автоматически открывается три потока: stdin, stdout, stderr. stdin — стандартный входной поток (по умолчанию связан с клавиатурой). stdout — стандартный выходной поток (по умолчанию связан с экраном монитора). stderr — поток стандартных ошибок (связан с экраном монитора)

Открытие файла

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

FILE *fp;

где FILE — это структура, определенная в <stdio.h> с помощью средства typedef и содержащая некоторую информацию о файле.

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

fp=fopen(“имя_файла”,”режим_доступа”);

Константы в круглых скобках имеют следующий смысл:

имя_файла — это параметр, характеризующий имя и тип используемого файла на диске, например “test.txt”;

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

r — файл открывается для чтения

w — файл открывается для записи, если файла нет, то он создается, если есть, то его содержимое затирается.

a — файл открывается, либо создается для дозаписи в конец файла.

r+’ — открывается для чтения и записи (файл должен существовать)

w+’ — файл открывается для чтения и записи, старое содержимое, если файл существовал, теряется

a+’ — файл открывается, либо создается для чтения уже существующей информации и добавления новой в конец файла.

обычно по умолчанию файл считается текстовым, однао можно указать с каким файлом будет работать программа : текстовым (t) или бинарным (b).

Закрытие файла

fclose (имя_файла)

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

Операции ввода/вывода

Ввод-вывод отдельных символов. Эти операции осуществляются с помощью следующих функций:

1) getc() и fgetc() — ввод символа из файла

2) putc() и fputc() — вывод символа из файла

Ввод-вывод строк. Эти операции осуществляются с помощью следующих функций:

fgets() — ввод строки из файла

fputs() — вывод строки из файла

Вопрос №40

Упорядоченный массив B' получается из В следующим образом: сначала он состоит из единственного элемента К1; далее для i=2,...,N выполняется вставка узла Кi в B' так, что B' остается упорядоченным списком длины i.

Например, для начального списка B=< 20,-5,10,8,7 > имеем:

B=< 20,-5,10,8,7> B'=< >

B=< -5,10,8,7 > B'=< 20 >

B=< 10,8,7 > B'=< -5,20 >

B=< 8,7 > B'=< -5,10,20 >

B=< 7 > B'=< -5,8,10,20 >

B=< > B'=< -5,7,8,10,20 >

Функция insert реализует сортировку вставкой.

float *insert(float *s, int m, int n)

{

int i,j,k;

float aux;

for (i=m+1; i<=n; i++)

{ aux=s[i];

for (k=m; k<=i && s[k]=k; j--) s[j+1]=s[j];

s[k]=aux;

}

return(a);

}

Здесь оба списка В и В' размещаются в массиве s, причем список В занимает часть s c индексами от i до n, а B' - часть s c индексами от m до i-1

При сортировке вставкой требуется Q=(n-m)*(n-m) сравнений и не требуется дополнительной памяти.

Вопрос №38

Классы памяти и их описатели

Класс памяти определяет время жизни объекта. Под объектом понимается идентификатор переменной, функция либо указатель функции. Кроме этого, класс памяти в совокупности с местоположением переменной в программе, определяет область видимости переменной. Различают два вида объектов: глобальные и локальные. Объекты с глобальным временем жизни существуют и имеют значение на протяжении всего времени исполнения программы. Все функции и их указатели — глобальные объекты. Локальные объекты «захватывают» новую область памяти всякий раз, когда управление передается блоку, в котором они описаны. Если переменная описана вне всяких блоков, то она считается глобальной. Это описание на, так называемом, внешнем уровне. Блок — это описание функции, составная команда, либо часть программы, заключенная в фигурные скобки. Переменные, описанные внутри некоторого блока, являются локальными. При каждом входе в блок им выделяется новая область памяти, а при выходе из блока память освобождается и значение переменной, следовательно, теряется. локальные объекты видны с момента их описания до конца блока. Если при выходе из блока нужно сохранить значение переменной, то ее следует описать как статистическую в данном блоке. Глобальные объекты видны с момента их описания до конца файла всем функциям (блокам). Если имя локального объекта совпадает с именем глобального объекта, то локальный объект маскирует глобальный в этом блоке. Область действия меток — функция, в которой метка используется. Внешний уровень — уровень файла. Объект внешнего уровня виден везде в файле. Время его жизни — глобальное. На локальном уровне внешний объект может быть переопределен. Описатели классов памяти. Различают два класса объектов: глобальные и локальные, но используют четыре описателя классов: extern, static, auto и register. Автоматический, регистровый, статический описываются внутри функций. Внешний и внешний статический описываются вне функций. По умолчанию переменные, описанные внутри функции, являются автоматическими. Вне функции — глобальные. Класс памяти extern указывает, что глобальная переменная описана где то в другом месте. Таким образом, описатель extern позволяет только сослаться на описание, сделанное в другом месте. Для того чтобы описание extern было корректным, необходимо чтобы описание самой переменной существовало только один раз в любом из файлов, образующих текст программы. Если переменная внутри функции имеет класс памяти extern то она может быть описана только после этой функции. При неявной инициализации переменным присваивается нулевые значения. Класс памяти stativ на внешнем уровне маскирует описание переменных внутри файла, в котором они описаны. Другим файлам они не недоступны. Класс памяти register предполагает хранение переменной во внутреннем регистре процессора. Время жизни и область видимости регистровой переменной такая же, как и у автоматической. Если компилятор не может разместить эту переменную в регистре то она трактуется как автоматическая. По умолчанию значение регистровых переменных не определено.

Вопрос 41

Сортировка путем слияния

Для получения упорядоченного списка B' последовательность значений В=<K1,K2,...,Kn> разделяют на N списков В1=<K1>, B2=<K2>,...,Bn=<Kn>, длина каждого из которых 1. Затем осуществляется функция прохода, при которой М>=2 упорядоченных списков B1,B2,...,Bm заменяется на М/2 (или (М+1)/2) упорядоченных списков, B(2i-1)-oго и B(2i)-ого ( 2i<=M ) и добавлением Вm при нечетном М. Проход повторяется до тех пор пока не получится одна последовательность длины N.

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

Пример:

9 / 7 / 18 / 3 / 52 / 4 / 6 / 8 / 5 / 13 / 42 / 30 / 35 / 26;

7,9 / 3,18 / 4 / 52 / 6 / 8 / 54 / 13 / 30 / 42 / 26 / 35;

3,7,9,18 / 4,6,8,52 / 5,13,30,42 / 26,35;

3,4,6,7,8,9,18,52 / 5,13,26,30,35,42;

3,4,5,6,7,8,9,13,18,26,30,35,42,52.

Количество действий, требуемое для сортировки слиянием, равно Q=N*log2(N), так как за один проход выполняется N сравнений, а всего необходимо осуществить log2(N) проходов. Сортировка слиянием является очень эффективной и часто применяется для больших N, даже при использовании внешней памяти.

Функция smerge упорядочивает массив s сортировкой слиянием, используя описанную ранее функцию merge.

/* сортировка слиянием */

double *smerge (double *s, int m, int n)

{ int l,low,up;

double *merge (double *, int, int, int);

l=1;

while(l<=(n-m))

{ low=m;

up=m-1;

while (l+up < n)

{ up=(low+2*l-1 < n) ? (low+2*l-1) : n ;

merge (s,low,up,l);

low=up-1; }

l*=2; }

return(a); }

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

/* рекурсивная сортировка слиянием 1/2 */

double *srecmg (double *a, int m, int n)

{ double * merge (double *, int, int, int);

double * smerge (double *, int, int);

int i;

if (n>m)

{ i=(n+m)/2;

srecmg(a,m,i);

srecmg(a,i+1,n);

merge(a,m,n,(n-m)/2+1);

}

return (a); }

Вопрос 39 Пузырьковым методом

Задача сортировки заключается в следующем: задан список целых чисел (простейший случай) В=< K1, K2,..., Kn >. Требуется переставить элементы списка В так, чтобы получить упорядоченный список B'=< K'1, K'2,...,K'n >, в котором для любого 1<=i<=n элемент K'(i) <= K'(i+1).При обменной сортировке упорядоченный список В' получается из В систематическим обменом пары рядом стоящих элементов, не отвечающих требуемому порядку, пока такие пары существуют. Наиболее простой метод систематического обмена соседних элементов с неправильным порядком при просмотре всего списка слева на право определяет пузырьковую сортировку: максимальные элементы как бы всплывают в конце списка. Пример:

B=<20,-5,10,8,7>, исходный список;

B1=<-5,10,8,7,20>, первый просмотр;

B2=<-5,8,7,10,20>, второй просмотр;

B3=<-5,7,8,10,20>, третий просмотр.

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

#include <stdio.h>

#include <conio.h>

#define SZ 5

void main()

{

int a[SZ];

int i; // счетчик циклов

dint к; // текущий индекс элемента массива

int buf;

printf("\пСортировка массива методом \"пузырька\"\п");

printf("Введите массив (в одной строке %i ", SZ);

printf("целых чисел) и нажмите <Enter>\n");

for (к = 0; к < SZ; k+-f)

scanf("%i", &а[к]);

printf("Сортировка...\п");

for (i = 0; i < SZ-1; i++)

(

for (k = 0; к < SZ-1; k++)

{

if (a[k] > a[k+l])

{

// обменяем к-й и {к+1)-й элементы

buf = а[к];

а[к] = а[к+1];

а[к+1] = buf;

}

}

}

printf("Массив отсортированХп");

for (к = 0 ; к < SZ; к++)

printf("%i ",а[к]);

printf("\п\пДля завершения работы нажмите <Enter>");

getch();

}

Пузырьковая сортировка выполняется при количестве действий Q=(n-m)*(n-m) и не требует дополнительной памяти.

Вопрос № 45

Управление цветом

Современная техника позволяет выводить текст в цвете. Можно определить как цвет текста, так и цвет фона. Однако использовать цвет могут только специальные функции, связанные с оконным интерфейсом. Такие функции как printf() для этого не предназначены.

Для изменения цвета текста предназначена функция textcolor(). ее прототип

void textcolor (int color);

аргумент color может принимать значения от 0 до 15. Каждому значению соответствует свой цвет. (Число может быть заменено соответствующим макросом). Кроме того, textcolor() позволяет делать цвет мигающим (blink). Код этого аргумента — 128. Для того, чтобы сделать цвет мигающим надо применить побитовую операцию «OR» к цвету и величине BLINK. Например, для вывода текста красным мигающим цветом надо применить функцию

textcolor(RED||BLINK);

Изменение цвета текста оказывает действие только на вновь выводимый текст и не оказывает никакого действия на ранее введенный текст. Для установки цвета фона используется функция

void textbackground (int color);

Здесь аргумент color имеет те же значения что и в функции textcolor(). Функция clrscr() не только очищает активное окно, но и заполняет его цветом заданном в функции background().