ПРИЛОЖЕНИЕ 1
ПРИМЕРЫ ОБРАБОТКИ ТЕКСТОВЫХ И БИНАРНЫХ ФАЙЛОВ
Пример 1. Дан текстовый файл, фразы в котором отделены друг от друга точками, а слова – пробелами и знаками препинания. Каждая фраза располагается не более, чем на одной строке. Удалить из этого файла все фразы, содержащие цифры.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
char str[100], c;
int i, n;
FILE *fin, *fout;
fin = fopen("text.txt", "rt"); /* исходный файл */
fout = fopen("rezt.txt", "wt"); /*новый файл для
сохранения результата */
if(!fin) /* если не открылся исходный файл */
{ /* сообщаем об ошибке */
printf("Can not open text file\n");
system (“pause”);
return 0; /* прерываем программу */
}
if (!fout) /*если не удалось создать новый файл */
{ /* сообщаем об ошибке */
printf("Can not create text file\n");
system (“pause”);
return 0; /* прерываем программу */
}
printf("\n\nIn file: \n");
while(!feof(fin)) /* пока не конец исходного файла */
{
i = 0;
n = 0;
do
{
fscanf(fin, "%c", &c); /* читаем один символ */
if(c!='\n'&&!(c==' ' && i==0))
{ /* если это не символ конца строки
и не начальный пробел */
str[i] = c; /* присоединяем его к фразе */
i++;
}
if (c>='0'&&c<='9') /* если это цифра */
n++; /* устанавливаем флаг */
} while(c!='.'&&!feof(fin)); /* пока не конец
фразы и не конец файла*/
str[i] = '\0'; /* завершаем фразу */
if(!n) /* если флаг не установлен (цифр не было) */
fprintf(fout, "%s\n", str); /* запись фразы
в новый файл */
}
fclose(fin); /* закрываем файлы */
fclose(fout);
return 0;
}
Пример 2. В текстовом файле записаны целые числа. Подсчитать, сколько чисел содержится в каждой строке.
#include <stdio.h>
main()
{
FILE *f;
int x,k=0;
char c;
f=fopen("int.txt","r");
if (!f) /* если не открылся исходный файл */
{ /* сообщаем об ошибке */
printf("Can not open text file\n");
system ("pause");
return 0; /* прерываем программу */
}
while (!feof(f)) /* пока не конец файла */
{
fscanf(f,"%d",&x); /* читаем число */
k++; /* увеличиваем счетчик */
c=fgetc(f); /* читаем символ – разделитель чисел */
if (c=='\n'||c==EOF) /* если достигнут конец строки
или конец файла */
{
printf("%d ",k); /* выводим значение счетчика
на экран */
k=0; /* обнуляем счетчик для следующей строки */
}
}
fclose(f);
return 0;
}
Пример 3. Компоненты бинарного файла – целые числа. Записать в этот файл вместо отрицательных чисел их квадрат.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
void Gen_press(void); /* функция создания бинарного файла,
содержащего целые числа */
void Pow_file(void); /* замена отрицательных значений в
файле их квадратами */
void Out_file(void); /* вывод содержимого бинарного файла
на экран */
int main(void)
{
int key = 0;
srand(time(0));
while(key!=52)
{
system("CLS");
printf("Menu:\n\t1 - Create file gen press \
\n\t2 - Output file\n\t3 - Change file \
\n\t4 - Exit\n");
key = getchar();
if (key==49) Gen_press();
if (key==50) Out_file();
if (key==51) Pow_file();
}
return 0;
}
void Gen_press(void)
{ /* заполнение файла с помощью генератора случайных чисел */
int k = 0, n = 0;
FILE *fin;
fin = fopen("datfile.dat", "wb");
if(!fin)
{
printf("Can not create binary file\n");
system("pause");
exit(0);
}
k = rand()%100+1; /* случайное количество чисел */
while(k)
{
n = rand()%101 - 50; /* случайное число от -50 до 50 */
fwrite(&n, sizeof(n), 1, fin); /* запись числа */
k--;
}
fclose(fin);
printf("\n\nFile create\nPress any key...\n");
system("pause");
}
void Out_file(void)
{/* вывод содержимого файла на экран */
int n = 0;
FILE *fin;
fin = fopen("datfile.dat", "rb");
if(!fin)
{
printf("Can not open binary file\n");
system("pause");
exit(0);
}
printf("\n\nIn file: \n");
while(fread(&n, sizeof(n), 1, fin)) /* читаем из
файла числа, пока есть, что читать */
{
printf("%5d", n); /* и выводим на экран */
}
fclose(fin);
printf("\nPress any key...\n");
system("pause");
}
void Pow_file(void)
{ /* изменение содержимого файла */
int n = 0;
long k;
FILE *fin;
fin = fopen("datfile.dat", "r+b");
if(!fin)
{
printf("Can not open binary file\n");
system("pause");
exit(0);
}
rewind(fin);
while(fread(&n, sizeof(n), 1, fin)) /* читаем из
файла числа, пока есть, что читать */
{
if (n<0) /*если число отрицательное */
{
n*=n; /* возводим его в квадрат */
fseek(fin, ftell(fin)-sizeof(n), SEEK_SET);
/* возврат к началу блока, содержащего это число */
fwrite(&n, sizeof(n), 1, fin);
/* запись измененного значения */
fseek(fin, ftell(fin), SEEK_SET);
/* повторно используем fseek() для перехода от записи
к чтению, положение указателя текущей позиции
не меняется */
}
}
fclose(fin);
printf("\n\nFile change!\nPress any key...\n");
system("pause");
}
Пример 4. Дан файл, содержащий сведения о клиентах одного кредитора. Структура записи: ФИО, номер телефона, возраст, сумма. Получить сведения о самом старом клиенте, задолжавшем более указанной суммы.
#include <stdio.h>
#include <stdlib.h>
struct person /* описание типа данных */
{
char name[30];
char phone[11];
char age;
float money;
};
void add (char*); /* добавление записи */
void edit (char*); /* редактирование записи */
void show (char*); /* вывод списка */
void search (char*); /* поиск клиента */
int main (void)
{
char file[50];
char menu;
puts ("Name of file:");
gets (file);
do
{
system ("CLS");
puts ("1. Add");
puts ("2. Edit");
puts ("3. Show");
puts ("4. Search");
puts ("5. Exit");
menu = getchar();
switch (menu)
{
case '1': add (file); break;
case '2': edit (file); break;
case '3': show (file); break;
case '4': search (file);
}
}
while (menu!='5');
return 0;
}
/* заполнение одной записи (ввод данных) */
struct person input_client (void)
{
struct person client;
int temp;
fflush(stdin); /* очистка потока ввода */
puts ("Name");
gets (client.name); /*отдельно считывается каждое поле*/
puts ("Phone");
gets (client.phone);
puts ("Age");
scanf ("%d", &temp);
client.age = temp;
puts ("Money");
scanf ("%f", &client.money);
return client; /*функция возвращает всю запись целиком*/
}
void add (char* file) /* добавление записи в файл */
{
FILE * f;
struct person client;
system ("CLS");
if ((f=fopen (file, "ab"))==NULL) /* открываем файл
для добавления */
{
perror ("Error open file");
system ("pause");
return;
}
client = input_client(); /* ввод данных */
fwrite (&client, sizeof (client), 1, f); /* запись
в файл */
fclose (f);
}
void print1 (struct person data) /*печать одной записи */
{
printf ("Name : %s\nPhone : %s\nAge : %d\n \
Sum : %.2f\n",data.name, data.phone,
data.age, data.money);
}
void edit (char* file) /* редактирование записей */
{
FILE * f;
struct person client;
char name[30], yes;
system ("CLS");
if ((f=fopen (file, "rb+"))==NULL) /* открываем
файл для чтения и редактирования */
{
perror ("Error open file");
system ("pause");
return;
}
printf ("Name: ");
fflush(stdin);
gets (name); /* фамилия для поиска */
while (fread(&client,sizeof(client), 1, f))
if (!strcmp(client.name, name)) /*если совпадает */
{
print1 (client); /* выводим запись */
puts ("Redact? (y/n)");
do
yes=getchar();
while (yes!='y' && yes!='Y' &&
yes!='n' && yes!='N');
if (yes=='y' || yes=='Y')
{ /* редактирование */
client = input_client();
fseek(f,-sizeof(client),SEEK_CUR);
fwrite (&client, sizeof (client), 1, f);
fseek(f,0,SEEK_CUR);
}
}
system ("pause");
fclose(f);
}
void show (char* file) /* вывод на экран */
{
FILE * f;
struct person client;
int k=0;
system ("CLS");
if ((f=fopen (file, "rb"))==NULL) /* открываем файл
для чтения */
{
perror ("Error open file");
system ("pause");
return;
}
/* выводим шапку таблицы */
puts ("| N | Name | \
Phone | Age | Sum |");
puts ("---------------------------------------\
----------------------------------");
/* считываем записи по одной до конца файла и выводим их */
while (fread(&client, sizeof(client), 1, f)==1)
printf ("|%3d |%30s |%11s |%8d |%10.2f |\n",
++k, client.name, client.phone,
client.age, client.money);
puts ("---------------------------------------\
----------------------------------");
fclose (f);
system ("pause");
}
void search (char* file) /* поиск */
{
FILE * f;
struct person client;
float money;
int max_age=0, pos;
system ("CLS");
if ((f=fopen (file, "rb"))==NULL) /* открываем файл
для чтения */
{
perror ("Error open file");
system ("pause");
return;
}
puts ("Money?");
scanf ("%f",&money); /* считываем искомую сумму */
while (fread(&client, sizeof(client), 1, f)==1)
{
if (client.money > money &&
client.age > max_age)
{
max_age = client.age;
pos = ftell(f); /* запоминаем текущую позицию –
конец записи */
}
}
if (max_age == 0) puts ("No clients");
else
{
/* возврат к началу запомненной записи */
fseek(f,pos-sizeof(client),SEEK_SET);
fread(&client, sizeof(client), 1, f);
print1 (client);
}
fclose(f);
system ("pause");
}
ПРИЛОЖЕНИЕ 2
НАЧАЛО РАБОТЫ С SDL 1.2.15, SDL_DRAW 1.2.13 И SDL_TTF 2.0.11В ИНТЕГРИРОВАННОЙ СРЕДЕ РАЗРАБОТКИ DEV-CPP 4.9.9.2 ПОД УПРАВЛЕНИЕМ WINDOWS XP
Предположим, что исходно имеется персональный компьютер под управлением операционной системы Microsoft Windows XP, на котором установлена среда разработки Dev-Cpp 4.9.9.2 для всех пользователей. При этом установка была произведена в каталог C:\Dev-Cpp\, в дальнейшем именуемый «каталогом среды разработки Dev-Cpp», а также в качестве языка пользовательского интерфейса выбран русский и включена возможность анализа заголовочных файлов для поиска функций, классов переменных и т.п.
Предположим также, что для упрощения работы с архивами на компьютере установлен свободно распространяемый файловый менеджер FAR 3.0 с модулем расширения arclite для работы с архивами в форматах zip, tar и tar.gz.
Для подготовки среды разработки Dev-Cpp с библиотеками SDL 1.2 и возможности выполнения созданных приложений в дальнейшем вне среды разработки потребуются следующие свободно распространяемые файлы, скачать которые можно по адресу http://www.libsdl.org/:
— SDL-1.2.15.zip – исходные тексты библиотеки SDL. Если не заниматься их сборкой, то из данного файла понадобятся лишь заголовочные файлы.
— SDL-1.2.15-devel-1.2.15-mingw32.tar.gz – архив с файлами для разработки программ в окружении mingw32 (такое же используется в Dev-Cpp), содержит уже собранную динамическую библиотеку SDL.dll для программ, использующих Win32 API, а также необходимые для ее подключения статические библиотеки.
— SDL_draw-1.2.13.tar.gz – исходные тексты библиотеки графических примитивов SDL_draw. Потребуется собирать библиотеку средствами Dev-Cpp, соответствующий проект входит в состав архива.
— SDL_ttf-2.0.11.zip – исходные тексты библиотеки SDL_ttf. Если не заниматься их сборкой, то из данного файла понадобятся лишь заголовочные файлы.
— SDL_ttf-2.0.11-win32.zip – архив с уже собранной динамической библиотекой SDL_ttf для программ, использующих Win32 API и используемыми ей другими динамическими библиотеками: libfreetyp-6.dll и zlib1.dll. К двум последним прилагаются файлы лицензий.
— CharisSILR.ttf – свободно распространяемый шрифт, включающий символы русского алфавита.
Подключение к среде разработки Dev-Cpp библиотеки SDL-1.2.15:
1. Выделяем в архиве SDL-1.2.15.zip все файлы вида SDL-1.2.15\include\*.h и копируем выделенные файлы в подкаталог \include каталога среды разработки Dev-Cpp.
2. Выделяем в архиве SDL-1.2.15-devel-1.2.15-mingw32.tar.gz все файлы вида SDL-1.2.15-devel-1.2.15-mingw32.tar\SDL-1.2.15\lib\libSDL*.* и копируем три выделенных файла в подкаталог \lib каталога среды разработки Dev-Cpp.
Пример создания проекта, использующего только библиотеку SDL-1.2.15 с динамическим связыванием:
1. Создаем новый каталог для проекта, например C:\SDLtest.
2. Запускаем среду разработки Dev-Cpp, создаем новый C-проект типа Console Application с именем, например, SDLtest, сохраняем файл проекта SDLtest.dev в каталоге C:\SDLtest.
3. В файле main.c вместо автоматически созданной заготовки текста программы вводим следующий текст:
#include <SDL.h>
int main(int argc, char *argv[]){
SDL_Surface *screen;
SDL_Event event;
SDL_Rect dst;
if (SDL_Init(SDL_INIT_VIDEO))
return 1;
screen = SDL_SetVideoMode(640, 480, 32,
SDL_ANYFORMAT);
if (!screen){
SDL_Quit();
return 1;
}
dst.x = 10;
dst.y = 10;
dst.w = 50;
dst.h = 50;
SDL_FillRect(screen, &dst,
SDL_MapRGB(screen->format,0,255,0));
SDL_Flip(screen);
while(SDL_WaitEvent(&event)){
if(event.type == SDL_QUIT ||
(event.type == SDL_KEYDOWN &&
event.key.keysym.sym == SDLK_ESCAPE))
{
SDL_Quit();
return 0;
}
}
SDL_Quit();
return 2;
}
4. Из архива SDL-1.2.15-devel-1.2.15-mingw32.tar.gz копируем файл SDL-1.2.15-devel-1.2.15-mingw32.tar\SDL-1.2.15\bin\SDL.dll в каталог с созданным проектом (C:\SDLtest).
5. В параметрах проекта (меню «Проект» – «Параметры проекта»), на вкладке «Параметры», добавляем в столбец «Компоновщик» строку:
-lmingw32 -lSDLmain -lSDL
6. Собираем и запускаем проект (меню «Выполнить» – «Скомпилировать и выполнить») – и он успешно запускается: в верхнем левом углу с небольшим отступом от края на черном фоне ярко-зеленый квадрат. Выход из программы по нажатию клавиши Esc или щелчку по системной кнопке закрытия окна в его заголовке.
Подключение к среде разработки Dev-Cpp библиотеки SDL_ttf-2.0.11:
1. Из архива SDL_ttf-2.0.11.zip копируем файл SDL_ttf-2.0.11\SDL_ttf.h в подкаталог \include каталога среды разработки Dev-Cpp.
2. Из архива SDL_ttf-2.0.11-win32.zip копируем файл SDL_ttf.dll в подкаталог \lib каталога среды разработки Dev-Cpp.
Пример создания проекта, использующего библиотеки SDL-1.2.15 и SDL_ttf-2.0.11 с динамическим связыванием:
1. Создаем новый каталог для проекта, например C:\SDLttftest.
2. Запускаем среду разработки Dev-Cpp, создаем новый C-проект типа Console Application с именем, например, SDLttftest, сохраняем файл проекта SDLttftest.dev в каталоге C:\SDLttftest.
3. В файле main.c вместо автоматически созданной заготовки текста программы вводим следующий текст:
#include <SDL.h>
#include <SDL_ttf.h>
int main(int argc, char *argv[])
{
SDL_Surface *screen;
SDL_Event event;
TTF_Font *fnt = NULL;
SDL_Color text_color;
SDL_Rect dest;
SDL_Surface *text_surface = NULL;
/* Строка "Привет, Мир!" в кодировке utf8 */
char hello_world[]="Привет, Мир!";
if (SDL_Init(SDL_INIT_VIDEO))
return 1;
if (TTF_Init())
return 1;
if(!(screen=SDL_SetVideoMode(640,480,32,
SDL_ANYFORMAT))){
TTF_Quit();
SDL_Quit();
return 1;
}
if(!(fnt = TTF_OpenFont("CharisSILR.ttf", 29))){
TTF_Quit();
SDL_Quit();
return 3;
}
dest.x = 200;
dest.y = 100;
dest.w = 1;
dest.h = 1;
text_color.r = 0;
text_color.g = 0;
text_color.b = 255;
if(text_surface = TTF_RenderUTF8_Solid(fnt,
hello_world, text_color))
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
SDL_Flip(screen);
while(SDL_WaitEvent(&event)){
if(event.type == SDL_QUIT ||
(event.type == SDL_KEYDOWN &&
event.key.keysym.sym == SDLK_ESCAPE))
{
TTF_CloseFont(fnt);
TTF_Quit();
SDL_Quit();
return 0;
}
}
TTF_CloseFont(fnt);
TTF_Quit();
SDL_Quit();
return 2;
}
4. Из архива SDL-1.2.15-devel-1.2.15-mingw32.tar.gz копируем файл SDL-1.2.15-devel-1.2.15-mingw32.tar\SDL-1.2.15\bin\SDL.dll в каталог с созданным проектом (C:\SDLttftest).
5. Выделяем в архиве SDL_ttf-2.0.11-win32.zip все файлы вида *.dll и копируем в каталог с созданным проектом (C:\SDLttftest).
6. В параметрах проекта (меню «Проект» – «Параметры проекта»), на вкладке «Параметры», добавляем в столбец «Компоновщик» строку:
-lmingw32 -lSDLmain –lSDL –lSDL_ttf
7. Копируем файл CharisSILR.ttf в каталог с созданным проектом (C:\SDLttftest).
8. Собираем и запускаем проект (меню «Выполнить» – «Скомпилировать и выполнить») – и он успешно запускается: на экран выводится ярко-синяя надпись «Привет, Мир!». Выход из программы по нажатию клавиши Esc или щелчку по системной кнопке закрытия окна в его заголовке.
Сборка библиотеки SDL_draw-1.2.13 из исходных текстов:
1. Из архива SDL_draw-1.2.13.tar.gz копируем каталог SDL_draw-1.2.13.tar\SDL_draw-1.2.13 в корень диска C: – получаем каталог C:\SDL_draw-1.2.13\ (диск C: приведен для примера – вместо него возможно любое другое расположение, но далее будет рассматриваться именно такой пример).
2. В каталоге C:\SDL_draw-1.2.13\Dev-Cpp\ открываем проект SDL_draw_static.dev.
3. Выполняем в среде разработки Dev-Cpp команду «Перестроить все» (меню «Выполнить» – «Перестроить все») – в каталоге C:\SDL_draw-1.2.13\Dev-Cpp\ появляется новый файл libSDL_draw.a (статическая библиотека). Закрываем проект.
4. В каталоге C:\SDL_draw-1.2.13\Dev-Cpp\ открываем проект SDL_draw_dynamic.dev.
5. В параметрах проекта (меню «Проект» – «Параметры проекта»), на вкладке «Параметры», в столбце «Компоновщик» заменяем вторую строку на следующую:
–lSDL
6. Выполняем в среде разработки Dev-Cpp команду «Перестроить все» (меню «Выполнить» – «Перестроить все») – в каталоге C:\SDL_draw-1.2.13\Dev-Cpp\ появляется новый файл SDL_draw.dll (динамическая библиотека). Закрываем проект.
Подключение к среде разработки Dev-Cpp библиотеки SDL_draw-1.2.13:
1. Из каталога C:\SDL_draw-1.2.13\include копируем файл SDL_draw.h в подкаталог \include каталога среды разработки Dev-Cpp.
2. Из каталога C:\SDL_draw-1.2.13\Dev-Cpp\ копируем файл SDL_draw.dll в подкаталог \lib каталога среды разработки Dev-Cpp.
Пример создания проекта, использующего библиотеки SDL-1.2.15 и SDL_draw-1.2.13 с динамическим связыванием:
1. Создаем новый каталог для проекта, например C:\SDLdrawtest.
2. Запускаем среду разработки Dev-Cpp, создаем новый C-проект типа Console Application с именем, например, SDLdrawtest, сохраняем файл проекта SDLdrawtest.dev в каталоге C:\ SDLdrawtest.
3. В файле main.c вместо автоматически созданной заготовки текста вводим следующий текст программы:
#include <SDL.h>
#include <SDL_draw.h>
int main(int argc, char *argv[])
{
SDL_Surface *screen;
SDL_Event event;
if (SDL_Init(SDL_INIT_VIDEO))
return 1;
screen = SDL_SetVideoMode(640,480,32,
SDL_ANYFORMAT);
if (!screen)
{
SDL_Quit();
return 1;
}
Draw_FillEllipse(screen, 320, 240, 300, 200,
SDL_MapRGB(screen->format, 128, 128, 128));
SDL_Flip(screen);
while(SDL_WaitEvent(&event))
{
if(event.type == SDL_QUIT ||
(event.type == SDL_KEYDOWN &&
event.key.keysym.sym == SDLK_ESCAPE))
{
SDL_Quit();
return 0;
}
}
SDL_Quit();
return 2;
}
4. Из архива SDL-1.2.15-devel-1.2.15-mingw32.tar.gz копируем файл SDL-1.2.15-devel-1.2.15-mingw32.tar\SDL-1.2.15\bin\SDL.dll в каталог с созданным проектом (C:\SDLdrawtest).
5. Из каталога C:\SDL_draw-1.2.13\Dev-Cpp\ копируем файл SDL_draw.dll в каталог с созданным проектом (C:\SDLdrawtest).
6. В параметрах проекта (меню «Проект» – «Параметры проекта», комбинация клавиш Alt+P), на вкладке «Параметры», добавляем в столбец «Компоновщик» строку:
-lmingw32 -lSDLmain –lSDL –lSDL_draw
7. Собираем и запускаем проект (меню «Выполнить» – «Скомпилировать и выполнить») – и он успешно запускается: на черном фоне отображается серый закрашенный эллипс. Выход из программы по нажатию клавиши Esc или щелчку по системной кнопке закрытия окна в его заголовке.
Создание проектов, использующих библиотеки SDL-1.2.15, SDL_draw-1.2.13 и SDL_ttf-2.0.11 с динамическим связыванием:
1. Сам проект создается аналогично вышеприведенным примерам, в папку с проектом помещаются все требуемые файлы динамических библиотек и используемых шрифтов (см. примеры).
2. В параметрах проекта (меню «Проект» – «Параметры проекта», комбинация клавиш Alt+P), на вкладке «Параметры», в столбец «Компоновщик» добавляется строка, подключающая все три библиотеки:
-lmingw32 -lSDLmain –lSDL –lSDL_draw –lSDL_ttf
ПРИЛОЖЕНИЕ 3
ПРИМЕР ПРОГРАММЫ ИМИТАЦИИ ДВИЖЕНИЯ ОБЪЕКТА
Рассмотрим пример демонстрации полета вертолета на фоне облачного неба. Само небо формируется заливкой голубым, с последующим нанесением в случайных местах белых и слегка-сероватых эллипсов – облаков. Вертолет для имитации вращения винтов на разных кадрах рисуется с разным их положением. Создается три поверхности: одна для отображения, вторая для рисования вертолета (в разных положениях) и третья для временного сохранения фона, затираемого вертолетом. Программа будет выглядеть следующим образом:
#include <stdlib.h>
#include <SDL.h>
#include <math.h>
#include <SDL_draw.h>
const int scrwidth = 1027, scrheight = 768,
scrdepth = 32;
void draw_heli(SDL_Surface *surf,
int centre_x, int centre_y,
int phase_big, int phase_samll)
{
const int lw = 200, lh = 80;
if(surf)
{
if(surf->w >= centre_x + lw/2 &&
surf->h >= centre_y + lh/2 &&
centre_x - lw/2 >= 0 && centre_y - lh/2 >= 0)
{
SDL_Rect dstarea;
double phase;
Sint16 x1, y1, x2, y2;
Uint32 keycolor = SDL_MapRGB(surf->format,
0, 255, 0);
Uint32 helicolor = SDL_MapRGB(surf->format,
100, 100, 255);
Uint32 phasecolor = SDL_MapRGB(surf->format,
255, 100, 200);
int i;
dstarea.x = centre_x - lw/2;
dstarea.y = centre_y - lh/2;
dstarea.w = lw;
dstarea.h = lh;
SDL_FillRect(surf, &dstarea, keycolor);
Draw_FillEllipse(surf, centre_x + 40,
centre_y + 10, 60, 30, helicolor);
Draw_FillEllipse(surf, centre_x + 60,
centre_y, 25, 15, keycolor);
dstarea.x = centre_x + 35;
dstarea.y = centre_y - 30;
dstarea.w = 10;
dstarea.h = 15;
SDL_FillRect(surf, &dstarea, helicolor);
dstarea.x = centre_x - 80;
dstarea.y = centre_y - 20;
dstarea.w = 120;
dstarea.h = 10;
SDL_FillRect(surf, &dstarea, helicolor);
dstarea.x = centre_x - 80;
dstarea.y = centre_y - 30;
dstarea.w = 10;
dstarea.h = 30;
SDL_FillRect(surf, &dstarea, helicolor);
for(i = 0; i < 15; i++)
{
phase = M_PI / 180 * (phase_samll + i) ;
x1 = floor(centre_x - 75 –
(15 - i/2)*cos(phase));
y1 = floor(centre_y - 25 +
(15 - i/2)*sin(phase));
x2 = floor(centre_x - 75 +
(15 - i/2)*cos(phase));
y2 = floor(centre_y - 25 –
(15 - i/2)*sin(phase));
Draw_Line(surf, x1, y1, x2, y2,
phasecolor);
}
for(i = 0; i < 15; i++)
{
phase = M_PI / 180 * (phase_big + i) ;
x1 = centre_x + 40;
y1 = centre_y - 30;
x2 = floor(x1 + (60 - i/2)*cos(phase));
y2 = floor(y1 - (7 - i/2));
Draw_Line(surf, x1, y1, x2, y2,
phasecolor);
x2 = floor(x1 - (60 - i/2)*cos(phase));
Draw_Line(surf, x1, y1, x2, y2,
phasecolor);
}
}
}
}
void draw_sky(SDL_Surface *surf, int cloud_cnt)
{
int i;
Sint16 x0, y0;
Uint16 xr, yr;
Uint8 cl;
Draw_FillRect(surf, 0, 0, surf->w, surf->h,
SDL_MapRGB(surf->format,0,200,255));
for(i = 0; i < cloud_cnt; i++)
{
xr = floor((rand()*0.05)/RAND_MAX * surf->w);
yr = floor((rand()*0.05)/RAND_MAX * surf->h);
x0 = xr + floor((rand()*1.0)/RAND_MAX *
(surf->w - 2*xr));
y0 = yr + floor((rand()*1.0)/RAND_MAX *
(surf->h - 2*yr));
cl = 220 + floor((rand()*1.0)/RAND_MAX * 35);
Draw_FillEllipse(surf, x0, y0, xr, yr,
SDL_MapRGB(surf->format, cl, cl, cl));
}
}
int main ( int argc, char** argv )
{
SDL_Surface *background, *temp, *sprites;
int frame_num;
SDL_Rect frame_src, frame_dst, frame_tmp;
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "Unable to init SDL: %s\n",
SDL_GetError() );
return 1;
}
SDL_Surface* screen = SDL_SetVideoMode(scrwidth,
scrheight, scrdepth,
SDL_HWSURFACE|SDL_DOUBLEBUF);
if ( !screen )
{
printf("Unable to set 640x480 video: %s\n",
SDL_GetError());
return 1;
}
background = SDL_CreateRGBSurface(SDL_HWSURFACE |
SDL_DOUBLEBUF, scrwidth, scrheight, scrdepth,
screen->format->Rmask, screen->format->Gmask,
screen->format->Bmask, screen->format->Amask);
temp = SDL_CreateRGBSurface(SDL_HWSURFACE |
SDL_DOUBLEBUF, 200, 80, scrdepth,
screen->format->Rmask, screen->format->Gmask,
screen->format->Bmask, screen->format->Amask);
sprites = SDL_CreateRGBSurface(SDL_HWSURFACE |
SDL_DOUBLEBUF, 200, 80*36, scrdepth,
screen->format->Rmask, screen->format->Gmask,
screen->format->Bmask, screen->format->Amask);
if( !(background && temp && sprites) )
{
printf("Unable to create temporary surfaces: \
%s\n", SDL_GetError());
return 1;
}
SDL_SetColorKey(sprites, SDL_SRCCOLORKEY,
SDL_MapRGB(sprites->format, 0, 255, 0));
for(frame_num = 0; frame_num < 36; frame_num ++)
draw_heli(sprites, 100, 40+80*frame_num,
10*frame_num, 10*frame_num);
draw_sky(background, 250);
SDL_BlitSurface(background, NULL, screen, NULL);
int step = 0;
while (step < (50*60)) /* Примерно 1 минута */
{
frame_tmp.x = 0;
frame_tmp.y = 0;
frame_tmp.w = 200;
frame_tmp.h = 80;
frame_dst.x = -200 + step % (scrwidth +200);
frame_dst.y = scrheight/2 - 100;
frame_dst.w = 200;
frame_dst.h = 80;
SDL_BlitSurface(screen, &frame_dst, temp,
&frame_tmp);
frame_src.x = 0;
frame_src.y = 80*(step % 36);
frame_src.w = 200;
frame_src.h = 80;
SDL_BlitSurface(sprites, &frame_src, screen,
&frame_dst);
step++;
SDL_Flip(screen);
SDL_Delay(20); /* 50 кадров/с */
SDL_BlitSurface(temp, &frame_tmp, screen,
&frame_dst);
}
SDL_Quit();
return 0;
}
ПРИЛОЖЕНИЕ 4
ПРИМЕР ВЫВОДА НА ЭКРАН ГРАФИКА ФУНКЦИИ С ИСПОЛЬЗОВАНИЕМ БИБЛИОТЕКИ SDL
В качестве примера рассмотрим два фрагмента программы с использованием библиотеки SDL_draw, отображающей в окне 640 на 480 пикселей график функции y=ln(|x|), причем xmin = –32, xmax = 32, (MX = MY = 10 пикселей), а экранное положение начала координат – в центре экрана. В первом фрагменте – отображение производится по точкам с шагом ∆x = 0,001, во втором – отрезками с ∆x = 0,1. Инициализация, отображение осей координат, асимптот и т.п. не приводятся.
/* Отображение графика функции по точкам */
/* screen – инициализированная поверхность для рисования 640 на 480 пикселей, */
const Sint16 width=640, heght=480;
double xmin=-32.0, xmax=32.0, ymin, ymax;
double mx=10.0, my=10.0, dx=0.001, x, y;
Sint16 x0scr, y0scr, xscr, yscr;
x0scr=floor(-1*xmin*mx);
/* ymin – неизвестно, так нельзя: y0scr=floor(height+ymin*my);
Используем соглашение о середине экрана: */
y0scr=height/2; /*целочисленное деление */
for(x=xmin;x<=xmax;x+=dx)
{
if((fabs(x)-1e-4)>0)
{ /*исключение нуля */
y=log(fabs(x));
xscr=x0scr+floor(x*mx);
yscr=y0scr-floor(y*my);
/*Точка синим цветом: */
Draw_Pixel(screen, xscr, yscr, 0x0000FF);
}
}
/* Отображение графика функции отрезками */
/* screen – инициализированная поверхность для рисования 640 на 480 пикселей, */
const Sint16 width=640, heght=480;
double xmin=-32.0, xmax=32.0, ymin, ymax;
double mx=10.0, my=10.0, dx=0.1, x1, y1, x2, y2;
Sint16 x0scr, y0scr, xscr1, yscr1, xscr2, yscr2;
x0scr=floor(-1*xmin*mx);
/* ymin – неизвестно, так нельзя:
y0scr=floor(height+ymin*my);
Используем соглашение о середине экрана: */
y0scr=height/2; /*целочисленное деление */
for(x1=xmin, x2=xmin+dx;x1<xmax;x1=x2, x2+=dx)
{
if((fabs(x1)-1e-4)>0 && (fabs(x2)-1e-4)>0)
{
/*исключение нуля */
y1=log(fabs(x1)); /* можно исключить
повтор вычислений*/
y2=log(fabs(x2));
xscr1=x0scr+floor(x1*mx);
yscr1=y0scr-floor(y1*my);
xscr2=x0scr+floor(x2*mx);
yscr2=y0scr-floor(y2*my);
/*Отрезок синим цветом: */
Draw_Line(screen,xscr1,yscr1,
xscr2,yscr2,0x0000FF);
}
}
Полный текст примера попеременного рисования графика данной функции обоим способами выглядит следующим образом (файл main.c, проект создается согласно приложению 2 как консольное приложение Win32 с динамическим подключением библиотек):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <SDL.h>
#include <SDL_draw.h>
#include <SDL_ttf.h>
void draw_by_pixels(SDL_Surface *who_draw);
void draw_by_line(SDL_Surface *who_draw);
int main(int argc, char *argv[])
{
SDL_Surface *screen;
SDL_Event event;
int flag = 0;
if (SDL_Init(SDL_INIT_VIDEO)) /* инициализация SDL */
{ /* При ошибке формируем сообщение и выходим */
fprintf(stderr,"Ошибка в SDL_Init: %s\n",
SDL_GetError());
return 1;
}
atexit(SDL_Quit);
/* После инициализации собственно SDL
и установки atexit(SDL_Quit): */
screen=SDL_SetVideoMode(640,480,32,SDL_ANYFORMAT);
if (!screen)
{
fprintf(stderr,"SDL mode failed: %s\n",
SDL_GetError());
return 1;
}
/* Сначала рисуем по точкам синим цветом*/
draw_by_pixels(screen);
/* цикл ожидания событий */
while(SDL_WaitEvent(&event))
{
if(event.type == SDL_QUIT ||
(event.type == SDL_KEYDOWN &&
event.key.keysym.sym == SDLK_ESCAPE))
{
SDL_Quit();
return 0; /* пусть 0 - нормальное завершение*/
}
if(event.type == SDL_VIDEOEXPOSE)
{ /*чередуем способы перерисовки */
if(flag)
draw_by_line(screen);
else
draw_by_pixels (screen);
flag = !flag;
}
}
fprintf(stderr,"WaitEvent failed: %s\n",
SDL_GetError());
SDL_Quit();
return 2; /* Выход с другим кодом ошибки */
}
void draw_by_pixels(SDL_Surface *who_draw)
{
/* Отображение графика функции по точкам */
const Sint16 width=640, height=480;
double xmin=-32.0, xmax=32.0, ymin, ymax;
double mx=10.0, my=10.0, dx=0.001, x, y;
Sint16 x0scr, y0scr, xscr, yscr;
x0scr=floor(-1*xmin*mx);
/* ymin - неизвестно, так нельзя: y0scr=floor(height+ymin*my);
Используем соглашение о середине экрана: */
y0scr=height/2; /*целочисленное деление */
for(x=xmin;x<=xmax;x+=dx)
{
if((fabs(x)-1e-4)>0)
{ /*исключение нуля */
y=log(fabs(x));
xscr=x0scr+floor(x*mx);
yscr=y0scr-floor(y*my);
/*Точка синим цветом: */
Draw_Pixel(who_draw, xscr, yscr, 0x0000FF);
}
}
}
void draw_by_line(SDL_Surface *who_draw)
{/* Отображение графика функции отрезками */
const Sint16 width=640, height=480;
double xmin=-32.0, xmax=32.0, ymin, ymax;
double mx=10.0, my=10.0, dx=0.1, x1, y1, x2, y2;
Sint16 x0scr, y0scr, xscr1, yscr1, xscr2, yscr2;
x0scr=floor(-1*xmin*mx);
/* ymin - неизвестно, так нельзя: y0scr=floor(height+ymin*my);
Используем соглашение о середине экрана: */
y0scr=height/2; /*целочисленное деление */
for(x1=xmin, x2=xmin+dx;x1<xmax;x1=x2, x2+=dx){
if((fabs(x1)-1e-4)>0 && (fabs(x2)-1e-4)>0){
/*исключение нуля */
y1=log(fabs(x1)); /* можно исключить
повтор вычислений*/
y2=log(fabs(x2));
xscr1=x0scr+floor(x1*mx);
yscr1=y0scr-floor(y1*my);
xscr2=x0scr+floor(x2*mx);
yscr2=y0scr-floor(y2*my);
/*Отрезок красным цветом: */
Draw_Line(who_draw,xscr1,yscr1,
xscr2,yscr2,0xFF0000);
}
}
}
Второй пример – рисование графика функции y=a+b/(x*c+d) на отрезке [xmin; xmax] с использованием максимальной площади экрана. При этом все параметры вводятся пользователем с клавиатуры.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "SDL.h"
#include "SDL_draw.h"
#include "SDL_ttf.h"
void draw_by_pixels(SDL_Surface *who_draw);
void draw_by_line(SDL_Surface *who_draw);
/*Вывод рационального числа с экранным редактированием. Параметры:
где рисовать (поверхность), каким шрифтом, каким цветом,
в какой прямоугольной области можно отображать вводимые данные,
исходное значение (значение по умолчанию) */
double input_double(SDL_Surface *who_draw, TTF_Font *fnt,
SDL_Color color, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,
double defval);
/* Параметры функции и значения по умолчанию*/
double a=0, b=1, c=1, d=0;
const Sint16 width=640, height=480;
double xmin=-32.0, xmax=32.0, ymin, ymax;
double mx=10.0, my=10.0;
Sint16 x0scr, y0scr;
int main(int argc, char *argv[])
{
SDL_Surface *screen;
SDL_Event event;
TTF_Font *fnt;
/* Для вывода текста */
SDL_Color text_color;
SDL_Rect dest;
SDL_Surface *text_surface = NULL;
char txtbuf[100];
int flag = 0; /* очередность использования методов
рисования*/
setbuf(stderr, NULL); /* Отмена буферизации stderr
для гарантированного сохранения сообщений об ошибках*/
if (SDL_Init(SDL_INIT_VIDEO)) /* инициализация SDL */
{ /* При ошибке формируем сообщение и выходим */
fprintf(stderr,"Ошибка в SDL_Init: %s\n",
SDL_GetError());
return 1;
}
if (TTF_Init()) /* инициализация SDL_ttf */
{ /* При ошибке формируем сообщение и выходим */
fprintf(stderr,"Ошибка в TTF_Init: %s\n",
SDL_GetError());
return 1;
}
atexit(SDL_Quit);
/* После инициализации собственно SDL
и установки atexit(SDL_Quit): */
screen=SDL_SetVideoMode(640,480,32,SDL_ANYFORMAT);
if (!screen)
{
fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError());
return 1;
}
/* Первый параметр должен быть полностью
на одной строке вместе с кавычками! */
SDL_WM_SetCaption("Построение
графика функции с
использованием SDL.
Пример №2",NULL);
/* Загружаем шрифт размером sz пунктов*/
fnt = TTF_OpenFont("ClearSans-Thin.ttf", 30);
printf("fnt = %p\n", fnt);
if(!fnt)
return 3;
/* Цвета для ввода параметров (ярко-зеленый): */
text_color.r = 0; text_color.g = 255; text_color.b = 0;
/* Ввод параметров: */
dest.x = 0; dest.y = 0;
text_surface = TTF_RenderUTF8_Solid(fnt, "a=",
text_color);
if(text_surface)
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
SDL_Flip(screen);
a = input_double(screen, fnt, text_color,
dest.x+dest.w, dest.y,
dest.x+dest.w + 200, dest.y+dest.h, a);
dest.x = 0; dest.y = dest.y + dest.h;
text_surface = TTF_RenderUTF8_Solid(fnt, "b=",
text_color);
if(text_surface)
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
SDL_Flip(screen);
b = input_double(screen, fnt, text_color,
dest.x+dest.w, dest.y,
dest.x+dest.w + 200, dest.y+dest.h, b);
dest.x = 0; dest.y = dest.y + dest.h;
text_surface = TTF_RenderUTF8_Solid(fnt, "c=",
text_color);
if(text_surface)
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
SDL_Flip(screen);
c = input_double(screen, fnt, text_color,
dest.x+dest.w, dest.y,
dest.x+dest.w + 200, dest.y+dest.h, c);
dest.x = 0; dest.y = dest.y + dest.h;
text_surface = TTF_RenderUTF8_Solid(fnt, "d=",
text_color);
if(text_surface)
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
printf("before input_double(), d=%lf\n",d);
SDL_Flip(screen);
d = input_double(screen, fnt, text_color,
dest.x+dest.w, dest.y,
dest.x+dest.w + 200, dest.y+dest.h, d);
dest.x = 0; dest.y = dest.y + dest.h;
text_surface = TTF_RenderUTF8_Solid(fnt, "xmin=",
text_color);
if(text_surface)
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
SDL_Flip(screen);
xmin = input_double(screen, fnt, text_color,
dest.x+dest.w, dest.y,
dest.x+dest.w + 200, dest.y+dest.h, xmin);
dest.x = 0; dest.y = dest.y + dest.h;
text_surface = TTF_RenderUTF8_Solid(fnt, "xmax=",
text_color);
if(text_surface)
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
SDL_Flip(screen);
xmax = input_double(screen, fnt, text_color,
dest.x+dest.w, dest.y,
dest.x+dest.w + 200, dest.y+dest.h, xmax);
/* Расчет масштабных коэффициентов:*/
mx = (1.0 * width) / fabs(xmax-xmin);
dest.x = 0; dest.y = dest.y + dest.h;
memset(txtbuf,0,100);
sprintf(txtbuf,"mx = %lf",mx);
text_surface = TTF_RenderUTF8_Solid(fnt, txtbuf,
text_color);
if(text_surface)
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
dest.x = 0; dest.y = dest.y + dest.h;
memset(txtbuf,0,100);
sprintf(txtbuf,"my = %lf",my);
text_surface = TTF_RenderUTF8_Solid(fnt, txtbuf,
text_color);
if(text_surface)
{
SDL_BlitSurface(text_surface, NULL, screen,
&dest);
SDL_FreeSurface(text_surface);
text_surface = NULL;
}
/* Сначала рисуем по точкам синим цветом*/
draw_by_pixels(screen);
SDL_Flip(screen);
/* цикл ожидания событий */
while(SDL_WaitEvent(&event))
{
if(event.type == SDL_QUIT ||
(event.type == SDL_KEYDOWN &&
event.key.keysym.sym == SDLK_ESCAPE))
{
TTF_CloseFont(fnt); /* Закрываем шрифт */
SDL_Quit();
return 0; /* пусть 0 - нормальное завершение*/
}
if(event.type == SDL_VIDEOEXPOSE)
{ /*чередуем способы перерисовки */
if(flag)
draw_by_line(screen);
else
draw_by_pixels(screen);
flag = !flag;
}
}
fprintf(stderr,"WaitEvent failed: %s\n",
SDL_GetError());
SDL_Quit();
return 2; /* Выход с другим кодом ошибки */
}
/* Отображение графика функции по точкам */
void draw_by_pixels(SDL_Surface *who_draw)
{
double dx=0.001, x, y;
Sint16 xscr, yscr;
x0scr=floor(-1*xmin*mx);
/* ymin - неизвестно, так нельзя:
y0scr=floor(height+ymin*my);
Используем соглашение о середине экрана: */
y0scr=height/2; /*целочисленное деление */
for(x=xmin; x<=xmax; x+=dx){
if((fabs(x)-1e-4)>0){ /*исключение нуля */
y=a+b/(c*x+d);
xscr=x0scr+floor(x*mx);
yscr=y0scr-floor(y*my);
/* рисуем синим цветом только точки,
помещающиеся на поверхности, иначе будет ошибка*/
if(0<=xscr && xscr<width &&
0<=yscr && yscr < height)
Draw_Pixel(who_draw, xscr, yscr, 0x0000FF);
}
}
}
/* Отображение графика функции отрезками */
void draw_by_line(SDL_Surface *who_draw)
{
double dx=0.1, x1, y1, x2, y2;
Sint16 xscr1, yscr1, xscr2, yscr2;
x0scr=floor(-1*xmin*mx);
/* ymin - неизвестно, так нельзя:
y0scr=floor(height+ymin*my);
Используем соглашение о середине экрана: */
y0scr=height/2; /*целочисленное деление */
for(x1=xmin, x2=xmin+dx;x1<xmax;x1=x2, x2+=dx)
{
if((fabs(x1)-1e-4)>0 && (fabs(x2)-1e-4)>0)
{ /*исключение нуля */
y1=a+b/(c*x1+d); /* можно исключить повтор
вычислений*/
y2=a+b/(c*x2+d);
xscr1=x0scr+floor(x1*mx);
yscr1=y0scr-floor(y1*my);
xscr2=x0scr+floor(x2*mx);
yscr2=y0scr-floor(y2*my);
/*Отрезок красным цветом (для отрезков больше проверок:*/
if( 0<=xscr1 && xscr1<width &&
0<=yscr1 && yscr1 < height &&
0<=xscr2 && xscr2<width &&
0<=yscr2 && yscr2 < height)
Draw_Line(who_draw,xscr1,yscr1,xscr2,yscr2,
0xFF0000);
}
}
}
/* Функция вывода на поверхность одиночного символа заданным
шрифтом в указанных координатах заданным цветом */
void OutSymbolFntColorXY(SDL_Surface *screen,
TTF_Font *fnt, SDL_Color clr,
Sint16 x, Sint16 y, int symbolcode)
{ /* Такая реализация корректно работает только с символами,
код которых в utf8 задается 1 байтом. То есть, только
символами ASCII, имеющими код от 0 до 127. Этого достаточно
для записи вещественных чисел. */
SDL_Rect dest; dest.x = x; dest.y = y;
сhar s[2]; s[0]=symbolcode; s[1]='\0';
SDL_Surface *TextSurface = TTF_RenderUTF8_Solid
(fnt, s, clr);
SDL_BlitSurface(TextSurface, NULL, screen,
&dest);
SDL_FreeSurface(TextSurface); /* Освобождаем
поверхность */
/* Обновляем только измененный участок целевой поверхности:*/
SDL_UpdateRect(screen,dest.x,dest.y,
dest.w,dest.h);
}
/* Функция ввода вещественного числа. Параметры см. выше при объявлении.*/
double input_double(SDL_Surface *who_draw,
TTF_Font *fnt, SDL_Color color,
Sint16 x1, Sint16 y1,
Sint16 x2, Sint16 y2, double defval)
{
#define WHOLE 7 /* кол-во знаков под целую часть мантиссы */
#define FRACTIONAL 6 /* кол-во знаков под дробную часть мантиссы */
#define EXP 3 /* кол-во знаков под степень */
#define E 308 /* максимальное значение степени */
/* Символьный буфер для ввода и редактирования: размер исходя
из заданного числа знаков, а также места по одному байту
для возможного знака мантиссы и показателя, десятичной точки
в мантиссе, разделителя мантиссы и показателя и завершающего
NULL-терминатора.*/
char s[WHOLE+FRACTIONAL+EXP+5];
/* Все символы в нем делаем нулевыми */
memset(s,0,WHOLE+FRACTIONAL+EXP+5);
/* количество и положение различных символов в буфере */
int _kol=-1, _whole=0, _fractional=0, _exp=0,
_pointf=0,_minusf=0,_ef=0,_minusEf=0;
/* Координаты рабочей области */
Sint16 wrk_x1=x1, x=wrk_x1, wrk_y1=y1, y=wrk_y1;
SDL_Event event;
int i;
while ( SDL_WaitEvent(&event) ){
if (event.type == SDL_QUIT){
/* По идее, надо вернуть его обратно в очередь
и пусть обрабатывает основная программа...
В данном примере не реализовано. */
break;
}
if (event.type == SDL_KEYDOWN)
{ /*Если нажата клавиша...*/
if((!_pointf && _whole<WHOLE &&
!_fractional && !_ef)||
(_pointf && _fractional<FRACTIONAL
&& !_ef)||(_ef && _exp<EXP))
{/*При соблюдении условий смотрим, не цифра ли нажата...*/
if(event.key.keysym.sym >= SDLK_0 &&
event.key.keysym.sym <=SDLK_9)
{/* Цифровую клавиатуру пока игнорируем */
char digitsym =
(char) event.key.keysym.sym;
OutSymbolFntColorXY(who_draw, fnt, color,
x,y, digitsym);
x+=20; s[++_kol]=digitsym;
if(!_pointf && _whole<WHOLE
&& !_fractional && !_ef)
_whole=_whole+1;
else
if(_pointf && _fractional<FRACTIONAL
&& !_ef)
_fractional=_fractional+1;
else
_exp=_exp+1;
}
}
if ((event.key.keysym.sym==SDLK_BACKSPACE)
&&(x!=x1))
{
if(_whole<=WHOLE && !_pointf && !_ef
&& _whole>0 && !_fractional)
_whole=_whole-1; /* удаление цифры
из целой части */
else
if(_pointf && _fractional>0 &&
_fractional<=FRACTIONAL &&
!_ef && _whole)
_fractional=_fractional-1; /*удаление
цифры из дробной части мантиссы */
else
if(!_whole && _minusf)
_minusf=0; /* удаление минуса перед
целой частью*/
else
if (_pointf && !_fractional &&
!_ef && _whole)
_pointf=0; /*удаление точки*/
else
if (_ef && !_exp && !_minusEf)
_ef=0; /*удаление символа exp*/
else
if (_ef && !_exp && _minusEf)
_minusEf=0; /* удаление минуса
после exp*/
else
if (_ef && _exp<=EXP)
_exp=_exp-1; /*удаление цифры
в степени*/
/* Смещаемся на 20 пикселей влево (одно "знакоместо")*/
x-=20;
/* Затираем знакоместо черным цветом */
Draw_FillRect(who_draw,x,y,20,42,0);
/* Обновляем экран */
SDL_UpdateRect(who_draw,0,0,width,height);
_kol=_kol-1; /* Уменьшаем число символов */
continue; /*Продолжаем ожидание событий */
}
if(event.key.keysym.sym==SDLK_MINUS &&
((!_minusf && !_whole && !_ef) ||
(!_minusEf && _ef && !_exp)))
{
OutSymbolFntColorXY(who_draw, fnt, color,
x,y,SDLK_MINUS);
x+=20; s[++_kol]=45;
if (!_minusf && !_whole && !_ef)
_minusf=1;
else
_minusEf=1;
continue;
}
if (event.key.keysym.sym==SDLK_PERIOD &&
!*pointf && !_ef)
{
if (!_whole)
{
s[++_kol]=48; _whole=1;
OutSymbolFntColorXY(who_draw,fnt,color,
x,y,SDLK_0);
}
s[++_kol]=46;
OutSymbolFntColorXY(who_draw, fnt, color,
x,y,SDLK_PERIOD);
x+=20;
_pointf=1;
continue;
}
if (event.key.keysym.sym==SDLK_e && !_ef)
{
OutSymbolFntColorXY(who_draw, fnt, color,
x,y,SDLK_e);
x+=20; s[++_kol]=101; _ef=1;
continue;
}
if (event.key.keysym.sym==SDLK_RETURN &&
_kol!=-1)
{ /* Завершение ввода */
double tmp;
s[_kol+1]='\0';
sscanf(s,"%lf",&tmp); /*Нет проверки ввода! */
return tmp;
}
if (event.key.keysym.sym == SDLK_ESCAPE)
/* Будет возвращено значение по умолчанию */
break;
} /* Конец обработки события SDL_KEYDOWN */
} /* Конец цикла обработки событий */
return defval;
} /* конец тела функции input_double */
ПРИЛОЖЕНИЕ 5
ЛИНЕЙНЫЙ ОДНОСВЯЗНЫЙ СПИСОК
Пример организации односвязного линейного списка
#include <iostream.h>
#include <conio.h>
typedef int DataType;
class Element //класс, описывающий элемент односвязного списка
{ //закрытые члены класса
DataType Info; // поле данных
Element * Next; // указатель на следующий элемент
public: //открытые члены класса
Element() //конструктор элемента
{
Next = NULL;
}
};
class List // класс, описывающий односвязный список
{ //закрытые члены класса
Element *Begin, *End; //указатели на первый и последний
//элементы списка
public: //открытые члены класса
List() //конструктор списка
{
Begin = End = NULL;
}
~List() //деструктор списка
{
Element *Rex; //вспомогательный указатель
While (Begin) // пока список не пуст
{
Rex = Begin; // запоминаем адрес первого элемента
Begin = Begin->Next; // переставляем указатель
// начала на следующий элемент списка
delete Rex; // удаляем первый элемент списка
}
}
void Add(void) //метод добавления элемента в конец списка
{
Element *Rex = new Element; //выделяем память
//под новый элемент
cout << "\n\tADD:\n";
cout << "\t\tEnter Info = ";
cin >> Rex->Info; // вводим данные
cout << "\tPress any key...\n\n";
if (Begin == NULL) //если список пуст
Begin = Rex; //добавляемый элемент является первым
else //иначе
End->Next = Rex; //добавляем его в конец списка
End = Rex; //добавленный элемент является последним
}
void Show (void) //печать списка
{
Element *Rex;
cout << "\n\tSHOW:\n";
if (!Begin) //если очередь пуста
{
cout << "\t\tList is empty!\n";
cout << "\tPress any key...\n\n";
return;
}
cout << "\t\tInfo\n";
Rex = Begin; //устанавливаем указатель текущего
//элемента на начало списка
while (Rex) //пока не конец списка
{ //выводим значение поля данных
cout << "\t\t\t"<< Rex->Info << endl;
Rex = Rex->Next; //переходим к следующему
}
cout << "\tPress any key...\n\n";
}
};
main()
{
List L;
int key = 0;
do
{
cout << "MENU:\n\n";
cout << "\t1 – ADD\n\t2 – SHOW\n";
cout << "\t3 – Exit\n\n";
cout << "Press any key...\n";
key = getchar();
switch(key)
{
case 49: L.Add(); break;
case 50: L.Show(); break;
}
}
while(key!=51);
return 0;
}
ПРИЛОЖЕНИЕ 6
ОЧЕРЕДЬ В ЦИКЛИЧЕСКОМ МАССИВЕ
#define MAXLENGTH 10
typedef int T;
class Queue
{
int front, rear; //индексы головы и хвоста
T elements[MAXLENGTH]; //массив для хранения элементов
public:
Queue () {front=0; rear=MAXLENGTH-1;}
int Empty (void); //проверка на пустоту
int Full (void); //проверка на полноту заполнения
T Front (void); //неразрушающее чтение элемента
void EnQueue (T x); //добавление элемента в очередь
T DeQueue (void); //извлечение элемента из очереди
};
int Queue::Empty(void)
{
if ((rear+1)%MAXLENGTH == front)
return 1;
return 0;
}
int Queue::Full(void)
{
if ((rear+2)%MAXLENGTH == front)
return 1;
return 0;
}
T Queue::Front (void)
{
return elements[front];
}
void Queue::EnQueue (T x)
{
rear = (rear+1)%MAXLENGTH;
elements[rear] = x;
}
T Queue::DeQueue (void)
{
int temp = front;
front = (front+1)%MAXLENGTH;
return elements[temp];
}