Mk_fp создать дальний указатель


Содержание

Создание указателя данного адреса «сегмент:смещение»

Как создать дальний указатель на конкретный адрес памяти

(конкретный адрес «сегмент:смещение»)? Для этого можно воспользоваться встроенной библиотечной подпрограммой MK_FP, которая в качестве аргумента воспринимает сегмент и смещение, и возвращает дальний указатель. Например:

Имея дальний указатель fp, вы можете получить значение сегмента полного адреса с помощью FP_SEG(fp) и значение смещения с

помощью FP_OFF(fp). Более полную информацию об этих трех библиотечных функциях Borland C++ можно найти в справочнике по библиотеке.

Разновидности указателей в С ++. Замечания о работе менеджера кучи в С++. Ссылки, структуры и объединения

Страницы работы

Содержание работы

Разновидности указателей в С ++

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

Указатели подразделяются на четыре вида:

При определении указателя модификатор размещается непосредственно перед * и относится только к одному указателю.

Ближний указатель

тип near * указатель [инициализатор]

Имеют внутреннее представление 2 байта и позволяют адресовать объекты в пределах сегмента.

Дальний указатель

тип far * имя_указателя [инициализатор];

Занимает 4 байта и содержит сегментную часть и смещение. Для формирования значения дальнего указателя в модуле dos имеется макрос MK_FP.

void far * MK_FP (unsigned segment, unsigned offset)

Один и тот же физический адрес в виде сегмента и смещения можно задать по-разному.

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

При сравнении дальних указателей на >, >=,

#include «имя пользовательского файла»

Функции с переменным числом параметров

Функции с переменным количеством параметров – это функции, у которых тип и количество параметров в момент компиляции могут быть не определены. Они становятся известными только в точках вызова функции, когда явно задается список фактических параметров. Прототип функции с переменным количеством параметров:

тип имя_функции (спецификация_явных_параметров,…);

Чтобы определить, где заканчивается список необязательных параметров, можно:

Вывод текстовых символов путем непосредственного обращения к видеопамяти

Помогите пожалуйста срочно выполнить упражнения!
Заранее благодарен.
C.rar

Ниже приведен пример программы, которая выполняет очистку экрана и вывод текстовых символов путем непосредственного обращения к видеопамяти:

Функция OutChar имеет следующие параметры:
x и y – координаты символа;
CharCode – код символа;
Color – цвет символа и фона.

Требуется выполнить следующую последовательность действий:
1) Ввести, откомпилировать и запустить программу.
2) Изменить программу таким образом, чтобы вместо очистки экрана выполнялась раскраска фона в виде шахматной доски с коричневыми и желтыми клетками (использовать по два знакоместа на каждую клетку, чтобы клетки были квадратными).
3) Вывести «бегущий ноль». При запуске в левом верхнем углу экрана выводится символ ‘0’. Далее при каждом нажатии на клавишу Enter символ должен перемещаться в следующую колонку, а при достижении конца строки – в следующую строку. Работа программы должна прекращаться по достижении конца третьей строки.

Ниже приведен пример программы, которая работает в графическом режиме с разрешением 320200 точек. В программе используются следующие функции: SetMode – установка видеорежима; ClearScreen – очистка экрана; Pixel – вывод точки заданного цвета в указанную позицию экрана.
Функция установки видеорежима SetMode имеет один параметр – код режима. Для установки 256-цветного режима с разрешением 320200 точек используется код 0x13, для возврата в текстовый режим – код 0x03.
Функция вывода точки Pixel имеет следующие параметры:
x и y – координаты точки;
Color – цвет точки.

Требуется выполнить следующую последовательность действий:
1) Ввести, откомпилировать и запустить программу.
2) Добавить в программу функцию, рисующую горизонтальные отрезки заданного цвета с заданной координатой Y от левого до правого края экрана.
3) Добавить в программу функцию, рисующую вертикальные отрезки заданного цвета с заданной координатой X от верхнего края экрана до нижнего..
4) С помощью добавленных функций разлиновать экран линиями светло-серого цвета таким образом, чтобы получились клетки 88 точек
5) Создать маску изображения в виде массива 88 типа unsigned char.
6) Организовать цикл вывода изображения таким образом, чтобы оно перемещалось от левого края экрана до правого с шагом в одну точку при каждом нажатии клавиши Enter.
7) Добавить массив 88 типа unsigned char для хранения фона и усовершенствовать цикл вывода изображения, чтобы фон восстанавливался после перемещения изображения.
8) Добавить в программу функцию синхронизации вывода изображения с частотой кадров WaitSync.Изменить цикл вывода изображения так, чтобы изображение перемещалось не по нажатию Enter, а по началу обратного хода луча.
9) Изменить программу таким образом, чтобы слева направо перемещался не один, а несколько одинаковых объектов – строем (цепью).

Ниже приведен пример программы, которая работает в режиме TrueColor32 1024768.

В программе используются следующие функции: SetTrueColorMode – установка графического режима, SetTextMode – восстановление текстового режима, SetPage – установка заданного окна видеопамяти, FillScreen – заливка экрана заданным цветом.
Параметры обозначены следующим образом:
• Page – номер окна видеопамяти;
• B – яркость по синей цветовой компоненте;
• G – яркость по зеленой компоненте;
• R – яркость по красной компоненте.

Требуется выполнить следующую последовательность действий:
1) Ввести, откомпилировать и запустить программу.
2) Добавить в программу функцию, рисующую горизонтальные отрезки заданного цвета с заданной координатой Y от левого до правого края экрана, а также функцию, рисующую вертикальные отрезки заданного цвета с заданной координатой X от верхнего края экрана до нижнего. С помощью добавленных функций разлиновать экран линиями белого цвета, чтобы получить клетки 3232.
3) Добавить описатель структуры заголовка файла BMP. В главном модуле отрыть для чтения двоичный файл rgb1.bmp. Прочитать из файла заголовок.
4) Добавить в программу массив из 4096 элементов типа unsigned char для промежуточного хранения строки изображения. Используя информацию о ширине и высоте изображения, построчно читать и выводить на экран данные из файла.
5) Добавить указатель для работы с видеопамятью как c массивом типа unsigned long, чтобы можно было передавать точку изображения за одну операцию.
6) Добавить функцию, переворачивающую изображение слева направо. Перевернуть изображение, ожидать нажатия любой клавиши, вернуть изображение в исходное состояние, ожидать нажатия клавиши.
7) Добавить функцию, переворачивающую изображение сверху вниз. Перевернуть изображение, ожидать нажатия клавиши, вернуть в исходное состояние, ожидать нажатия клавиши.
8) Добавить функцию, преобразующую изображение в черно-белое (с 256 градациями яркости).
9) Изменить программу таким образом, чтобы имя файла передавалось из командной строки через параметры функции main().

Не удается записать на экранную память в C

Я очень новичок в C, это мой второй язык программирования высокого уровня после Java. Я потерял большинство основ, но по какой-то причине я не могу написать один символ для отображения памяти.

Эта программа скомпилирована с использованием Turbo C для DOS на Am486-DX4-100 с частотой 120 МГц. Графическая карта является стандартным VLB Diamond Multimedia Stealth SE с использованием микросхемы Trio32.

Для ОС я запускаю PC-DOS 2000 с загруженной кодовой страницей ISO. Я работаю в стандартном режиме текстового текста в формате MDA/CGA/EGA/VGA 80 с цветом.

Вот программа, как я ее написал:

Как я уже сказал, я очень новичок в C, поэтому я извиняюсь, если моя ошибка кажется очевидной, я не смог найти надежный источник, как это сделать, что я мог понять.

Насколько я знаю, в реальном режиме на платформе x86 экранная память для текстового режима начинается с 0xB8000. Каждый символ хранится в двух байтах, один для символа и один для фона/переднего плана. Идея состоит в том, чтобы написать значение 0x0402 (которое должно быть красным улыбающимся лицом) до 0xB8000. Это должно поместить его в верхнем левом углу экрана.

Я принял во внимание возможность прокрутки экрана и, таким образом, сразу же удалив моего персонажа при выполнении двумя способами. Чтобы решить эту проблему, я попытался:

  • Повторно записывайте это значение с помощью цикла
  • Напиши немного дальше.

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

Физическое представление указателей near, far, huge

Указатель типа near задает неполный физический адрес, а только смещение (offset). Сегментная часть адреса определяется текущим значением регистра.

Указатель типа far задает полный физический адрес и при хранении в памяти занимает 4 байта. В памяти сначала располагается смещение адреса (2 байта) затем сегмент адреса.

Синтаксис обоих указателей следующий:

Тип _ near * имя _ переменный

Тип _ _ far * имя _ переменный

Int far * my _ ptr = 0x0000041A

Задает адрес 0000:041А, который находится в ячейке памяти, которая адресуется указателем my _ ptr

Заголовочный файл определяет три макроопределения (макрос) работы с указателями


FP _ OFF (void far * p),

Макрос возвращает смещение указателя Р

FP _ SEG (void far * p),

Макрос возвращает сегмент указателя Р

MK _ FP (unsigned seg, unsigned off)

Макрос возвращает длинный указатель, составленный из сегмента seg и смещения off, определенных в качестве параметров. А функция

* MK _ FP (unsigned seg, unsigned off)

возвратит содержимое адреса, на который указывает данный указатель.

Указатель типа huge аналогичен far – указателю, у которого смещение не превышает 15 (OXOF) байт.

Указатель может обозначаться в виде знака амперсанда &. Например

означает, что Р указывает адрес, по которому размещается значение переменной а.

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

Где x, y параметры.

Тогда сама функция имеет вид:

Int pixlit (* x, *y) <…>,

Где х, у описаны уже как указатели. Прототип этой функции будет:

int pixlit (* x, *y)

Доступ к регистрам и флагам.

Доступ к регистрам и флагам в языке Си осуществляется через псевдопеременные. Их имена имеют вид: _AX, _AL, _ AH, _BX, _BL, _BH, _CX, _CL, _CH, _DX, _DL, _DH, _SI, _DI, _BP, _SP, _CS, _ES, _DS, _SS.

Для этого, например, чтобы узнать состояние регистра АХ необходимо ввести переменную, например sost _ reg, описать ее

int unsigned sost _reg

и выполнить оператор присваивания

sost _ reg = _AX

В регистр через псевдопеременную можно поместить также и определенное значения. Например, полагая

Можно осуществить следующий оператор присваивания

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Учись учиться, не учась! 10384 — | 7887 — или читать все.

188.64.174.135 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.

Отключите adBlock!
и обновите страницу (F5)

очень нужно

46019 (Turbo C++ Programer`s gu >

Описание файла

Документ из архива «Turbo C++ Programer`s guide», который расположен в категории «рефераты». Всё это находится в предмете «информатика, программирование» из раздела «Студенческие работы», которые можно найти в файловом архиве Студент. Не смотря на прямую связь этого архива с Студент, его также можно найти и в других разделах. Архив можно найти в разделе «рефераты, доклады и презентации», в предмете «информатика, программирование» в общих файлах.

Онлайн просмотр документа «46019»

Текст 29 страницы из документа «46019»

| \! дальняя| \! До конца

Рис.4.4 Сегментация для модели памяти small

Сегментные регистры: Размер сегмента:

адрес | \! _TEXT класс ‘CODE’\! до 64К

| \! sfileкод \!каждый sfile

| / \! / _DATA класс ‘DATA’ \!\

| Несколько __|__\!_/инициализирован. данные\! |

| \!sfile A\! | \! _BSS класс ‘BSS’ \! |

| \! дальняя| \! До конца

Рис.4.5 Сегментация для модели памяти medium

CS указывает одновременно только на один sfile.

Сегментные регистры: Размер сегмента:

| / \! _DATA класс ‘DATA’ \!\

Рис.4.6 Сегментация для модели памяти compact

| / \! _DATA класс ‘DATA’ \!\

Рис.4.7 Сегментация для модели памяти large

Рис.4.8 Сегментация для модели памяти huge

Таблица 4.1. суммирует различные модели, а также результаты их сравнения друг с другом. Эти модели часто группируются в соответствии с тем, насколько малы (64К) или велики (1М) размеры их модулей кода и данных; Эти группы соответствуют рядами колонкам табл. 4.1.

Размер \! Размер кода

\! максимальный размер 64К) \!

\! Small (без перекрытия \! Medium (данные — small


\! максимальный размер 128К) \! коды — large)

1Mb\! Compact ( данные — large \! Large ( данные и коды \! коды — small) \! large)

\! \! Huge (также как и large,

Когда Выкомпилируете модуль (исходный файл с некоторым количеством процедур в нем), то результирующий код для этого модуля не может превышать 64К, т.к. он должен вмещаться в один кодовый сегмент. Это остается правилом, даже если Вы используете один из больших кодовых модулей (medium, large, huge). Если ваши модули очень велики ( > 64К ), Вы должны разбить их на несколько маленьких исходных файлов, компилировать их раздельно, а потом собирать в один файл. Аналогичным образом, несмотря на то, что huge модель позволяет набору статических данных превышать размер 64 К, все равно он должен быть . 24 25 26 27 28 29 30 31 32 33 . 46

Некоторые запутанные проблемы в движении задним ходом с МАР о Gs сегменте

После того, как я использовал IDA Pro, чтобы разобрать ELF и я нашел некоторый код, как

*mk_fp(\__gs__,12) или *mk_fp(\__gs__,8) и так далее.

Что это значит? Это что-то значит о системных вызовах или вызовах функций?

Большое спасибо за некоторую помощь

Создан 28 сен. 13 2013-09-28 03:15:18 user2579274

1 ответ

Я предполагаю, что mk_fp означает сделать дальний указатель как таковые они могут быть идея МАР декомпиляции gs:[12] и gs:[8] соответственно.

В 64-битовом ядре gs сегмент используется для хранения данных ядра процессора. В 32-битном пользовательском режиме он обычно используется для локального хранилища потоков.

Создан 28 сен. 13 2013-09-28 12:41:45 Jester

Адрес inTLS фиксированный или нет? – user2579274 29 сен. 13 2013-09-29 06:32:40

Адрес TLS не фиксирован, каждый поток имеет свои собственные, конечно. Смещения внутри TLS одинаковы, поэтому каждый поток может получить доступ к своему набору значений. Определенная реализация (например, ‘libc’) определяет макет. – Jester 29 сен. 13 2013-09-29 12:19:10

Замените прерывание HW в режиме плоской памяти с помощью DOS32/A

У меня вопрос о том, как заменить прерывание HW в режиме плоской памяти .

  1. about my application.
    • created by combining Watcom C and DOS32/A.
    • written for running on DOS mode( not on OS mode )
    • with DOS32/A now I can access >1M memory and allocate large memory to use. (running in flat memory mode . )
  2. current issue.
    • I want to write an ISR(interrupt service routine) for one PCI card. Thus I need to «replace» the HW interrupt.
    • Ex. the PCI card’s interrupt line = 0xE in DOS. That means this device will issue interrupt via 8259’s IRQ 14.

Но я не смог достичь своей цели: заменить это прерывание в плоском режиме?

@ resource I found. — in watcom C’s library, there is one sample using _dos_getvect, _dos_setvect, and _chain_intr to hook INT 0x1C. I tested this code and found OK. But when I apply it to my case: INT76 ( where IRQ 14 is «INT 0x76» 8: 1544 (INT9), . 8: 1560 (INT70), 8: 1564 (INT71), .. ., 8: 157C (INT77)

Ex. Используйте DPMI 0x205 , чтобы установить вектор прерывания для IRQ14 (INT76) и возвратить CF = 0, указав успешную

2) Create my own ISR MyISR() as follows:

3) Set new interrupt vector by DPMI call 0x205:

Тогда sts = 0 (CF = 0), указывающий на успешность!

  • Одна странная вещь: мое приложение работает в модели с плоской памятью , и я думаю, что селектор должен быть 0 для MyISR() . Но если selector = 0 для вызова DPMI 0x205, то я получил CF = 1 и AX = 0x8022 с указанием «неверный селектор»!

4) Let HW interrupt be generated and the evidences are:

  • Регистр конфигурации устройства PCI 0x5 бит2 (Прерывание отключено) = 0
  • Регистр конфигурации устройства PCI 0x6 бит3 (состояние прерывания) = 1
  • Регистр конфигурации устройства PCI 0x3C/0x3D (строка прерывания) = 0xE/0x2
  • В DOS режим прерывания — режим PIC (режим 8259) и основанный на контактах (MSIE = 0)

5) Display the value of tick and found it is still «0».

Таким образом, я думаю, что MyISR() не вызывается правильно .

Turbo C++ Programer`s gu >
  • 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
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160

for (i = 0; s[i] != 0; i++) putc(s[i]);

char near *mystr;

mystr = «Hello, world\n»;

Эта программа работаетудовлетворительно, хотя объявление mystr как near избыточно, поскольку все указатели, как кода, так и данных, будут near по умолчанию.

Однако, что произойдет, если перекомпилировать эту программу с моделью памяти compact (либо large или huge)? Указатель mystr в main останется ближним (16-битовым). Однако, указатель s в myputs теперь будет far, поскольку умолчанием теперь будет являться far. Это означает, что попытка создания дальнего указателяприведет к снятию со стека двух слов, и полученный таким образом адрес, безусловно, не будет являться адресом mystr.

Как избежать этой проблемы? Решение состоит втом, чтобы определить myputs в современном стиле С:

void myputs(char *s)

Теперь при компиляции вашей программы Turbo C++ знает, что myputs ожидает указатель на char; и поскольку компиляция выполняется с моделью large, то известно, что указатель должен быть far. Вследствие этого Turbo C++ поместит в стек регистр сегмента данных (DS) и 16-битовоезначение mystr, образуя тем самым дальний указатель.

Если вы собираетесь явнообъявлять указатели как farили near,не забывайте использовать прототипы тех функций, которые могут использовать эти указатели.

Как быть в обратном случае: когда аргументы myputs объявлены как far, а компиляция выполняется с моделью памяти small? И в этом случае без прототипа функции у вас возникнут проблемы, поскольку main будет помещать в стек и смещение, и адрес сегмента, тогда как myputs будет ожидать приема только одного смещения. При наличии определений функций в прототипах main будет помещать в стек только смещение.

Создание указателя данного адреса сегмент:смещение

Как создать дальний указательна конкретный адрес памяти (конкретный адрессегмент:смещение)? Для этого можно воспользоваться встроеннойбиблиотечной подпрограммой MK_FP, которая в качестве аргументапринимает сегмент и смещение, и возвращает дальний указатель. Например,

Имея дальний указательfp, вы можете получить компонент сегмента полного адреса с помощью FP_SEG(fp) и компонент смещения с помощью FP_OFF(fp). Более полную информацию об этих трех библиотечных функциях Turbo C++ см. в Справочнике по библиотеке.

Использование библиотечных файлов

Turbo C++ предлягает для каждой из шести моделей памяти собственную версию библиотеки стандартных подпрограмм. Turbo C++ при этом проявляет достаточно «интеллекта», чтобы при компоновке брать нужные библиотеки и в нужной последовательности, в зависимости от выбранной вами модели памяти. Однако,при непосредственном использовании компоновщика Turbo C++ TLINK (как автономного компоновщика) вы должны явно указывать используемые библиотеки. Более подробно это описано в разделе TLINK Главы 5Б «Утилиты», Руководства пользователя.

Компоновка смешанных модулей

Что произойдет,если вы компилируете один модуль с использованием модели памяти small, второй — модели large, и затем хотите скомпоновать их? Что при этом произойдет?

Файлы скомпонуются удовлетворительно, но при этом вы встретитесь с проблемами, которые будут аналогичны с описанными выше в разделе «Объявление функций как near или far». Если функция модуля с моделью small вызывает функцию в модуле с моделью large, она будет использовать при этом ближний вызов, что даст абсолютно неверные результаты.Кроме того, у вас возникнут проблемы с указателями, описанные в разделе «Объявление указателей как near, far или huge», поскольку функция в модуле small ожидает, что принимаемые и передаваемые ейуказатели будут near, тогдакак функция в модуле large ожидает рабрту с указателями far.

И снова решение заключается в использовании прототипов функций. Предположим, что вы поместили myputs в отдельный модуль и скомпилировали его с моделью памяти large. Затем вы создаете файл заголовка myputs.h (либо с любым другим именем и расширением .h), который содержит следующий прототип функции:

void far myputs(char far *s);

Теперь, если поместить main в отдельный модуль (MYMAIN.

«МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ Московский государственный институт электроники и . »


МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ

РОССИЙСКОЙ ФЕДЕРАЦИИ

ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ

Московский государственный институт электроники и математики

Кафедра Управления и информатики

в технических системах

ИНФОРМАТИКА

к лабораторным работам Москва 2009 г.

Составитель ст. преп. В.Г. Кулаков УДК .

Информатика. Метод, указания к лабораторным работам / Моск. гос. ин-т электроники и математики; Сост. В.Г. Кулаков. М., 2009, 27 с.

Табл. 2. Ил. 5. Библиогр.:8 назв.

Методические указания к лабораторным работам по дисциплине «Информатика» предназначены для студентов первого курса дневного отделения. Основной целью лабораторных работ является освоение студентами правил элементарного программирования на языке Си.

Методические указания составлены в соответствии с программой и планом для специальности «Управление и информатика в технических системах» — 210100.

1. Лабораторная работа №1. Знакомство с интегрированной средой Borland C++ 4

1.1. Цель лабораторной работы 4

1.2. Основы работы в IDE 4

1.3. Окна системы Borland C++ 4

1.4. Горячие клавиши 5

1.5. Упражнения 6

2. Лабораторная работа №2. Использование указателей при работе с видеопамятью 8

2.1. Цель лабораторной работы 8

2.2. Организация памяти IBM PC 8

2.3. Видеоконтроллер VGA 9

2.4. Вывод спрайтов на экран монитора 12

2.5. Упражнения 12

3. Лабораторная работа №3. Работа с файлами и каталогами 15

3.1. Цель лабораторной работы 15

3.2. Функции для работы с дисками и каталогами 15

3.3. Поиск файлов 16

3.4. Функции общего назначения для работы с файлами 17

3.5. Функции для работы с текстовыми файлами 17

3.6. Функции для работы с двоичными файлами 18

1.1. Цель лабораторной работы Целью работы является освоение интегрированной среды Borland C++.

В настоящее время язык Си считается устаревшим и используется только в учебном процессе – для освоения основ программирования на алгоритмических языках, поэтому на персональных компьютерах для трансляции Си-программ используются компиляторы с языка C++

– усовершенствованной версии Си.

На территории России в настоящее время наиболее распространены C++ компиляторы Microsoft (Visual C++ и Visual Studio) и Borland (Turbo C, Turbo C++ и Borland C++). И Microsoft, и Borland предоставляют возможность бесплатной закачки учебных версий компиляторов через Интернет, однако возможности таких компиляторов сильно ограничены.

Фирма Borland предоставляет две бесплатные версии Си-компилятора, предназначенные для работы в среде MS DOS – Turbo C 2.01 и Turbo C++ 1.01. Это полноценные версии компиляторов, снабженные интегрированной средой разработки (включая подсказку и отладчик), но запуск компиляторов возможен только в среде MS DOS или в режиме эмуляции DOS под управлением Windows.

1.2. Основы работы в IDE В интегрированной среде разработки (IDE) системы Borland C++ имеется все необходимое для написания, редактирования, компиляции, компоновки и отладки программ пользователя.

Для запуска IDE после приглашения DOS наберите BC. За этой командой могут следовать один или несколько параметров командной строки (обычно в качестве параметра задают имя исходного файла, который надлежит открыть в окне редактирования).

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

Строка меню представляет собой основное средство доступа ко всем командам меню. Для доступа к меню обычно используется мышь, однако можно также перейти в строку меню, нажав клавишу F10.

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

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

Для отмены некоторого действия используют клавишу Esc.

Для того, чтобы выйти из среды IDE, выберите команду Quit в меню File или нажмите комбинацию клавиш Alt-X. Если вы внесли в тексты программ какие-либо изменения, которые еще не были сохранены, то среда выдаст сообщение, в котором спрашивается, хотите ли вы сохранить перед выходом из системы ваши программы.

1.3. Окна системы Borland C++ Большая часть того, что вы видите и делаете в IDE, происходит в окне. Окно представляет собой область экрана, которую можно открывать, закрывать, перемещать, у которой можно изменять размеры, которую можно распахивать на весь экран и перекрывать с другими окнами.

В IDE может быть открыто много окон, но в каждый момент времени активным может быть только одно окно. Активным окном является то окно, в котором вы в настоящий момент работаете. Любые выбираемые вами команды или вводимый вами текст, как правило, относится только к активному окну.

Маркер закрытия окна представляет собой прямоугольник, который расположен в левом верхнем углу окна. Для закрытия окна необходимо подвести к нему указатель мыши и щелкнуть кнопкой мыши. Можно также выбрать команду Close в меню Window или нажать комбинацию клавиш Alt-F3.

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

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

В правом верхнем углу первых девяти окон, которые вы открываете в системе Borland C++, имеется номер окна. Какое-либо окно можно сделать активным нажатием клавиши Alt в комбинации с номером окна.

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

1.4. Горячие клавиши Для выполнения часто используемых операции используются так называемые горячие клавиши и комбинации клавиш.

Клавиши общего назначения:

F1 – вызвать подсказку;

F2 – сохранить файл;


F3 – открыть файл;

F4 – выполнить программу до строки, на которой установлен курсор;

F5 – развернуть/свернуть активное окно;

F6 – перейти к следующему окну;

F7 – выполнение программы в режиме отладки с трассировкой;

F8 – выполнение программы в режиме отладки;

F9 – откомпилировать программу и создать исполняемый файл;

F10 – перейти в меню.

Клавиши активации меню:

Alt+пробел – системное меню;

Alt+C – меню компиляции;

Alt+D – меню отладки;

Alt+E – меню редактирования;

Alt+F – меню операций с файлами;

Alt+H – меню подсказки;

Alt+O – меню настроек;

Alt+P – меню проекта;

Alt+R – меню запуска;

Alt+S – меню поиска;

Alt+W – меню выбора окна;

Alt+X – выход из системы.

Клавиши режима редактирования:

Ctrl+Del – удалить выделенный текст;

Ctrl+Ins – скопировать выделенный текст в буфер;

Shift+Del – скопировать выделенный текст в буфер и удалить его;

Shift+Ins – вставить текст из буфера в файл;

Аlt+Bksрc – возвращает текст в предыдущее состояние.

Клавиши управления окнами:

Alt+F3 – закрыть активное окно;

Alt+F4 – открыть окно проверки;

Alt+F5 – отобразить экран пользователя.

Клавиши активации режима подсказки:

F1 – выдать инструкцию по использованию подсказки;

Shift+F1 – вызвать тематический указатель по системе подсказки.

Ctrl+F1 – вызывать контекстную подсказку.

Клавиши режима выполнения и отладки:

Alt+F4 – открыть окно проверки;

Alt+F7 – возврат к предыдущей ошибке;

Alt+F8 – перейти к следующей ошибке;

Alt+F9 – создать объектный файл (компиляция без компоновки);

Ctrl+F2 – реинициализация выполняющейся программы;

Ctrl+F3 – вывести на экран окно со стеком вызовов функций;

Ctrl+F4 – вычислить выражение;

Ctrl+F7 – добавить просматриваемое выражение;

Ctrl+F8 – установить или отменить точку останова;

Ctrl+F9 – выполнить программу.

Блоком называют произвольный фрагмент текста размером от одного символа до сотен строк текста, который выделен на экране специальным образом. В каждый момент времени в окне может существовать только один блок текста. Блок маркируется с помощью мыши или путем перемещения маркера от начала блока до его конца при нажатой клавише Shift. Будучи помеченным, блок может быть скопирован, перемещен, удален, отпечатан или записан в файл.

Команды работы с блоками начинаются с комбинации Ctrl+K, после чего следует нажать клавишу с определенным символом:

B – начало отметки блока;

K – конец отметки блока;

Y – удалить блок;

C – скопировать блок;

V – переместить блок.

Упражнение 1. Требуется выполнить следующую последовательность действий:

Запустить интегрированную среду Borland C++, набрав в командной строке команду BC.

Набрать в окне редактирования следующий текст:

> Записать программу на диск в файл с именам HELLO.C, нажав клавишу F2.


3) Установить курсор на функцию printf и вызвать контекстную подсказку, путем нажатия 4) комбинации клавиш Ctrl+F1.

Закрыть окно подсказки путем нажатия комбинации клавиш Alt+F3.

5) Скомпилировать программу, нажав клавишу F9. Если программа набрана правильно, в окне 6) результатов компиляции будет указано, что количество ошибок (ERRORS) и предупреждений (MESSAGES) равно нулю. В том случае, если в процессе набора были допущены ошибки, появится окно сообщений об ошибках. Если выбрать в окне какое-либо сообщение и нажать клавишу Enter, в окне редактирования строка программы, содержащая ошибку, будет выделена красным цветом.

После устранения всех обнаруженных ошибок запустить программу на выполнение путем 7) нажатия комбинации клавиш Ctrl+F9.

Просмотреть результат работы программы, для чего требуется перейти на пользовательский 8) экран путем нажатия комбинации клавиш Alt+F5.

Вернуться из пользовательского окна в окно редактирования можно путем нажатия любой 9) произвольной клавиши.

Выйти из интегрированной среды путем нажатия комбинации клавиш Alt+X.

Упражнение 2. Требуется выполнить следующую последовательность действий:

Запустить интегрированную среду.

Набрать в окне редактирования следующий текст:

2) #include conio.h #include ctype.h void main() < int c;

while ((c = getch()) != ’0’) putch(isupper(c) ? tolower(c) : c);

> Записать программу на диск в файл с именам LOWER.C.

3) Скомпилировать программу.

4) После устранения всех обнаруженных ошибок запустить программу на выполнение.

5) Ввести в пользовательском окне любую произвольную последовательность символов, 6) наблюдая за результатом преобразования. Ввод завершить нажатием цифры 0.

Выйти из интегрированной среды путем нажатия комбинации клавиш Alt+X.

7) Упражнение 3. Составить, скомпилировать и запустить на выполнение программу, которая запрашивает у пользователя ввод целого числа N, а затем выводит на экран квадраты целых чисел от 1 до N.

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

Упражнение 5. Транспонированная матрица AT (NM) получается из матрицы A (MN) путем перестановки элементов: столбцы становятся строками и наоборот, т.е. aTji = aij, где i = 1, …, M, j = 1, …, N. Требуется сформировать квадратную матрицу A размером 55, содержащую целые числа от 1 до 25 (при заполнении матрицы использовать циклы for) и вывести ее на экран по строкам, а затем создать транспонированную матрицу AT на месте матрицы A и вывести ее на экран по строкам.

2. Лабораторная работа №2 Использование указателей при работе с видеопамятью

2.1. Цель лабораторной работы Целью данной лабораторной работы является изучение организации внутренней памяти ATсовместимых персональных компьютеров и освоение правил работы с дальними указателями.

Работа с указателями рассматривается на примере видеоконтроллера.

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

2.2. Организация памяти IBM PC При работе в MS DOS современные AT-совместимые персональные компьютеры вынуждены использовать организацию адресного пространства, унаследованную от IBM PC (рис. 2.1).

Память ЭВМ IBM PC была организована следующим образом: первые 640 Кбайт адресного пространства с адресами от 00000 до 9FFFF выделены под оперативную память, а остальные 384 Кбайт c адресами от A0000 до FFFFF используются для размещения ПЗУ и отображаемого на память ввода-вывода.

В начале области ОЗУ размещена область векторов прерываний: 256 векторов, занимающих по 4 байта памяти. После них расположены области данных и программ операционной системы.

Оставшуюся часть ОЗУ занимают программы пользователя.

Адреса в области ПЗУ и отображаемого ввода-вывода распределены следующим образом:

A0000-BFFFF – область ввода-вывода видеоконтроллера, C0000-FFFFF – область ПЗУ жесткого диска, видеоадаптера и других устройств.

Программы используют пространство памяти в 1 Мбайт в виде сегментов. Сегмент представляет собой логическую единицу памяти размером 64 Кбайт. Каждому сегменту программой назначается базовый адрес, являющийся адресом его первого байта в адресном пространстве памяти. Все сегменты начинаются на 16-байтных границах памяти, называемых границами параграфов. Сегменты могут быть соседними (смежными), непересекающимися, частично или полностью перекрывающимися. Физическая ячейка памяти может принадлежать одному или нескольким сегментам.

Во время выполнения программы процессору в любой момент времени непосредственно доступны один сегмент кода и один сегмент данных – при работе с ними процессор может использовать «короткие» 16-разрядные адреса. Для работы с данными, расположенными в других сегментах, используются так называемые дальние указатели.

Дальний указатель (far-указатель) – это двойное слово, представляющее собой полный адрес памяти «сегмент:смещение». Старшее слово задает базовый адрес (начало сегмента), а младшее – смещение от начала сегмента.

Для создания дальнего указателя в Borland C используется библиотечная функция MK_FP, описанная в заголовочном файле dos.h:

void far* MK_FP(unsigned segment, unsigned offset) где segment задает сегмент, а offset указывает смещение.

2.3. Видеоконтроллер VGA Видеоконтроллеры IBM PC/AT и совместимых с ними машин могут работать в двух режимах – текстовом и графическом. В связи с тем, что стандартные процедуры BIOS, предназначенные для вывода на экран текста и графики, выполняются медленно, на практике применяются только процедуры переключения видеорежимов, а все остальные операции выполняются путем прямого взаимодействия с аппаратурой.

С точки зрения процессора видеопамять выглядит как одномерный массив, а с точки зрения видеоконтроллера – как матрица. Ось Y и в текстовом, и в графическом режиме направлена сверху вниз.

При работе в цветных текстовых режимах контроллер отображает на видеопамять область адресного пространства B8000h–BFFFFh. Начало этой области соответствует левому верхнему углу экрана.

Каждому символу соответствует два байта памяти: младший байт кодирует вид символа, а старший байт – цвет символа и цвет фона, на котором будет отображен символ. Старший байт при этом имеет формат, показанный на рис. 2.2.

Рис. 2.2. Формат байта описания цвета символа в текстовом режиме

Значения цветовых кодов следующие: 0 – черный, 1 – синий, 2 – зеленый, 3 – бирюзовый, 4 – красный, 5 – фиолетовый, 6 – коричневый, 7 – светло-серый, 8 – темно-серый, 9 – светло-синий, 10

– светло-зеленый, 11 – голубой, 12 – светло-красный, 13 – малиновый, 14 – желтый, 15 – белый.

Для кодирования цвета символов можно использовать значения от 0 до 15, а для кодирования фона – только значения от 0 до 7.

Порядок отображения содержимого видеопамяти на экран в текстовом режиме показан на рис. 2.3.

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

Любые манипуляции с графическими изображениями на растровом устройстве в своей основе опираются на одну-единственную операцию – «нарисовать точку». Данная операция тривиальна и заключается в записи кода цвета точки в ячейку видеопамяти, соответствующую положению точки на экране.

Существует два основных режима адресации видеопамяти:

Устаревший страничный режим, в котором доступ к памяти осуществляется через окно 1) размером в 64 Кбайт, размещенное в первом мегабайте адресного пространства процессора;

Современный линейный режим, в котором процессор видит всю видеопамять целиком как 2) участок своей оперативной памяти и может работать с ней непосредственно.

Для тренировки мы будем в дальнейшем использовать самый простой режим – восьмиразрядный режим с разрешением 320200 точек и страничной адресацией видеопамяти. В страничном режиме процессор видит участок памяти видеоконтроллера как область размером 64 Кбайт внутри своего адресного пространства (рис. 2.4). Эта область начинается по адресу 0A0000h.

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

Восьмиразрядный режим позволяет отобразить 256 различных цветовых оттенков. Каждой точке экрана соответствует один байт видеопамяти.

Рис. 2.4. Страничная адресация видеопамяти

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

Рис. 2.5. Отображение видеопамяти на экран в восьмиразрядном графическом режиме

При работе с видеопамятью следует избегать записи информации в тот участок памяти, который в данный момент выводится на экран монитора лучом электронно-лучевой трубки (ЭЛТ).


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

В случае, когда на экран выводится статическое изображение (рисунок, фотография, график), синхронизация не нужна; если же на экране должны отображаться динамические объекты, вывод изображения должен быть синхронизирован с началом обратного хода луча по кадру.

Параметры работы видеоконтроллера хранятся в специальных восьмиразрядных ячейках памяти – регистрах видеоконтроллера. Доступ к регистрам осуществляется не через адресное пространство оперативной памяти, а через так называемые порты ввода-вывода.

Для синхронизации вывода изображения с началом обратного хода луча по кадру используется так называемый регистр состояния видеоконтроллера, доступный для чтения через порт 3DAh. Синхронизация осуществляется путем проверки значения третьего разряда этого регистра, который содержит признак обратного хода луча по кадру: 0 – прямой ход, 1 – обратный ход луча.

Пример функции синхронизации вывода изображения с частотой кадров:

// Ожидание окончания обратного хода луча по кадру while(!(inportb(0x3DA)&0x8));

2.4. Вывод спрайтов на экран монитора Самый простой способ создания на экране иллюзии движения – спрайтовая анимация.

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

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

Для того, чтобы можно было выводить на экран рисунки сложной формы, применяют маску прозрачности, каждая ячейка которой содержит числовой код, показывающий, выводить ли в данном месте точку рисунка или сохранить фон (например, 0 – сохранить фон, 1 – вывести точку).

При использовании маски прозрачности вывод изображения на экран усложняется: прежде чем копировать точку из матрицы рисунка на экран, процессор должен числовое значение в соответствующей позиции маски (если оно равно нулю, точка пропускается).

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

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

вычислить текущее местоположение изображения движущегося объекта в видеопамяти;

1) сохранить участок фона, поверх которого будет выводиться изображение;

2) вывести изображение объекта;

3) ожидать начала обратного хода луча по кадру;

4) восстановить участок фона, стирая тем самым изображение движущегося объекта.

5) Данные операции повторяются при выводе каждого кадра. Старое изображение объекта каждый раз стирается, после чего объект выводится на новом месте, создавая иллюзию движения.

Упражнение 1. Требуется выполнить следующую последовательность действий:

Ввести, откомпилировать и запустить программу, которая выполняет очистку экрана и вывод 1) текстовых символов путем непосредственного обращения к видеопамяти. Текст программы приведен в листинге 2.1.

Изменить программу таким образом, чтобы вместо очистки экрана выполнялась раскраска 2) фона в виде шахматной доски с синими и зелеными клетками (использовать по два знакоместа на каждую клетку, чтобы клетки были квадратными).

Вывести «бегущий ноль». При запуске в левом верхнем углу экрана выводится символ „0.

3) Далее при каждом нажатии на клавишу Enter символ должен перемещаться в следующую колонку, а при достижении конца строки – в следующую строку. Работа программы должна прекращаться по достижении конца третьей строки.

Листинг 2.1.

Программа, которая выполняет очистку экрана и вывод текстовых символов путем непосредственного обращения к видеопамяти.

#include conio.h #include dos.h // Создание указателя на видеопамять unsigned char far *screen = (unsigned char *) MK_FP(0xB800, 0);

// Вывод символа (параметры: x и y – координаты символа, // CharCode – код символа, Color – цвет символа и фона).

Упражнение 2. Требуется выполнить следующую последовательность действий:

Ввести, откомпилировать и запустить программу, которая работает в графическом режиме с 1) разрешением 320200 точек. Текст программы приведен в листинге 2.1.

Добавить в программу функцию, рисующую горизонтальные отрезки заданного цвета с 2) заданной координатой Y от левого до правого края экрана.

Добавить в программу функцию, рисующую вертикальные отрезки заданного цвета с 3) заданной координатой X от верхнего края экрана до нижнего..

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

5) Организовать цикл вывода изображения таким образом, чтобы оно перемещалось от левого 6) края экрана до правого с шагом в одну точку при каждом нажатии клавиши Enter.

Добавить массив 88 типа unsigned char для хранения фона и усовершенствовать цикл 7) вывода изображения, чтобы фон восстанавливался после перемещения изображения.

Добавить в программу функцию синхронизации вывода изображения с частотой кадров 8) WaitSync.Изменить цикл вывода изображения так, чтобы изображение перемещалось не по нажатию Enter, а по началу обратного хода луча.

Изменить программу таким образом, чтобы слева направо перемещался не один, а несколько 9) одинаковых объектов – строем (цепью).

Листинг 2.2.

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

// Вывод точки заданного цвета в заданную позицию экрана // (параметры: x и y – координаты точки, Color – цвет точки).

> // Главный модуль void main() < unsigned x, y;

SetMode(0x13); // установить графический режим 320×200 ClearScreen(); // очистить экран // Отобразить всю палитру цветов в виде вертикальных линий for(y=0; y100; y++) for(x=0; x256; x++) Pixel(x,y,x);

getch(); // ожидать нажатия любой клавиши SetMode(3); // восстановить текстовый режим >

3. Лабораторная работа №3 Работа с файлами и каталогами

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

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

3.2. Функции для работы с дисками и каталогами Прототипы функции, предназначенных для выполнения операций с логическими дисками и каталогами файлов, заданы в файле dir.h.

Функция getdisk возвращает номер текущего устройства (0 – A, 1 – B, 2 – C и т. д.).

Синтаксис:

Пример:

#include stdio.h #include dir.h void main(void) < int disk;

disk = getdisk() + ‘A’;

printf(«Текущий дисковод: %c\n», disk);

> Функция setdisk устанавливает в качестве текущего дисковод, определяемый параметром

drive (0 – A, 1 – B и т. д.). Функция возвращает общее число доступных дисководов. Синтаксис:

int setdisk(int drive);


Пример:

#includestdio.h #includedir.h void main(void) < int maxdrives;

printf(«Доступно %d логических устройств\n», maxdrives);

> Функция chdir делает текущим каталог, определяемый аргументом path. При успешном завершении функция возвращает значение 0, при возникновении ошибки – -1. Синтаксис:

int chdir(const char * path);

Функция getcwd получает полное имя маршрута для текущего каталога (до buflen байт длиной) и запоминает его в переменной buf. Функция возвращает параметр buf, а в случае ошибки

– значение NULL. Синтаксис:

char * getcwd(char * buf, int buflen);

Пример:

#include stdio.h #include dir.h void main(void) < char buffer[256];

printf(«Текущий каталог: %s\n»,buffer);

> Функция mkdir создает новый каталог с заданным именем. При успешном завершении функция возвращает 0, при возникновении ошибки – -1. Синтаксис:

int mkdir(const char *path);

Пример:

Функция rmdir удаляет каталог, маршрут к которому указан в path (каталог не должен быть текущим или корневым). Функция возвращает 0, если каталог был успешно удален, иначе – значение -1.

Синтаксис:

int rmdir(const char *path);

3.3. Поиск файлов Функция findfirst производит в каталоге диска поиск первого файла, соответствующего заданному шаблону. При успешном завершении поиска функция возвращает 0, иначе – -1.

Синтаксис:

int findfirst(char * pathname, struct ffblk * ffblk, int attrib);

Параметр pathname представляет собой строку, содержащую имя диска, маршрут поиска и имя файла, которое содержать шаблоны (? и *). Если соответствующий файл найден, структура

ffblk заполняется информацией о файле. Структура определена следующим образом:

Параметр attrib – это байт атрибута файла, который может задаваться при помощи констант:

FA_RDONLY – только для чтения, FA_HIDDEN – скрытый файл, FA_SYSTEM – системный файл, FA_LABEL – метка тома, FA_DIREC – каталог, FA_ARCH – архив.

Функция findnext используется для выборки последовательности файлов, соответствующих параметру pathname, задаваемому функцией findfirst. При успешном завершении поиска файла функция возвращает значение 0, в противном случае – значение -1.

Синтаксис:

int fidtnext(struct ffblk * ffblk);

Параметр ffblk – это тот же самый блок, который заполняется при вызове функции findfirst.

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

Пример:

#include stdio.h #include dir.h void main(void) < struct ffblk ffblk;

printf(«Листинг текущего каталога:\n»);

3.4. Функции общего назначения для работы с файлами Прототипы функции, предназначенных для выполнения операций с файлами, заданы в заголовочном файле stdio.h.

Функция fopen открывает файл, именованный параметром filename и связывает его с соответствующим потоком stream. При успешном завершении fopen возвращает указатель на открытый поток stream, в случае ошибки – значение NULL.

Синтаксис:

FILE * fopen(char * filename, char * type);

Строка type, используемая в функции fopen может принимать следующие значения:

r – открыть файл для чтения;

w – создать файл для записи;

а – открыть файл для продолжения записи с конца файла (если файл не существует, он создается);

r+ – открыть существующий файл для обновления (чтения и записи);

w+ – создать новый файл с возможностью изменения (перезаписи данных);

a+ – открыть файл для продолжения записи (с возможностью перезаписи данных).

Если данный файл открывается или создается в текстовом режиме, вы можете приписать символ t к значению параметра type (rt, w+t, и т.д.); аналогично, для спецификации двоичного режима вы можете к значению type добавить символ b (wb, a+b, и т.д.).

При открытии файла в режиме обновления, над результирующим потоком stream могут быть выполнены как операции ввода, так и вывода. Тем не менее вывод не может следовать непосредственно за вводом и наоборот без вмешательства функций fseek или rewind.

Функция fclose закрывает указанный поток stream. Буфера, связанные с потоком, перед закрытием сбрасываются и освобождаются. При успешном завершении функция возвращает 0, если были обнаружены ошибки – значение EOF.

Синтаксис:

int fclose (FILE * stream);

Функция remove удаляет файл, имя которого определяется параметром filename (строка с именем файла может включать маршрут). Если файл был открыт, его следует закрыть. При успешном завершении remove возвращает 0, при ошибке – -1.

Синтаксис:

int remove(const char *filename);

Функция rename изменяет имя файла с oldname на newname. Функцию rename можно использовать для перемещения файла из одного каталога в другой. При успешном переименовании файла функция возвращает 0, при ошибке – -1.

Синтаксис:

int rename(const char *oldname, const char *newname);

Функция feof является макрокомандой, которая производит проверку данного потока stream на признак конца файла EOF. Функция возвращает ненулевое значение, если при последней операции ввода из потока stream был обнаружен конец файла, и 0 в противном случае.

Синтаксис:

int feof(FILE * stream);


Функция fflush записывает в файл содержимое буфера, связанного с потоком stream, если он был открыт на вывод. В случае успешного завершения возвращает 0, при ошибке – EOF.

Синтаксис:

int fflush(FILE * stream);

3.5. Функции для работы с текстовыми файлами Функция fgetc возвращает следующий символ из указанного входного потока stream. При успешном завершении функция возвращает символ, преобразованный к типу int, при обнаружении конца файла – EOF. Синтаксис:

int fgetc(FILE * stream);

Функция fgets считывает из потока stream строку символов и помещает ее в s. Ввод завершается после ввода n–1 символа или при вводе символа перевода строки. При успешном завершении функция возвращает указатель на s, при ошибке или конце файла – NULL.

Синтаксис:

char * fgets(char s, int n, FILE *stream);

Функция fprintf выводит данные в поток stream. Функция возвращает число выведенных байт, а при появлении ошибки – значение EOF.

Синтаксис:

int fprintf(FILE * stream, const char *format [,argument. ]);

Пример:

fprintf(stream,»%d %c %f»,i,c,f);

Функция fputc выводит символ с в поток stream. В случае успеха возвращается символ с, в случае ошибки – EOF.

Синтаксис:

int fputc(int c, FILE * stream);

Функция fputs копирует строку в поток stream. Она не добавляет в конец строки символ перехода на новую строку. При успешном завершении fputs возвращает последний выведенный символ, в случае ошибки – EOF.

Синтаксис:

int fputs(char * string, FILE * stream);

Пример вызова функции:

Функция fscanf сканирует посимвольно набор вводимых полей, считывая их из потока, а затем каждое поле из потока форматируется в соответствии со спецификацией формата, которая передается fscanf в виде указателя на строку format. Полученные значения fscanf запоминает в аргументах, передаваемых после параметра format. Функция возвращает количество успешно прочитанных входных полей. Если fscanf делает попытку чтения в конце файла, то возвращается

EOF. Если не было записано ни одного поля, возвращается значение 0. Синтаксис:

int fscanf(FILE * stream, char * format[, adress. ]);

Пример вызова функции:

Пример использования функций fopen, fgetc, fputc, feof и fclose:

// Программа создает дубликат файла AUTOEXEC.BAT #include stdio.h int main(void) < FILE *in, *out;

if((in = fopen(«AUTOEXEC.BAT»,»rt»))==NULL) return(1);

if((out = fopen(«AUTOEXEC.BAK»,»wt»))==NULL) return(1);

while(!feof(in)) fputc(fgetc(in), out);

3.6. Функции для работы с двоичными файлами Функция fread считывает n элементов данных, каждый длиной size байтов, из потока stream в блок с адресной ссылкой ptr. Функция возвращает количество прочитанных элементов данных.

Синтаксис size_t fread(void *ptr, size_t size, size_t n, FILE * stream);

Функция fseek устанавливает адресный указатель файла, соответствующий потоку stream, в новую позицию, которая расположена по смещению offset относительно места в файле, определяемого параметром fromwhere. Параметр fromwhere может иметь одно из трех значений: 0 (начало файла), 1 (текущая позиция указателя) или 2 (конец файла). Функция возвращает значение 0, если указатель файла успешно перемещен, и ненулевое значение в случае ошибки.

Синтаксис:

int fseek(FILE * stream, long offset, int fromwhere);

Пример – перевести указатель в конец файла:

fseek(stream, 0L, 2);

Функция ftell возвращает положение указателя текущей позиции файла, связанного с потоком stream. При успешном завершении функция возвращает положение указателя, при ошибке – значение -1L. Синтаксис long int ftell(FILE *stream);

Функция fwrite добавляет n элементов данных (каждый элемент имеет размер size байт) в указанный поток. Данные записываются из ptr (ptr должен быть объявлен как указатель на некоторый объект). Функция возвращает число выведенных элементов. Общее число выведенных байт равно n*size.

Синтаксис:

size_t fwrite(void * ptr, size_t size, size_t n, FILE * stream);

Функция rewind устанавливает указатель в начало потока. Синтаксис:

int rewind(FILE *stream);

Пример:

#includestring.h #includestdio.h int main(void) < FILE *stream;

char msg[] = «Тестовый пример»;

if((stream = fopen(«DUMMY.FIL»,»w+»)) == NULL) return 1;

fwrite(msg,strlen(msg)+1,1,stream); // вывести данные fseek(stream,SEEK_SET,0); // перейти на начало файла fread(buf,strlen(msg)+1,1,stream); // прочитать данные printf(«%s\n»,buf);

Требуется составить программы, которые будут выполнять следующие действия:

Ввести текст с клавиатуры (с помощью функции gets), сохраняя каждую введенную строку в 1) файле text.txt с помощью функции fputs. Работа продолжается, пока не будет введена пустая строка.

Вывести на экран текст из файла text.txt (чтение из файла производить с помощью функции 2) fgets, вывод строк на экран – с помощью функции puts).

С помощью функций fseek и ftell определить размер файла text.txt в байтах и вывести 3) полученное значение на экран.

Сформировать массив из 20 элементов типа int, содержащий значения от 1 до 20, и сохранить 4) его в текстовом файле numbers.txt. Каждое число размещается в отдельной строке.

Ввести с клавиатуры значение N типа int. Сформировать массив из N элементов типа int, 5) содержащий значения от 1 до N, и сохранить его в двоичном файле numbers.bin (вначале в файл записывается значение N, а затем – элементы массива).

Прочитать массив чисел из двоичного файла numbers.bin (вначале считывается количество 6) элементов N, а затем производится считывание элементов массива), отобразить массив на экране, а затем удалить файл numbers.bin.

Написать программу, которая выводит в текстовый файл dir.txt следующую информацию:

7) имя активного дисковода, полное имя маршрута для текущего каталога и список файлов в текущем каталоге.


Каждую программу сохранять в отдельном файле.

4. Лабораторная работа №4 Работа с структурами данных на примере файла BMP

4.1. Цель лабораторной работы Целью данной лабораторной работы является изучение современных графических видеорежимов контроллера SVGA и правил работы со структурами данных. В качестве примера рассматривается вывод изображения из файла в формате BMP на экран. В процессе работы требуется преобразовать информацию из одной формы представления, принятой для хранения в BMP-файлах, в другую, используемую для вывода на экран.

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

4.2. Организация видеопамяти в графическом режиме TrueColor Структура таблицы данных файла BMP соответствует организации памяти видеоконтроллера в режиме TrueColor24. В режимах TrueColor для кодирования каждого из трех основных цветов используется по одному байту (рис. 4.1).

Рис. 4.1. Кодирование цвета пикселя в режиме TrueColor

При выводе кода цвета точки в видеопамять первым передается младший байт, соответствующий синей компоненте. Старший байт в 32-битовом режиме не используется – он добавлен только для выравнивания адресов памяти на границу двойного слова и должен иметь значение 0. Пример организации видеопамяти в режиме TrueColor32 показан на рис. 4.2.

Рис. 4.2. Отображение видеопамяти на экран в режиме TrueColor32 1024768

Существует два режима работы с видеопамятью – линейная адресация и передача данных через буфер кадра. При работе в MS DOS можно использовать только режим адресации через буфер. В этом режиме процессор видит участок памяти видеоконтроллера как область размером 64 Кбайт с начальным адресом 0A0000h (рис. 4.3).

Рис. 4.3. Организация доступа к видеопамяти в оконном режиме

Обмен данными между процессором и видеопамятью при адресации через буфер кадра осуществляется заметно медленнее, чем при линейной адресации, так как необходимо постоянно контролировать пересечение границ блока и производить при необходимости переключение на следующий блок. В видеорежимах с длиной строки в байтах, не равной 2N, границы блоков оказываются неровными – конец блока может находиться в любом произвольном месте строки экрана. Для упрощения работы с памятью можно изменить логическую длину строки, увеличив ее до ближайшего значения 2N, превышающего физическую ширину экрана. Такая операция приводит границы сегментов к прямоугольной форме (рис. 4.4).

Рис. 4.4. Реорганизация видеопамяти путем изменения логической длины строки Используемый в лабораторной работе режим TrueColor32 1024768 автоматически обеспечивает прямоугольные границы сегментов. Каждый сегмент отображается в виде узкой полосы шириной 1024 и высотой 16 точек. Всего на экране помещается 48 таких полос.

4.3. Функции VESA BIOS Функции VESA BIOS были введены ассоциацией VESA с целью обеспечения использования новых возможностей современных видеоконтроллеров в операционной системе MS DOS.

Обращение к VESA BIOS выполняется по прерыванию 0x10 с номером функции 0x4F.

Передача данных производится через регистры процессора. После выполнения вызова в регистре AX будет возвращен код результата.

В данной работе используются две подфункции: установка режима и переключение окон.

Подфункция 0x02 устанавливает видеорежим с заданным номером.

Перед вызовом прерывания 0x10 требуется занести в регистр АХ код 0x4F02, в BX – код видеорежима, который имеет следующий формат:

биты 0–8 – номер режима;

биты 9–13 – зарезервированы (имеют значение 0);

бит 14 – режим адресации памяти (0 – оконный, 1 – линейный);

бит 15 – очистка видеопамяти (0 – очищать, 1 – не очищать).

Обычно бит 15 имеет значение 0 – при переключении режима производится очистка памяти.

Номера часто используемых режимов стандартизированы (табл. 4.1). В лабораторной работе используется режим номер 0x118.

Подфункция 0x05 предназначена для управления отображением видеопамяти на адресное пространство процессора при использовании оконного режима. Перед вызовом прерывания требуется занести в регистр АХ значение 0x4F05, в BH – код операции (0 – установить заданное окно), в BL – значение 0, в DX – номер окна.

4.4. Формат BMP для несжатого RGB-изображения Формат BMP для несжатого изображения – самый простой из всех форматов, предназначенных для хранения фотографий. Он воспринимается большинством графических редакторов, но порождает файлы гигантских размеров, поскольку одна точка изображения кодируется тремя байтами данных, по байту на каждую из цветовых компонент.

Файл BMP состоит из двух частей: заголовка файла и данных изображения. Формат заголовка файла описан в таблице 4.2.

Область данных изображения следует за заголовком файла и имеет смещение 0x36 от начала файла. Неприятной особенностью формата BMP является перевернутый по отношению к экрану монитора порядок записи строк в файл – первой записывается нижняя строка изображения.

Другая особенность – каждая строка дополняется пустыми (не содержащими информации) байтами для выравнивания на границу двойного слова, чтобы длина строки в байтах была кратна

4. Пример размещения данных для изображения размером 4х2 показан на рис. 4.5.

4.5. Параметры функции main В лабораторной работе потребуется изменить текст программы таким образом, чтобы можно было при запуске передавать имя BMP-файла в виде параметра. Параметры, передаваемые программе, выступают в роли аргументов функции main. Параметр argc имеет тип int и определяет число строк-параметров. Параметр argv имеет тип char*[] и является массивом указателей на строки параметров программы. Первая строка argv содержит полное имя программы (включая путь доступа).

Пример программы, которая печатает все переданные аргументы:

#include stdio.h void main(int argc, char *argv[]) < int i;

for(i=0; iargc; i++) printf(«%s\n», argv[i]);

Требуется выполнить следующую последовательность действий:

Ввести, откомпилировать и запустить программу, приведенную на листинге 4.1.

1) Добавить в программу функцию, рисующую горизонтальные отрезки заданного цвета с 2) заданной координатой Y от левого до правого края экрана, а также функцию, рисующую вертикальные отрезки заданного цвета с заданной координатой X от верхнего края экрана до нижнего. С помощью добавленных функций разлиновать экран линиями белого цвета, чтобы получить клетки 3232.

Добавить описатель структуры заголовка файла BMP. В главном модуле отрыть для чтения 3) двоичный файл rgb1.bmp. Прочитать из файла заголовок.

Добавить в программу массив из 4096 элементов типа unsigned char для промежуточного 4) хранения строки изображения. Используя информацию о ширине и высоте изображения, построчно читать и выводить на экран данные из файла.

Добавить указатель для работы с видеопамятью как c массивом типа unsigned long, чтобы 5) можно было передавать точку изображения за одну операцию.

Добавить функцию, переворачивающую изображение слева направо. Перевернуть 6) изображение, ожидать нажатия любой клавиши, вернуть изображение в исходное состояние, ожидать нажатия клавиши.

Добавить функцию, переворачивающую изображение сверху вниз. Перевернуть 7) изображение, ожидать нажатия клавиши, вернуть в исходное состояние, ожидать нажатия клавиши.

Добавить функцию, преобразующую изображение в черно-белое (с 256 градациями яркости).

8) Изменить программу таким образом, чтобы имя файла передавалось из командной строки 9) через параметры функции main().

Ниже приведен пример программы, которая работает в режиме TrueColor32 1024768.

Листинг 4.1.

Программа, которая выполняет заливку экрана синим цветом в графическом режиме с разрешением 320200 точек.

#include stdio.h #include conio.h #include dos.h Библиографический список Абраш М. Таинства программирования графики. – К: ЕвроСИБ, 1996. – 384 с.: ил.

Белецкий Я. Энциклопедия языка Си: Пер. с польск. – М: Мир, 1992. – 687 с.: ил.

Керниган Б. Ритчи Д. Язык программирования Си: Пер. с англ. / Под ред. В.С. Штаркмана. – 3.

2-е изд. – М: Финансы и статистика, 1992. – 272 с.: ил.

Программирование на аппаратном уровне: специальный справочник. 2-е изд. / В.Г. Кулаков.

– СПб.: Питер, 2003. – 848 с.: ил.

Сван Т. Форматы файлов Windows: Пер с англ. – М: БИНОМ, 1994. – 288 с.: ил.

Turbo C++. Руководство пользователя. – М: СП Интрквадро, 1991.

Turbo C++. Руководство программиста. – М: СП Интрквадро, 1991.

Turbo C++. Справочник по библиотеке. – М: СП Интрквадро, 1991.

Илон Маск рекомендует:  Что такое код getmenuitemid
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL
Поделитесь ссылкой пожалуйста: