Скачиваний:
30
Добавлен:
15.06.2014
Размер:
12.24 Кб
Скачать

#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;
}
Соседние файлы в папке lab2
  • #
    15.06.20144.31 Кб28lab2.dsp
  • #
    15.06.2014533 б29lab2.dsw
  • #
    15.06.201448.64 Кб29lab2.opt
  • #
    15.06.2014855 б28lab2.plg
  • #
    15.06.201412.24 Кб30main.cpp
  • #
    15.06.201478 б28sample