Похожие презентации:
2_1 Программирование 2022_2023
1. Программирование 2 курс
Александр Иванов, канд. экон. наукПРОГРАММИРОВАНИЕ
2 КУРС
2.
1. Общие сведения о среде разработки Оконнаябиблиотека в данном курсе создается в операционной
системе MS-DOS. Такой выбор – исходя из учебных
целей.
2. Для написания программ используется
интегрированная среда разработки Turbo C 2.01
3.
Среда выпущена в 1989 г.Включает в свой состав редактор, компилятор, дебаггер.
Можно официально скачать с сайта правообладателя
http://edn.embarcadero.com/article/20841.
1) нельзя использовать комментарии типа //
2) все переменные надо объявлять в начале функции.
3) Тип int имеет размер 2 байта.
Стандарт: ANSI 1988
4.
1. В этом режиме экран разделён на 80 столбцов и 25строк, то есть на 80х25 знакомест.
2. При отрисовке каждого знакоместа может
использоваться 16 цветов.
3. Видеоадаптер имеет две области памяти. В первой
хранится битовый шрифт, а во второй размещаются
данные, образующее текущее изображение на
экране. Эта вторая область называется текстовым
буфером или просто видеопамятью. Запись в эту
область немедленно отражается на экране.
5.
1. Каждый символ кодируется целым числом от 0 до127 из ASCII кодировки, а также от 128 до 255 из
кодовой таблицы CP866.
6.
1. Каждому символу (коду символа) ставится всоответствие его битовый образ для изображения
на экране. Этот битовый образ представляет собой
матрицу фиксированного размера. Например, для
матрицы размером 8х10 символ ‘c’ может быть
нарисован так:
2. Такой символ можно описать десятью числами,
размером 1 байт каждое, которые в
шестнадцатеричном представлении имеют вид:
00 3С 66 С0 С0 С0 66 3С 00 00
7.
Будем описывать положение символа на экране номером строки xи номером столбца y. , где строки нумеруются сверху вниз от 0
до 24, а столбцы слева направо от 0 до 79. Тогда адрес
каждого символа можно вычислить так:
адрес = начало_видеопамяти + x*160 + y*2.
Видеопамять начинается с адреса 0хB80000000. Тогда для записи
символа на экран нужно написать следующий код
Запись символа и атрибута в видеопамять
static char* const VMEM = (char*)0xB8000000L;
int x=10,y=5;
char* v = (char*)0xB8000000L;
v += x*160 + y*2;
*(v++) = ‘A’; v = 0x17;
8.
Битовый флаг – это целое число, в котором имеется только одинненулевой бит в нужной позиции.
Битовая маска – это целое число, в котором имеется несколько
ненулевых битов в нужных позициях
Код символа можно задать как числом, так и непосредственно
символом ( ‘Ф’ или 0x94 ). Эта возможность поддерживается языком
программирования. Но для атрибута в языке никаких обозначений
нет .
Байт атрибута интерпретируется так, как показано на следующей
таблице
Бит
Значение
0
1
2
3
4
5
6
7
голубой для символа
зеленый для символа
красный для символа
интенсивность цвета
символа
голубой фоновый
зеленый фоновый
красный фоновый
мигающий символ
9.
Можно видеть, что символ может иметь 8 комбинаций цветов в двухразных интенсивностях, то есть 16 цветов. Фон символа будет иметь
всего восемь цветов. Кроме этого, символ может быть сделан
мигающим.
Однако непосредственная нумерация атрибутов неудобна. Что
означает, например, атрибут 0x17, который использовался в
примере выше? Чтобы ответить на этот вопрос, придётся провести
некоторые вычисления.
Для облегчения работы с закодированной в конкретных битах
информацией используются битовые флаги и битовые маски.
Бит
0
1
2
3
4
5
6
7
Значение
голубой для символа
зеленый для символа
красный для символа
интенсивность цвета
символа
голубой фоновый
зеленый фоновый
красный фоновый
мигающий символ
10. Битовые флаги
БИТОВЫЕ ФЛАГИИз таблицы с атрибутами можно определить восемь флагов,
определяющих значения битов в байте атрибута. Традиционно в С
для этого определения используют символические константы,
заданные через директивы препроцессора #define. Например,
Определение символических констант
#define BLACK 0x0000
#define BLUE 0x0001
#define GREEN 0x0002
#define RED 0x0004
Имея такие определения, можно определить циановый цвет с помощью
битовой маски
CYAN = BLUE | RED;
в которой биты будут стоять в нулевом и первом разрядах.
Однако и это неудобно, а удобно задать цвета символов
непосредственно:
#define CYAN 0x0003
11. Битовые маски
БИТОВЫЕ МАСКИБитовую маску удобно использовать для задания комбинации цвета символа,
цвета фона и признака мигания символа. Тогда вывод символа в предыдущей
программе будет выглядеть так:
write_char(10,10,’A’, CYAN | BGBLUE);
где BGBLUE – это голубой цвет для фона (background).
Хотя для задания цвета фона можно было бы воспользоваться цветами символа,
но это и неудобно, и чревато ошибками, что можно видеть из следующего
вызова, аналогичного предыдущему:
write_char(10,10,’A’, CYAN | (BLUE << 4) );
Мерцание символа можно задавать отдельным флагом, и тогда вывод
мигающего символа может иметь вид
write_char(10,10,’A’, CYAN | BGBLUE | BLINK);
12. Задача 1.2.
ЗАДАЧА 1.2.Определить символические константы для цвета
символов: BLACK, BLUE, GREEN, CYAN, RED, MAGENTA,
BROWN, LIGHTGRAY, DARKGRAY, LIGHTBLUE,
LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA,
YELLOW, WHITE, а также
2. Восемь цветов для цвета фона: BGBLACK, BGBLUE,
BGGREEN, BGCYAN, BGRED, BGMAGENTA, BGBROWN,
BGLIGHTGRAY.
Кроме того,
3. Определить флаг BLINK для мигания символа.
1.
4.
Протестировать определения с помощью функции
write_char.
13.
При выводе окна потребуется выводить не один символ,а целые строки (например, заголовок окна). Всё это
можно сделать непосредственно, имея только функцию
write_char, но удобнее иметь для этого специальную
функцию.
Строка для С – это набор символов типа char, который
заканчивается нуль-терминатором – символом с кодом
0.
Строка может храниться в массиве, а может – в
статической памяти.
14.
Определение строкиchar a[] = {‘a’,’b’,’c’,’\0’};
char *b = “abc”;
Практическое отличие между переменными a и b в вышеприведённом
примере в том, что операция sizeof для a и b будет давать разные
результаты
Массив a это, конечно, просто массив из 4 элементов, но его можно
использовать как строку из трёх символов. Без нуль-терминатора
массив a будет только массивом целых числе типа char. В качестве
строки его применять будет нельзя.
Указатель b содержит адрес первого символа строки “abc”. Следует
знать, что при приведённом выше определении указателя b в память
после символа ’c’ автоматически помещается также и нуль-терминатор.
Как и с любым указателем с b можно обращаться в почти во всех
случаях как с массивом, например так c = b[0];
Перебор символов строки удобно выполнять с помощью указателя на
текущий символ. Критерием остановки будет условие достижения нуля.
15.
char *s;for(s = b; *s; s++) write_char(x,y++,s,atrib);
Этот алгоритм надо реализовать в виде функции вывода
строки, которую будем называть write_string.
Задача 1.3.
Определить функции вывода строки и заполнения
области, имеющие вид:
write_string(int x,int y,char*string,char attrib);
16.
Заполнение и стирание прямоугольных областейалгоритм вывода и закрытия окна будет иметь следующий вид.
А. Создание окна. Создать память определённого размера - буфер.
А. Открытие окна.
1. Последовательно считать в буфер подоконный участок видеопамяти.
2. Нарисовать область окна.
Б. Закрытие окна
1. Считать содержимое буфера в видеопамять.
В. Уничтожение окна
1. Уничтожить буфер.
17.
Функции управления динамической памятью.Их прототипы объявлены в файле stdlib.h.
void *malloc(int size);
void free(void*p);
Функция malloc выделяет блок динамической памяти
размером size байт. В случае ошибки она возвращает
NULL. При нормальном завершении возвращается
указатель на нужную память.
Функция free освобождает выделенную память, на
которую указывает указатель p.
18.
Выделение буфера для подоконного пространства будеттогда иметь вид:
Выделение памяти для буфера
char * p;
int size = (endx-startx+1)*
(endy-starty+1)*2*sizeof(char);
p = malloc(size);
if( !p ) {
fprintf(stderr,”Error”);
exit(1);
}
19.
char*buffer,*p;for(x=startx;i<=endx;x++) for(y=starty;y<=endy;y++)
{
p = VMEM + y*160+x*2;
*buffer++ = *p++; // запись символа
*buffer++ = *p; // запись цвета
}
20.
Определить функцию заполнения области, имеющиевид символом ch с атрибутом attrib:
void сlear(int startx,int starty, int endx,int endy,
char ch,char attrib);
Определить функции чтения из видеопамяти в буфер и
наоборот
void get_vmem(int startx,int starty, int endx,int endy,
char*buffer);
void put_vmem(int startx,int starty, int endx,int endy,
char*buffer);
Написать программу, выводящую окно и стирающую
его с восстановлением подоконного содержимого.
21. Вывод рамки окна
ВЫВОД РАМКИ ОКНА• Для рисования в текстовом режиме используются
всякие вспомогательные символы, которые называются
псевдографическими.
• Например, для заполнения всего экрана (рисование
«рабочего стола») использовался часто
псевдографический символ с кодом 0xB0 белого цвета
на синем фоне. Для рамок окон используются
следующие символы.
• CD BA C9 BB C8 BC то есть ═ ║ ╔ ╗╚ ╝
• C4 B3 DA BF C0 D9 то есть ─ │ ┌ ┐└ ┘
22. Задача 2.2
ЗАДАЧА 2.2Определить функции заполнения всего экрана
символом с кодом 0xB0 белого цвета на синем фоне
void desktop(void);
а также вывода рамок в зависимости от типа рамки
typ:
void border(int startx,int starty, int endx,
int endy, char attrib, int typ);
23. Вывод имени окна
ВЫВОД ИМЕНИ ОКНАИмя окна будем выводить по центру самой первой
строки символов области окна. Для этого необходимо
вычислить координату начала строки.
y = starty + (endy-starty-len)/2
Длина строки len может быть вычислена
самостоятельно, а можно воспользоваться
библиотечной функцией strlen, объявленной в string.h.
Задача 3.3.
Определить функцию вывода заголовка окна
void name(int startx,int starty, int endy,
char*str, char attrib, int typ);
24. Архитектура библиотеки Программные модули и интерфейсы
АРХИТЕКТУРА БИБЛИОТЕКИПРОГРАММНЫЕ МОДУЛИ И ИНТЕРФЕЙСЫ
Пользовательские
модули
вызывают
недоступны
Функциональные
модули
вызывают
Базисные
модули
недоступны
используют
Системный
уровень
25. Интерфейс в заголовочных файлах
ИНТЕРФЕЙС В ЗАГОЛОВОЧНЫХ ФАЙЛАХЧасть заголовочного файла base.h
#if !defined (_BASE_H_)
#define _BASE_H_
#define BLACK 0x0000
#define BLUE 0x0001
#define GREEN 0x0002
#define RED 0x0004
write_char(int x,int y,char ch,char attrib);
write_string(int x,int y,char*string,char attrib);
put_box(int startx,int starty, int endx,int endy,
char ch,char attrib);
#endif
26. Физическое размещение частей программной системы базисного уровня
ФИЗИЧЕСКОЕ РАЗМЕЩЕНИЕ ЧАСТЕЙПРОГРАММНОЙ СИСТЕМЫ БАЗИСНОГО УРОВНЯ
включение
объявлений
базисных
функций
Файл base.h
void
write_char(...);
интерфейс
базисных
функций
реализация
базисных
функций
Файл с вызовом
базисных функций
#include <base.h>
...
void fun(void) {
write_char(...);
}
Файл base.c
#include <base.h>
void write_char(...)
{
...
}
27. Задача 3.1.
ЗАДАЧА 3.1.Переместить написанные базисные функции в файл
base.c, интерфейс – в заголовочном файле base.h, а
тестовые вызовы функций разместить в файле main.c.
Чтобы скомпилировать их вместе, нужно создать файл
проекта: текстовый файл с расширением prj, в котором
просто перечислены все с-файлы (каждый с новой
строки). Добавить этот файл в меню Project.
28. Интерфейс оконного модуля
ИНТЕРФЕЙС ОКОННОГО МОДУЛЯМинимально можно определить окно как 1)
прямоугольник 2) некоторого цвета 3) с именем. То есть
окно описывается следующими переменными:
Описание окна
int startx,starty,endx,endy;
int attrib;
char name[80];
каждое окно – это целый блок данных,
с которым удобнее было бы работать как с целым, для
чего используетя структуризация
.
29. Объявление структурного модуля
ОБЪЯВЛЕНИЕ СТРУКТУРНОГО МОДУЛЯstruct window {
int startx,starty,endx,endy;
int attrib;
char name[80];
};
Исключительный случай в языке С:
после фигурной скобки требуется ставить точку с запятой
};.
30. Объявление структурной переменной
ОБЪЯВЛЕНИЕ СТРУКТУРНОЙ ПЕРЕМЕННОЙОбъявление структурной переменной
struct window_t a;
Сразу видно ещё одно отличие от встроенных типов: при
объявлениях приходится «таскать» за собой ключевое
имя struct. Иногда это повышает ясность программ, но
чаще это мешает. Этот недостаток легко устранить,
воспользовавшись оператором typedef.
Другое объявление структуры
typedef struct {
int startx,starty,endx,endy;
int attrib;
char name[80];
} window_t;
window_t a;
31. Обращение к полям структуры
ОБРАЩЕНИЕ К ПОЛЯМ СТРУКТУРЫоператор typedef создаёт синоним для какого-то типа, и нужен
только для повышения «читабельности» исходного кода. Например:
Пример typedef
typedef char* String
String c;
Для обращения к полю структуры используется операция «точка»:
Обращение к полю структуры
window_t w;
w.startx = 10;
Рассмотрим теперь вопрос передачи структуры в качестве
аргумента функции.
Естественным способом будет написать некоторую функцию
следующим образом:
void fun(window_t w);
В этом случае при вызове функции создаётся копия структуры
window_t, и именно с этой копией будет работать код функции fun.
32. Программа обращения пользователя к функциям окна
ПРОГРАММА ОБРАЩЕНИЯ ПОЛЬЗОВАТЕЛЯ КФУНКЦИЯМ ОКНА
Используется способ передачи аргумента – «по ссылке», то есть с
использованием указателя:
void fun(window_t * w);
В этом случае функция fun вместо большого блока данных получит в
качестве аргумента одно целочисленное значение – адрес, где
находится структура w.
window_t *w;
w = window_create(“Окно”, 10,10, 50,17, WHITE | BLUE);
window_open(w);
window_close(w);
window_delete(w);
В функции window_create будут определены поля структуры,
описывающей окно.
Чтобы работать с членами структуры через указатель, используется
операция ->:
w->starty = starty;
strcpy(w->name,name); /* копирование строки */
33. Добавление интерактивности Обработка нажатий клавиш
ДОБАВЛЕНИЕ ИНТЕРАКТИВНОСТИОБРАБОТКА НАЖАТИЙ КЛАВИШ
Операционная система
(Windows, Linux)
Интерфейс
(BIOS, EFI)
Встроенные программы
(firmware)
Внешние устройства
34. Программа обращения пользователя к функциям окна
ПРОГРАММА ОБРАЩЕНИЯ ПОЛЬЗОВАТЕЛЯ КФУНКЦИЯМ ОКНА
Улучшение интерактивности через получение информации о
1) нажатой клавише и
2) о местоположении курсора в момент нажатия
Решение этих задач можно было бы осуществить
через прямое обращение к аппаратуре. В частности, для получения
информации о клавише можно было бы читать данные из
буфера клавиатуры, подобно видеопамяти имеющего
определённый адрес.
Однако для знакомства с возможностями языка, воспользуемся
вызовом функций BIOS.
BIOS (Base Input Output system) – это интерфейс для обращения к
программам, записанным на микросхему (ПЗУ) компьютера,
отвечающим за первоначальную загрузку компьютера, а также
предоставляющим интерфейс между операционной системой и
устройствами ввода-вывода (клавиатурой, монитором и т.д.).
35. Получение кода нажатой клавиши
ПОЛУЧЕНИЕ КОДА НАЖАТОЙ КЛАВИШИunion REGS in,out;
int code;
in.h.ah = 0x00;
int86(0x16,&in,&out);
code = out.x.ax;
Переменные in и out предназначены для доступа к регистрам
процессора до и после вызова прерывания. Остаётся лишь
разъяснить, что такое union., которое уже является частью языка С .
Объединение union применяется для организации доступа к
некоторой памяти как к целому, так и к её частям. Например,
вместо двух аргументов: символа и атрибута можно было бы
использовать один:
union {
char ch, attrib;
int vid;
} VID;
union VID v;
v.vid = 0x1780;
v.ch = ‘A’; v.attrib = 0x17;
36. Получение кода нажатой клавиши 2
ПОЛУЧЕНИЕ КОДА НАЖАТОЙ КЛАВИШИ 2В этом примере две последние строчки ведут к одному и тому же результату:
определению двух байтов с символом ‘A’ и атрибутом 0x17, причем
старший байт – это 0x17.
Вместо этого можно было бы обойтись битовыми операциями так:
int vid = 0x80 & (0x17 << 8);
Но этот способ менее наглядный и в нём наружу торчат низкоуровневые
детали. Объединение позволяет скрыть эти детали внутри своего
определения так, что при изменении низкоуровневых условий не
понадобится менять весь остальной код. Аналогично двухбайтный код
нажатой клавиши можно было бы обработать в функции window_getkey так.
union KEY {
char ascii, scancode;
int code;
};
union KEY k;
...
k.code = _AH;
if(k.ascii == 0) {
/* это функциональная клавиша */
return k.scancode + 0x100;
} else return k.ascii;
37. Хранение состояния регистров
ХРАНЕНИЕ СОСТОЯНИЯ РЕГИСТРОВstruct WORDREGS {
unsigned int ax,bx,cx,dx,si,di,cflag;
};
struct BYTEREGS {
unsigned int al,ah,bl,bh,cl,ch,dl,dh;
};
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
В структуре WORDREGS хранятся значения двухбайтных регистров общего
назначения AX, BX, CX, DX, а также нескольких специализированных
регистров.
В структуре BYTEREGS хранятся значения тех же двухбайтных регистров
общего назначения, но отдельно по младшему (Low) и старшему (High)
байтам AL, AH, BL, BH, CL, CH, DL, DH.
В объединении REGS эти структуры совмещаются в памяти так, что пара
байтов AL, AH образует два байта AX.
38. Позиционирование курсора
ПОЗИЦИОНИРОВАНИЕ КУРСОРАУстановка курсора в определённое место на экране
осуществляется с помощью прерывания BIOS.
Код на ассемблере имеет вид:
mov ah, 0x02 ; поместить 2 в регистр AH
mov dl, x ; поместить номер строки в регистр DL
mov dh, y ; поместить номер столбца в регистр DH
mov bh, 0x00 ; поместить 0 в регистр BH
int 10
; вызвать прерывание
Из этой программы можно получить код на С с
использованием функции geninterrupt, и оформить как
функцию базового уровня goto_xy.
39. Ввод и вывод строки в окне
ВВОД И ВЫВОД СТРОКИ В ОКНЕПереходим к реализации функций, обеспечивающих
взаимодействие пользователя с программой.
Для начала понадобится функция позиционирования в окне. Для
этого в структуру окна надо добавить координаты курсора curx и
cury, которые будут изменяться от 0 до endx(y)-startx(y)-1.
Координаты curx=0 и cury=0 будут соответствовать левому верхнему
углу окна (с учётом рамки).
Весь контроль за корректировку этих координат и саму
корректировку возьмёт на себя новая функция
int window_xy(window_t*w, int x,int y);
При выходе за пределы окна она должна возвращать какой-то код,
чтобы можно было скорректировать x или y.
Это нужно, чтобы в интерактивных функциях не возиться с
вычислениями экранных координат, так как работать с
относительными координатами проще.
40. Ввод и вывод строки в окне 2
ВВОД И ВЫВОД СТРОКИ В ОКНЕ 2Функция goto_xy использует абсолютные координаты, связанные со всем
экраном. Пересчёт в относительные координаты будет выполняться очень
просто. Для этого внутри функции window_xy будет использоваться код
наподобие следующего:
goto_xy(w->startx+x+1,
w->starty+y+1);
«Плюс 1» потому, что рабочая область окна не включает область рамки.
Далее понадобится функция вывода символа в окно. Прототип функции
следующий
void window_putchar(window_t*w, char c);
Поскольку в аргументах функции нет координат, то предполагается, что
перед этой функцией вызывается функция window_xy, то есть
window_putchar выводит символ, начиная с текущего положения курсора.
Ниже приведён не очень хороший код функции window_putchar. Плох он
тем, что работает с curx и cury и контролирует границы этих координат
вместо того, чтобы это делала window_xy.
41. Начальная версия функции вывода символа
НАЧАЛЬНАЯ ВЕРСИЯ ФУНКЦИИ ВЫВОДАСИМВОЛА
void window_putchar(window_t*w ,char ch)
{ int x,y;
if(!w->active) return;
x=w->curx+w->startx+1;y=w->cury+w->starty+1;
if(x<=w->startx || y<=w->starty ||
y>=w->endy || x>=w->endx) return;
if(ch =='\n') {
y++;x=w->startx+1;w->cury++;w->curx=0;
} else{
w->curx++;
write_char(x,y,ch,w->attrib);
}
window_xy(w,w->curx,w->cury);
}
42. Начальная версия функции вывода символа 2
НАЧАЛЬНАЯ ВЕРСИЯ ФУНКЦИИ ВЫВОДАСИМВОЛА 2
Функция window_putchar нужна, чтобы было проще реализовать следующую
функцию – ввода строки. Работа будущей функции будет выглядеть
следующим образом. Прототип
int window_gets(window_t*w, char*str,int len);
Длина строки указывается, чтобы не было переполнения буфера. При
вызове функции от пользователя ждут ввода символов. При вводе символа
курсор смещается вправо, и пользователь может вводить символ вновь.
При достижении границы окна ввод переносится на строку ниже в левую
позицию окна. Если пользователь нажимает BKSP, курсор сдвигается назад,
последний введённый символ удаляется. Если при этом удаляемый символ
самый правый (текущая позиция самая левая), то курсор перемещается на
строку вверх и в крайнюю правую позицию окна. Естественно, если
удаляемый символ нулевой, то ничего делать не надо.
Вводятся только ASCII-символы и F10. Ввод всех остальных символов
(функциональных клавиш) должно игнорироваться.
Все действия при вводе символа сопровождаются добавлением
(удалением) текущего символа в буфер str.
При нажатии клавиши Enter (CR) или F10 в конец буфера str добавляется
нуль-терминатор и возврат из функции. При нажатии ESC должно быть
восстановлено предыдущее содержимое строки.
}
43. Начальная версия функции ввода строки
НАЧАЛЬНАЯ ВЕРСИЯ ФУНКЦИИ ВВОДАСТРОКИ
int window_gets(window_t*w ,char* s ,int len)
{
char ch,*starts;
int count = 0;
if(!w->active) return 1;
starts = s;
for( ;; ) {
if(count == len) ch = '\r';
else ch=window_getkey(w);
switch(ch) {
case CR:
*s='\0'; return 0;
case BKSP:
if(s>starts) {
s--;count--;
window_xy(w,--w->curx,w->cury);
window_putchar(w,' ');
}
break;
case ESC: return 0;
default :
*s=ch;s++;count++;
}
}
return 0;
}
44. Начальная версия функции ввода строки комментарий
НАЧАЛЬНАЯ ВЕРСИЯ ФУНКЦИИ ВВОДАСТРОКИ КОММЕНТАРИЙ
Для полноты можно реализовать функцию вывода строки в окно. Прототип
функции следующий
void window_puts(window_t*w, char*str);
Поскольку в аргументах функции нет координат, то предполагается, что
перед этой функцией вызывается функция window_xy, то есть window_puts
выводит строку, начиная с текущего положения курсора.
Очевидно, надо контролировать выход строки за пределы активного окна,
поэтому алгоритм работы функции – это цикл посимвольного вывода строки
str с помощью уже готовой функции write_char и с контролем выхода за
пределы рабочей зоны окна.
Следует понимать, что window_puts не дублирует функцию write_char,
которая работает не в окне, а на экране. Функция window_puts ограничена
окном и не позволит выйти за его пределы.
Полезным дополнением к возможностям window_puts может быть перевод
строки при достижении границы окна. Тогда вывод большого текста в
рамках окна будет легко выполняться этой функцией. Более сложное, но
тоже очень полезное развитие возможностей – это добавление скроллинга
окна.
}
return 0;
}
45. Реализация функции вывода
РЕАЛИЗАЦИЯ ФУНКЦИИ ВЫВОДАПолезным дополнением к возможностям window_puts может быть перевод
строки при достижении границы окна. Тогда вывод большого текста в
рамках окна будет легко выполняться этой функцией. Более сложное, но
тоже очень полезное развитие возможностей – это добавление скроллинга
окна.
Реализацию функции сделаем очень простой.
void window_puts(window_t*w,char*str)
{
if(!w->active) return;
for( ; *str; str++) window_putchar(w,*str);
}
Можно видеть, что все проблемы с контролем местоположения переложены
на более элементарную функцию window_putchar.
46. Задание 4.3
ЗАДАНИЕ 4.3Реализовать функцию
int window_xy(window_t*w, int x,int y);
Добавить в неё проверку выхода за пределы окна и, разумеется,
активности самого окна.
Переделать функцию
void window_putchar(window_t*w ,char ch)
так, чтобы она не занималась контролем координат и вообще их не
касалась. Это надо поручить функции window_xy.
Реализовать функцию
int window_gets(window_t*w ,char* s ,int len);
которая соответствует спецификации
47. Спасибо за внимание!
СПАСИБО ЗА ВНИМАНИЕ!alexanderivanov52@yandex.ru
Программирование