Добавил:
Kaz
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лаба 1-3 Лабы / lab2 / main
.cpp
#include <stdlib.h>
#include <iostream>
using namespace std;
//перечисления типов множества
typedef enum {MTypeElement, MTypeSet, MTypeVector, MTypeNull} MSetType;
//структура множества
struct MSet_{
bool is_set; //являектся ли элемент множеством
bool is_vector; //являектся ли множество направленым
bool is_null; //являектся ли множество пустым
char name[256]; //имя элемента
int col; //число вхождений
MSet_ *entrys; //указатель yа массив вхождений помножеств в данное множество
};
//отношение
struct MRelation_{
char name[256]; //имя отношения
int att_col; //кол-во аттрибутов
char *attributes[256]; //имена аттрибутов
MSet_ carteges; //картежи
};
//создание множества
MSet_ create_set(MSetType type,char *name){
MSet_ new_set;
if(type == MTypeElement) new_set.is_set = false, new_set.is_vector=false, new_set.is_null=false;
if(type == MTypeSet) new_set.is_set=true, new_set.is_vector=false, new_set.is_null = false;
if(type == MTypeVector) new_set.is_set=true, new_set.is_vector=true, new_set.is_null=false;
if(type == MTypeNull) new_set.is_set=false, new_set.is_vector=false, new_set.is_null=true;
strcpy(new_set.name,name);
if(type == MTypeNull)
strcpy(new_set.name,"");
new_set.entrys = new MSet_[6666];
new_set.col = 0;
return new_set;
}
//добавление подмножества в множество
//add_set - добавляемое множество
//set - множество, в которое добавляем
MSet_ insert_set(MSet_ add_set, MSet_ set){
if(!add_set.is_set && !add_set.is_null && !add_set.is_vector && strlen(add_set.name)==0){}else
set.entrys[set.col++]=add_set;
return set;
}
//сравнение множеств
bool compare_sets(MSet_ a, MSet_ b){
if(a.is_vector && !b.is_vector) return false;
if(!a.is_vector && b.is_vector) return false;
if(a.col!=b.col) return false;
if(!a.is_set && !b.is_set && strcmp(a.name,b.name)==0) return true;
if(!a.is_set && !b.is_set && strcmp(a.name,b.name)!=0) return false;
if((!a.is_set && b.is_set) || (a.is_set && !b.is_set)) return false;
for(int i=0;i<a.col;i++){
bool found=false;
for(int j=0;j<a.col;j++)
if(compare_sets(a.entrys[i], b.entrys[j]))
if((a.is_vector || b.is_vector) && i==j) found=true;
else
if(!a.is_vector && !b.is_vector) found=true;
if(!found) return false;
}
return true;
}
//поиск подмножества mset в множестве set
bool findSet(MSet_ mset, MSet_ set){
for(int i = 0;i<set.col;i++)
if(compare_sets(mset,set.entrys[i])) return true;
return false;
}
//вывод множества на экран
void debugSet(FILE *f,MSet_ mset){
if(mset.is_set){
if(mset.is_vector) fprintf(f,"<"); else fprintf(f,"{");
for(int i=0;i<mset.col;i++){
MSet_ ms=mset.entrys[i];
if(!ms.is_set){
fprintf(f,"%s",ms.name);
}
else
debugSet(f,ms);
if(i!=mset.col-1)
fprintf(f,",");
}
if(mset.is_vector) fprintf(f,">"); else fprintf(f,"}");
}
}
bool peresek(MSet_ a, MSet_ b){
for(int i=0;i<a.col;i++)
for(int j=0;j<b.col;j++)
if(compare_sets(a.entrys[i],b.entrys[j])) return true;
return false;
}
//перечисление положений при считывании множества из файла
enum {StateSepReaded,StateStartParsing=101,StateNameReading=102, StateNameReaded=103, StateSetReaded=104, StateSetReading=105, StateElementReaded=106, StateElementReading=107} typedef ParserState;
//символы для чтения из файла
enum {OpenSymb='{',CloseSymb='}',OpenVeSymb='<',CloseVeSymb='>', SeparatorSymb=','};
//ф-ция выводит ошибку на экран
void onError(char *error,int pos){
printf("Parse error at %d : %s\n",pos,error);
}
char all[10000];
char last_s;
bool isMain;
int i=0;
//преобразование строки char all[10000] в множество
MSet_ parseSet(MSet_ myset){
MSet_ mset = myset;
ParserState state = StateStartParsing;
bool setOpened=false, setVeOpened=false;
if(last_s=='{') state = StateSetReading, setOpened=true;
if(last_s=='<') state = StateSetReading, setVeOpened=true;
if(last_s=='}'|| last_s=='>') state = StateSetReaded;//setOpened=false;
MSet_ tmp_set = create_set(MTypeSet,"");
MSet_ ns = create_set(MTypeSet,""), vs=create_set(MTypeSet,"");
char c,tmp[256]="";
int last_pos = 0;
bool isMain1=isMain;
while(true){
i++;
if(i>strlen(all)) break;
c=all[i];
switch(c){
case OpenSymb:
if(last_s=='}' || last_s=='>' || isalpha(last_s) || isalnum(last_s) || last_s=='_'){
onError("expected , ",i);
}
tmp_set=create_set(MTypeSet,"");
last_s = OpenSymb;
tmp_set=parseSet(tmp_set);
if((tmp_set.col>0) || (mset.is_vector))
mset=insert_set(tmp_set,mset);
isMain=false;
break;
case OpenVeSymb:
if(last_s=='}' || last_s=='>' || isalpha(last_s) || isalnum(last_s) || last_s=='_'){
onError("expected , ",i);
}
state = StateSetReading;
tmp_set=create_set(MTypeVector,"");
last_s = c;
tmp_set=parseSet(tmp_set);
mset=insert_set(tmp_set,mset);
break;
case SeparatorSymb:
if(last_s=='{' || last_s=='<' || last_s==',' )
onError("expected name before separator",i);
if(state == StateNameReading){
if(strcmp(tmp,"")==0)
onError("name can't be 0 lenght",i);
mset=insert_set(create_set(MTypeElement,tmp), mset);
strcpy(tmp,"");
state = StateNameReaded;
};
last_s=c;
break;
case CloseSymb:
if(setVeOpened){
onError("expected >",i);
}
if(!setOpened){
onError("can't find { before }",last_pos);
}
if(state == StateNameReading){
mset=insert_set(create_set(MTypeElement, tmp),mset);
strcpy(tmp,"");
last_s = c;
return mset;
}
if(state == StateNameReaded){
onError("expected name before >",i);
}
if(state == StateSetReading){
if(compare_sets(mset,ns) || compare_sets(mset,vs)){
}else{
last_s = c;
return mset;
}
}
tmp_set=create_set(MTypeSet,"");
last_s = c;
setOpened = false;
return tmp_set;
break;
case CloseVeSymb:
if(setOpened)
onError("expected }",i);
if(!setVeOpened){
onError("can't find < before >",last_pos);
}
if(state == StateNameReading){
mset=insert_set(create_set(MTypeElement, tmp),mset);
strcpy(tmp,"");
last_s = c;
return mset;
}
if(state == StateNameReaded){
onError("expected name before >",i);
}
if(state == StateSetReading){
if(compare_sets(mset,ns) || compare_sets(mset,vs)){
}else{
last_s = c;
return mset;
}
}
tmp_set=create_set(MTypeVector,"");
last_s = c;
setVeOpened = false;
return tmp_set;
break;
default:
if(isalpha(c) || isalnum(c) || c=='_'){
if(last_s!=',' && last_s!='{' && last_s!='<' && !isalpha(last_s) && !isalnum(last_s) && last_s!='_'){
if(setOpened || setVeOpened)
onError("expected , ",i);
if(!setOpened)
onError("expected { ",i);
else
onError("expected < ",i);
}
if(state!=StateSetReading && state!=StateSetReaded && state!=StateNameReading && state!=StateStartParsing && state!=StateNameReaded){
onError("expected open set symbol ",last_pos);
}
state = StateNameReading;
sprintf(tmp,"%s%c",tmp,c);
last_s=c;
}else{
if(c==';')
return mset;
if(c!=';' && c!=' ' && c!='\n' && c!='\r' && c!='\0' && c!=-1){
printf("<%c>\n",c);
onError("unknown symbol ",i);
}
}
break;
}
};
if(setOpened)
onError("expected } at",i);
if(setVeOpened)
onError("expected > at",i);
return mset;
}
//перечисление состояний для считывания отношения
enum {RelStarted, RelNameReading, RelNameReaded, RelAttributeReading, RelAttributeReaded} typedef RelParserState;
//ф-ция считывает отношение из строки all и возвращает считаноеотношение в структуру MRelation_
MRelation_ parseRelation(){
RelParserState state = RelStarted;
MRelation_ relation_;
*relation_.attributes = new char[1000];
relation_.att_col=0;
char tmp[256]="";
while(1){
if(i>strlen(all)) break;
char c = all[i++];
switch(c){
case '=':
if(state!=RelAttributeReaded)
onError("Expected attibutes before '='",i);
i--;
last_s=all[i];
MSet_ carteges = parseSet(create_set(MTypeSet,""));
relation_.carteges= carteges.entrys[0];
break;
case '(':
if(state!=RelNameReading && state!=RelNameReading)
onError("Bad position for attributes declaration",i);
state=RelAttributeReading;
strcpy(relation_.name,tmp);
strcpy(tmp,"");
break;
case ':':
if(state!=RelAttributeReading)
onError("Expecetd attributes open symbol '('",i);
if(strcmp(tmp,"")==0)
onError("Expected attribute name before ':'",i);
relation_.attributes[relation_.att_col]=new char[256];
strcpy(relation_.attributes[relation_.att_col],tmp);
relation_.att_col++;
// printf("readed attribute: %s\n", relation_.attributes[relation_.att_col-1]);
strcpy(tmp,"");
break;
case ')':
if(state!=RelAttributeReading)
onError("Excpecred '(' for ')'",i);
if(strcmp(tmp,"")==0)
onError("Expected attribute name ",i);
relation_.attributes[relation_.att_col]=new char[256];
strcpy(relation_.attributes[relation_.att_col],tmp);
relation_.att_col++;
// printf("readed attribute: %s\n", relation_.attributes[relation_.att_col-1]);
strcpy(tmp,"");
state=RelAttributeReaded;
break;
default:
if(state==RelStarted) state=RelNameReading;
if(c=='\n' || c=='\r') return relation_;
sprintf(tmp,"%s%c",tmp,c);
break;
}
}
return relation_;
}
//проверяет отношение на правильность
bool checkRelation(MRelation_ relation){
int i=0;
for(i=0;i<relation.carteges.col;i++)
if(!relation.carteges.entrys[i].is_vector){
printf("error!! carteges can be only a oriented set!!!\n");
return false;
}
for(i=0;i<relation.carteges.col;i++)
if(relation.carteges.entrys[i].col!=relation.att_col){
printf("error!! carteges must have %d elements\n", relation.att_col);
return false;
}
return true;
}
//выводит отношение в указаный поток вывода
void debugRelation(FILE *f,MRelation_ relation){
//выводим имя
fprintf(f,"%s(", relation.name);
//аттрибуты
for(int i=0;i<relation.att_col;i++){
fprintf(f,"%s",relation.attributes[i]);
if(i!=relation.att_col-1)
fprintf(f,":");
}
fprintf(f,")=");
debugSet(f,relation.carteges);
fprintf(f,"\n");
}
//ф-ция возвращает отношение, являющееся соединением 2х отношений
MRelation_ connectRelations(MRelation_ relation1, MRelation_ relation2){
//создаем новое отношение
MRelation_ relation;
//задаем имя для нового отношения
strcpy(relation.name,"r_con");
//кол-во аттрибутов в новом отношении
relation.att_col=0;
*relation.attributes=new char[1000];
int i,j;bool found;
//добавляем в новое отношение аттрибуты из воторого отншения
//(добавляем тольео новые аттрибуты, т.е. короые отсутствуют в результирующем отношении)
for(i=0;i<relation1.att_col;i++){
found=false;
for(j=0;j<relation2.att_col;j++)
if(strcmp(relation2.attributes[j],relation1.attributes[i])==0) found=true;
if(found){
relation.attributes[relation.att_col] = new char[256];
strcpy(relation.attributes[relation.att_col],relation1.attributes[i]);
relation.att_col++;
}
}
return relation;
}
int main(int argc, char *argv[]){
//считываем содержисое файла в сроку
FILE *f = fopen("sample","r");
strcpy(all,"");
char c = fgetc(f);
while(!feof(f)){
sprintf(all,"%s%c",all,c);
c = fgetc(f);
}
fclose(f);
last_s=all[0];
//счтиываем из строки отношения и заносим их в структуру
MRelation_ relation1 = parseRelation();
checkRelation(relation1);
debugRelation(stdout,relation1);
MRelation_ relation2 = parseRelation();
checkRelation(relation2);
debugRelation(stdout,relation2);
printf("connected relation:\n");
MRelation_ rel = connectRelations(relation1, relation2);
debugRelation(stdout,rel);
return 0;
}