Программирование баз данных
Особенностью разработки доступа к базам данных при помощи C++Builder является полностью объектный визуальный подход. Вторая особенность заключается в том, что доступ к разным базам данных (dBase, Paradox, Oracle и другим) происходит совершенно унифицированно. Эта дает определенные преимущества по сравнению с таким мощным средством разработки баз данных как Visual FoxPro. Интерфейсом между приложением и базами данных служит BDE - Borland Database Engine, т.е Механизм База данных Borland. Он позволяет не только осуществлять доступ к локальным базам данных, но и осуществлять доступ к данным по типу клиент-сервер. Одной из особенностей C++Builder является то,что доступ к базам данных осуществляется одинаково как на стадии разработки, так и на стадии исполнения. Для разработки используется трех ступенчатая модель. Каждой ступени соответствует своя компонента (класс). TDBGrid - отображает в окне область редактирования (по типу команды Browse (Grid) в FoxPro) TdataSource - служит интерфейсом между TDBEdit и нижней компонентой. TTable - содержит все записи таблици. На более низком уровне работают драйвера BDE, осуществляющие непосредственный обмен с хранимыми данными. Расмотрим более подробно описанные выше компоненты.
Источник данных (TDataSource). Основные свойства. AutoEdit - разрешает или запрещает редактирование записей (False или True). DataSet - определяет имя конкретного набора данных, таблицы или запроса. Например Table1. Можно переключаться с одного набора данных на другой непосредственно во время выполнения программы. Name - определяет название данной компоненты. Например DataSource. С данной компонентой связаны три события OnDataChange, OnStateChange, OnUpdateData.
Таблица (TTable). Основные свойства.
Active - разрешает или запрещает просмотр данных. DatabaseName - псевдоним базы данных и путь к каталогу, где база данных содержится. Name - псевдоним таблицы. TableName - конкретное имя таблицы (в указанном каталоге). Exclusive - разрешает или запрещает другому приложению обращаться к таблице. IndexFiles - выбор индексного файла для таблицы. IndexName - правило сортировки данных в индексе. Filter - установка фильтра. MasterFields и MasterSource - для образования связей между двумя таблицами. Для данной компоненты определены стандартные методы используемые другими системами управления баз данных: Locate, Lookup, Append, Insert, Next, MoveBye и другие.
Отображение данных (TDBGrid). Некоторые свойства. DataSource - совпадает со свойством Name компоненты TDataSource. В результате имеем следующую связку:
TDBGrid TDataSource TTable ----------------------------------------------------------------------------------------- DataSource <--> Name-DataSet <--> Name -DatabaseName-TableName Такая связка обеспечит в окне редактирования появления записей таблицы имеющей имя TableName (см.ниже). Другие свойства данной компоненты тривиальны - они определяют положение окна редактирования, цветовую гамму, размера окна, шрифты и т.п. Еще одна компонента часто используется в связи с работой с базами данных. Запросы (Tquery). Данная компонента понадобится вам, если у вас возникнет необходимость пользоваться командами SQL-языка. Основные свойства. Active - разрешает или запрещает просмотр данных. DatabaseName - содержит псевдоним базы данных или полный путь к каталогу, где эта база данных находится. SQL - используется для ввода команды SQL. Синтаксис этих команд является стандартом и с ним можно познакомиться в любом руководстве по СУБД (например FoxPro). RequestLive - разрешает или запрещает BDE возращать набор данных в любом случае. Приступаем теперь к разбору конкретного примера. Пример очень прост. При запуске программы появляется форма. На форме имеется окно редактирования таблицы, кнопка "Выход", кнопка "Добавить", кнопка "Удалить". Таблица содержит данные о людях: ФИО, выданная сумма, дата выдачи. У вас будет имется возможность редактировать таблицу, добавлять и удалять записи. При запуске программа проверяет наличие таблицы в указанном каталоге и при необходимости создает и индексирует эту таблицу.
Поместим на форму три кнопки, TDBGrid (для просмотра таблицы), TTable, TDataSource.. Пусть наша таблица будет находится в каталоге c:\baza\ и будет иметь имя 'proba' Заполним свойства трех компонент основных компонент: TTable: DatabaseName=c:\baza\ Name=Table1 TableType=ttDBase TableName=proba IndexName=proba TDataSource: DataSet=Table1 Name=DataSource1 TDBGrid: DataSource=DataSource1 Все остальные свойства можно оставить по умолчанию и менять по ходу работы над программой. Приведем текст модуля Unit1.cpp содержащего основные исполняемые функции.
//--------------------------------------------------------------------------- #include <vcl\vcl.h> #pragma hdrstop
#include "Unit1.h" //--------------------------------------------------------------------------- #pragma link "Grids" #pragma resource "*.dfm" TForm1 *Form1; char * baza="proba.dbf"; char * baza1="proba"; //--------------------------------------------------------------------------- //Конструктор __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { HANDLE handle; //пытаемся открыть таблицу как обычный файл handle=CreateFile(baza, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL); if(handle!=INVALID_HANDLE_VALUE) { //файл есть и закроем CloseHandle(handle); } else { //файла нет //создаем таблицу Table1->FieldDefs->Clear(); Table1->FieldDefs->Add("Name", ftString, 20, true); Table1->FieldDefs->Add("Zarpl", ftFloat, 0, true); Table1->FieldDefs->Add("Data", ftDate, 0, true); //теперь создаем индексный файл Table1->IndexDefs->Clear(); TIndexOptions MyIndexOptions; MyIndexOptions << ixPrimary << ixUnique; Table1->IndexDefs->Add(baza1, "Data", MyIndexOptions); Table1->CreateTable(); } //здесь открыть таблицу Table1->Active = true; //активизировать индекс Table1->OpenIndexFile("proba.MDX"); } //---------------------------------------------- //Деструктор __fastcall TForm1::~TForm1() { //закрыть таблицу Table1->Active = false; } //--------------------------------------------------------------------------- //выход void __fastcall TForm1::Button1Click(TObject *Sender) { //метод Close закрывает форму и вызывает деструктор Close(); } //--------------------------------------------------------------------------- //кнопка "добавить запись" void __fastcall TForm1::Button3Click(TObject *Sender) { Table1->Append(); } //---------------------------------------------------------------------------
//кнопка "удалить запись" void __fastcall TForm1::Button2Click(TObject *Sender) { Table1->Delete(); }
Прокоментируем вышеприведенный текст. Отметим одну интересную возможность C++Builder. Он может одновременно работать как с библиотекой объектов с которой мы до сих пор работали так и непосредственно с функциями API. В нашей программе мы демонстрируем эту возможность: в конструкторе пытаемся открыть файл (функция CreateFile). Если открытие не удается, выполняется часть кода создающий таблицу и индексный файл. Ниже представлено окно работы нашей программы.
ПАКЕТЫ
Существенную роль в разработке приложений на языке C++Builder 3 и выше играют пакеты(packages), которые представляют собой библиотеки динамической компоновки, содержащие компоненты C++Builder из библиотеки визуальных компонент(VCL). Применение пакетов позволяет умсеньшить размеры исполняемых (.EXE- файлов, однако в таком случае вместе с программой необходимо распространять эти библиотеки. Существует несколько видов пакетов- выделим из них пакеты времени выполнения(ПВВ). Пакеты данного вида используются: когда приложение выполняется. ПВВ могут связываться статически и динамически. При статическом связывании образуется выполняемый файл, для которого не нужны библиотеки с расширением (.BPL). Связывание в пакет динамически ведет к тому, что библиотеки.BPL должны распространяться с приложением. В C++Builder 3 и выше в меню Project/Options/Packages есть опция Build with runtime packages. Если флажок возле этой опции установлен, то приложение необходимо распространять вместе с библиотеками.BPL, если флажок не установлен, то получается полностью скомпилированный выполняемы файл. Динамическое связывание применяется при конструировании приложений, состоящих из большого количества выполняемых файлов. Заключение
В представленном учебном пособии были рассмотрены некоторые вопросы программирования на языке С++ и C++Builder. Для углубленного изучения языка программирования Си необходимо изучить литературу, приведенную ниже. Литература:
1. Уэйт М., Прата С., Мартин Д. Язык Си. Руководство для начинающих. - М.: Мир, 1988.- 512 с. 2. Страуструп Б. Язык программирования СИ++. - М.: Радио и связь,1991.352с. 3. Бруно Бабэ Просто и ясно о BORLAND С++.-М.:БИНОМ,1995.-400с. 4.Бочков С.О., Субботин Д.М. Язык программирования Си для персонального компьютера. -М.: Радио и связь,1990.-384с. 5. Ричард Вайнер, Льюс Пинсон С++ изнутри. - Киев: ДиаСофт,1993.-304с. 6. Лукас П. С++ под рукой. - Киев:ДиаСофт, 1993.-176с. 7. Стефан Дьюхарст, Кэти Старк Программирование на С++.- Киев: ДиаСофт, 1993.-272с. 8. Белецкий Я. Турбо Си++: Новая разработка. - М.: Машиностроение, 1994. -400с. 9. Том Сван. Программирование для WINDOWS в BORLAND C++.-М.:БИНОМ, 1995.-400с 10. Шилд Г. Программирование на С и С++ для WINDOWS 95.-К.:Торгово- издательское бюро BHV, 1996.-400с. 11. Круглински Дэвид. Основы Visual C++.-М.:Русская Редакция ТОО Channel Trading Ltd, 1997.-696с. 12. Шилдт Герберт. MFC: основы программирования. - К.: Издательская группа BHV, 1997.-560с. 13. Д. Кнут. Искусство программирования для ЭВМ. Т. 3. Сортировка и поиск. - М.: Мир, 1978. 14. Б. Керниган, Д. Ритчи. Язык программирования Си. - М.: Финансы и статистика, 1992. 15. Р.Андерсон. Доказательство правильности программ. М.: Мир, 1984. 16. Шилд Герберт. Самоучитель С++.-BHV.-С.-Петербург.,1997.-512с. 17. Шамис В.А. Borland C++ Builder. Программирование на С+ без проблем М.: Нолидж, 1997.-266с. 18. Елманова Н.З., Кошель С.П. Введение в Borland C++ Builder.-М.: Диалог. - МИФИ, 1997.-272с. 19. Рейсдорф К. Освой самостоятельно Borland C++Builder. М.: БИНОМ, 1998.-702с. 20. Рамодин Д. Создание приложений в среде Borland C++Builder, Мир ПК №10,11,12-1997г. 21. Калверт Чарльз C++Builder. Энциклопедия пользователя. 22.Оузьер Д., Гробман С., Батсон С. Delphi2. Освой самостоятельно.- М.:Восточная Книжная Компания,1997.-624с. 23. Пирогов В.Ю. Программирование на языке ассемблера для операционных систем MS DOS и Windows, 1999, -550c. 24. Калверт Чарльз и др. Borland C++Builder 3.Самоучитель.-К:ДиаСофт, 1999.-272с. 25. Московские олимпиады по программированию,М.-1988.-208с. ПРИЛОЖЕНИЕ N1
Задача N1. Определить, какая из точек плоскости A(x1,y1), B(x2,y2), C(x3,y3) расположена ближе к началу координат. #include<stdio.h> #include<conio.h> #include<math.h> int main(void) { char *n[30]; int x1,y1,x2,y2,x3,y3,p1,p2,p3,k; clrscr(); printf("Введите координаты первой точки\n"); printf("x1=",&x1); scanf("%d",&x1); printf("y1=",&y1); scanf("%d",&y1); printf("Введите координаты второй точки\n"); printf("x2=",x2); scanf("%d",&x2); printf("y2=",y2); scanf("%d",&y2); printf("Введите координаты третьей точки\n"); printf("x3=",x3); scanf("%d",&x3); printf("y3=",y3); scanf("%d",&y3); p1=sqrt(x1*x1+y1*y1); p2=sqrt(x2*x2+y2*y2); p3=sqrt(x3*x3+y3*y3); k=p1; *n="первая"; if(k>p2) { k=p2;*n="вторая"; } if(k>p3) { k=p3;*n="третья"; } printf("%s точка ближе всех к началу координат \n",*n);
getch(); return(0); } Задача N2. Можно ли раменять 25 рублей 9 купюрами достоинством в 1, 3 и 5 рублей? #include<stdio.h> int main(void) { int x,y,s,z; s=0; for(x=1;x<=10;x++) { for(y=1;y<=10;y++) { for(z=1;z<=10;z++) { if ((x+3*y+5*z==25) & (x+y+z==9)) { printf("Можно %d-1p, %d-3p, %d-5p\n",x,y,z); s=1; } } } } if (s==0) { printf("25 рублей нельзя разменять 9 купюрами в 1р,3p,5p");} return(0); } Задача N3. Определить в одномерном числовом массиве число соседств из двух чисел разного знака. #include<stdio.h> int main(void) { int i,j,s,n,a[10]; printf("Введите эл-ты массива \n"); for (i=1;i<=10;++i) scanf("%d",&a[i]); s=0; for (i=1;i<=9;++i) { if (a[i]* a[i+1]<0) s=s+1; } printf ("Число эл-тов разного знака =%d \n",s); } Задача N4. Определить, является ли одномерный числовой массив упорядоченным по убыванию. #include<stdio.h> #include<dos.h> int main(void) { int i,j=0,n=10,s=0; int a[10]; printf("Введите элементы массива\n"); for (i=1;i<=n;++i) {scanf("%d",&a[i]);} for (i=1;i<=n-1;++i) { if (a[i]<a[i+1]) s=1;} if (s==1) {printf ("Массив не упорядочен по убыванию \n");} else {printf ("Массив упорядочен по убыванию \n");} } Задача N5. Найти сумму чисел, обратных квадратам первых 100 натуральных чисел. #include<stdio.h> #include<dos.h> int main(void) { float i,s=0; printf ("-----------------------------\n"); for (i=1;i<=100;i++) { s=s+1/(i*i);} printf ("Сумма чисел равна %f\n",s); delay(5000); } Задача N6. Дана точка А с координатами x,y. Определить в каком квадранте координатной оси она расположена. #include<stdio.h> #include<conio.h> #include<stdlib.h> int main(void) { char xs[10],ys[10]; int x,y; clrscr(); printf ("Введите координаты т.А \n"); gets(xs); gets(ys); x=atoi(xs); y=atoi(ys); if (x==0) printf ("Точка на оси Х\n"); if (y==0) printf ("Точка на оси Y\n"); if (x>0 && y>0) printf ("Точка А в 1-й четверти \n"); if (x<0 && y>0) printf ("Точка А в 2-й четверти \n"); if (x<0 && y<0) printf ("Точка А в 3-й четверти \n"); if (x>0 && y<0) printf ("Точка А в 4-й четверти \n"); getch(); } Задача N7. Вы забрели в сад, в котором три калитки и решили пройти через них не пропустив ни одной. Набрав некоторое количество яблок, вы отдали половину всех яблок и еще поляблока человеку у первой калитки, половину того что осталось и еще поляблока человеку у второй калитки, а половину всех оставшихся яблок и еще поляблока человеку у третей калитки и при этом не разрезали ни одного яблока. Сколько яблок вы должны набрать в саду чтоб вынести X яблок? #include<stdio.h> int main(void) { int k,n,i,x; printf("\n Задача про яблоки.\n"); printf("Введите количество яблок,которое нужно вынести\n"); scanf("%d",&k); n=k; for (i=1;i<=3;i++) { x=2*k+1; k=x; } printf("%d нужно взять\n",k); return(0); } Задача N8. Написать программу вычисления числа сочетаний из m по n(формула m!\n!*(m-n)! при m>=n). #include<stdio.h> int main(void) { int i,m,n; float f1=1,f2=1,f3=1,c; printf ("Введите m: "); scanf ("%d",&m); for (i=1;i<=m;++i) { f1=f1*i; } printf ("Введите n: "); scanf ("%d",&n); for (i=1;i<=n;++i) { f2=f2*i; } if (m>=n) { for (i=1;i<=m-n;++i) { f3=f3*i; } c=f1/(f2*f3); printf ("c=%f \n",c); } else printf (" m должно быть больше, либо равно n! \n"); } Задача N9. Слова и фразы, переходящие в себя при "аккустическом" отображении называются палиндромами. Написать программу определяющую является слово палиндром или нет. #include<stdio.h> #include<conio.h> #include<string.h> int main(void) { char A[80],B[80]; int i,L; clrscr(); printf ("Введите слово A: "); scanf ("%s",&A); L=strlen(A); for (i=0;i<=L;++i) B[i]=A[L-i-1]; B[L]='\0'; i=strcmpi(A,B); if (i==0) printf ("Слово-полиндром \n"); else printf ("Слово-не полиндром \n"); getch(); } Задача N10. Определить находится ли точка M(x,y) внутри верхней части единичного круга с центром в начале координат. #include<stdio.h> int main(void) { float x,y,z; printf("Введите координаты точки\n"); scanf("%f",&x); scanf("%f",&y); z=x*x+y*y; printf("%f %f\n",z,y); if ((z<=1)&&(y>0)) printf("Точка принадлежит верхней части единичного круга\n"); else printf("Точка не принадлежит верхней части единичного круга\n"); return(0); } Задача N11. Составить программу для решения квадратного уравнения Ax^2+Bx+C=0. #include<stdio.h> #include<math.h> #include<dos.h> int main(void) { int i,d,a,b,c; float x1,x2; printf("\n Решение квадратного уравнения\n"); printf("Ведите коэффициенты уравнения a,b,c\n"); printf("a=");scanf("%d",&a); printf("b=");scanf("%d",&b); printf("c="); scanf("%d",&c); d=b*b-4*a*c; printf("d=%d\n",d); if(d<0) printf("корней нет\n"); else { if(d>0) { x1=(-b+sqrt(d))/2*a; x2=(-b-sqrt(d))/2*a; printf("корни уравнения x1=%f x2=%f\n",x1,x2);} else { x1=(-b)/(2*a); printf("корень уравнения x1=%f \n",x1); } } delay(5000); return(0); } Задача N12. Составить программу, позволяющую узнать войдет ли открытка размерами A,B в конверт размерами X,Y. #include<stdio.h> #include<dos.h> int main() { int t,a,b,x,y; printf("Введите размер a открытки:\n"); scanf("%d",&a); printf("Введите размер b открытки:\n"); scanf("%d",&b); printf("Введите размер x конверта:\n"); scanf("%d",&x); printf("Введите размер y конверта:\n"); scanf("%d",&y); if(b>a) {t=a;a=b;b=t;} if(y>x) {t=x;x=y;y=t;} if ((x>=a) &(y>=b)) printf("Открытка войдет в конверт.\n"); else printf("Открытка не войдет в конверт.\n"); delay(3500); return 0; } Задача N13. Существует ли четырехзначное натуральное число, куб суммы цифр которого равен ему самому? #include <stdio.h> #include <math.h> #include<conio.h> int main(void) { int j1,j2,j3,j4; float p,t,q=3; for(j1=1;j1<=9;j1++) { for(j2=1;j2<=9;j2++) { for(j3=1;j3<=9;j3++) { for(j4=1;j4<=9;j4++) { p=(j1*1000+j2*100+j3*10+j4); t=pow((j1+j2+j3+j4),q); if (p==t) { printf("Четырехзначное число, равное кубу суммы своих цифр\n"); printf("%f\n",p); } } } } } getch(); return(0); } Задача N14. Пара носков стоит 1.05 руб. связка -12 пар стоит 10.25 руб. а коробка - 12 связок стоит 114 руб. Составить программу, которая по числу N пар носков вычисляет числа n1, n2, n3 коробок, связок и пар носков, которые следует купить. Пояснение - вместо 11 пар носков покупать связку - это дешевле. Оптимальная покупка без излишков находится следующим образом:
n1=n\144: m=n-n1*144 n2=m\12: n3=m-n2*12
Удешевить ее можно лишь двумя способами - либо взять лишнюю связку и не брать пар, либо лишнюю коробку и не брать ни связок, ни пар. Если n3*1.05>10.25, то надо взять лишнюю связку:
n2=n2+1: n3=0
Если для получившейся покупки (старой или изменившейся) бу- дет n2*10.25+n3*1,05>114.00, то надо сделать
n1=n1+1: n2=0: n3=0 Это решение пригодно для любых цен (при которых коробка дешевле, чем 12 связок, а связка - чем 12 пар). #include <stdio.h> int main(void) { int n1,n2,n3,n,m; scanf("%d",&n); n1=n/144; m=n%144; n2=m/12; n3=m%12; if (n3*105>1025) {n2++;n3=0;} if (n2*1025+n3*105>11400){n1++;n2=n3=0;} printf("Для покупки %d пар надо купить %d кор.,%d св.%d пар \n",n,n1,n2,n3); } Задача N15. Имеется k селений. Если в селении i расположить пункт скорой помощи, то поездка по вызову в селение j займет время a[i,i]+a[i,j], где 1<=i,j<k,i не равно j. Найти номер селения i, поездка от которого в самое отдаленное(по времени) селение занимала бы минимальное время. Массив a[1:k,1:k] задан, в нем все a[i,j]>0;и a[i,j] м.б. не равно a[j,i]. Сформулируем эту задачу следующим образом. В каждой строке i массива A выберем максимальное среди чисел A[i, j] (j не равно i) и сложим его с A[i, i]. Найти i, при котором соответствующая сумма будет минимальна. #include <stdio.h> #define K 20 main() {int i,j,k,i1,s,t,a[K][K]; scanf("%d",&k); for (i=0;i<k;i++) for(j=0;j<k;j++) scanf("%d",&a[i][j]); for (i=0;i<k;i++) {for (s=0,j=0;j<k;j++) if(j!=i && s<a[i][j]) s=a[i][j]; s+=a[i][i]; if (i==0 || s<t) {i1=i; t=s;} } printf("%d\n",i); } Задача N16. Даны два упорядоченных массива a[1]<=a[2]<=...<=a[m] и b[1]<=b[2]<=...<=b[n]. Образовать из них упорядоченный массив c[1]<=c[2]<=...c[m+n]. Эта задача принципиально должна быть выполнена за m+n действий. Возьмем из A и B по первому элементу. Меньший из них занесем в С и заменим следующим из его же массива. Снова выберем меньший из двух, занесем в С и т.д. После каждого сравнения в С добавляется элемент - значит, сравнений будет меньше, чем m+n. Нужно только позаботиться о том, чтобы программа работала верно и при исчерпании одного из массивов. #include <stdio.h> #define mm 100 #define nn 100 main() { int m,n,i,j,k,a[mm],b[nn],c[mm+nn]; scanf("%d %d",&m,&n); for (i=0;i<m;i++) scanf("%d",&a[i]); for(j=0;j<n;j++) scanf("%d",&b[j]); for(k=i=j=0;k<m+n; k++) {if (i>=m) c[k]=b[j++]; else if (j>=n) c[k]=a[i++]; else if (a[i]>b[j]) c[k]=b[j++]; else c[k]=a[i++]; } for (k=0;k<m+n; k++) printf("%4d%c",c[k],(k+1)%10==0 || k==m+n-1?'\n':' '); } Задача N17. На квадратном клетчатом листе бумаги размерами 100х100 нарисовано несколько прямоугольников: каждый из прямоугольников состоит из некоторого числа целых клеток, причем различные прямоугольники не накладываются и не соприкасаются друг с другом. Написать программу, которая сосчитает и напечатает число прямоугольников. Эта задача решается следующим образом – прямоугольников столько, сколько их северо-западных углов (иначе говоря - верхних левых). Остается только не запутаться в случае, когда угол стоит у границы. #include <stdio.h> #define mm 20 #define nn 20 main() { int m,n,j,i,s,a[mm][nn]; scanf("%d %d",&m,&n); for(i=0; i<=m;i++) for (j=0;j<n; j++) if (a[i][j]=i*j) scanf("%d",&a[i][j]); for (s=0,i=1;i<=m; i++) for (j=1;j<=n; j++) if (a[i][j] &&!(a[i-1][j]+a[i][j-1])) s++; printf ("%d\n",s); }
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|