📄 5 创建向量模型.cpp
字号:
//功能:根据语料生成字典
//输入:dic_try3.txt 词/词性序列
//
#include <stdio.h>
#include <math.h>
//词条,用于记录某个字打头的词组
struct ct{
unsigned char cc[30];
int freq;
ct *next;
double ym_cx[44];
double length;
};
//词头,每个字对应一个词头,词头引领词条
struct ctou{
ct *head;
ct *tail;
int count;
} ctou[8000];
#define sen_len 150
//全局变量
int in_dic[sen_len][16]; //用于存储词图
struct ct *in_dic_pos [sen_len][16];
unsigned char test[sen_len]="\0";
FILE *fp_cx;
int compare(unsigned char *dic_ct,int length1,unsigned char *a ,int length2);//比较两个字符串是否相等
void strcopy(unsigned char *dic_ct,unsigned char *a,int length ); //把一个字符数组的内容拷贝到另一个数组
void fputstr(unsigned char * a,int length,FILE * pfw); //将字符串内容写入文件,可用 fprintf 代替
int array_len(unsigned char *c); //判断字符数组的实际长度
void sen_read(FILE *fp,unsigned char *c); //读入一个句子?
int ym_create(char * str);
int xl_compute(char * str); //构建隐马模型
void print_dic();//将字典中的所有词条打印到keyword.txt文本
void clear_dic();//将字典中的说哟词条freq项清0
void main()
{
//1创建模型-------------------------------------------
ym_create("dic_try3.txt");
//测试用:显示字典内容
clear_dic();
//ym_create("doc.txt");
xl_compute("doc.txt");
print_dic();
}
//---------------------------------------------------//---------------------------------------------------
void fputstr(unsigned char * a,int length,FILE * pfw)
{
for(int i=0;i<length*2;i++)
{
fputc(a[i],pfw);
}
fputc(' ',pfw);
}
void strcopy(unsigned char *dic_ct,unsigned char *a ,int length)
{
for (int i=0;i<length;i++)
dic_ct[i]=a[i];
dic_ct[i]='\0';
}
int compare(unsigned char *dic_ct,int length1,unsigned char *a ,int length2)
{
if(length1!=length2/2)return 1; //判断词等长
for (int i=0;i<length2;i++) //判断词中每个字节都相等
if(dic_ct[i]!=a[i]){return 1;}
return 0; //两词相等返回0
}
//返回数组长度(不含/0)
int array_len(unsigned char *c)
{
int i=0;
while(c[i]!='\0')
{i++;}
return i;
}
//---------------------------------------------------cut
void sen_read(FILE *fp,unsigned char *c)
{
unsigned char getc;
int i=0;
getc=fgetc(fp);
while(getc!=255)
{
c[i]=getc;
i++;
getc=fgetc(fp);
}
c[i]='\0';
}
void print_dic()
{
FILE *fpw;
fpw=fopen("keyword.txt","w");//写入文件
int i=0;
for(i=0;i<8000;i++)
{
ct *head=ctou[i].head;
while(head!=NULL)
{
fprintf(fpw,"%s %d\n",head->cc,head->freq);
// printf("%s\n",head->cc);
head=head->next;
}
}
}
void clear_dic()
{
int i=0;
for(i=0;i<8000;i++)
{
ct *head=ctou[i].head;
while(head!=NULL)
{
head->freq=0;
head=head->next;
}
}
}
//------------------------------------------------------
int ym_create(char * str)
{
unsigned char a[60];//30字符,15词;
FILE *fp;
fp=fopen(str,"r");//读入文件,用于创建字典的语料库文件
if (fp==NULL)
{ printf("cannot open thi file\n");}
//对 词头结构 进行初始化
for (int j=0;j<8000;j++)
{
ctou[j].head=NULL;
ctou[j].tail=NULL;
ctou[j].count=0;
}
//循环处理,字典构建开始
unsigned char c1; int i=0;int temp=0;//用于处理读取词性的结果
while(!feof(fp))
{
int flag_c_cx=0;//处理词,词性标志位;
int writeddown=0;i=0;
for(j=0;j<60;j++)
a[j]=0;
//取token:同时读取词性(读取词 到a[],读取词性 到temp )
do{ //如果不是空格 读入字符到数组.
c1 =fgetc(fp); //读入一位
if(c1==255){break;}//如果是文章结尾则跳出
//1 根据 '/' 和 ' '修改 当前状态(1 词性 0 词 )
if(c1=='/')
{
flag_c_cx=1;continue;//转为处理词性状态
}
if(c1==32 && flag_c_cx==1)
{
flag_c_cx=0;//结束处理词性状态,转为处理词状态
}
//2 处理词性部分;
if(flag_c_cx==1)//处理词性部分;
{
unsigned char c2=fgetc(fp);//取下一词
if(c2==' ' || c2==255)
{ //本字符是单字符
temp=c1-97;
c1=c2; flag_c_cx=0;
continue;
}
else{//本字符是双字符
temp=c2+c1;
switch(temp)
{
case 168: temp=26;break;//Ag
case 169: temp=27;break;//Bg(s)------------存在问题
case 171: temp=28;break;//Dg
case 180: temp=29;break;//180 Mg (s)
case 181: temp=30;break;//Ng
case 185: temp=31;break;//Rg(s)
case 187: temp=32;break;//Tg
case 189: temp=33;break;//Vg
case 192: temp=34;break;//192 Yg(只出现过一次:耳)
case 197: temp=35;break;//ad
case 207: temp=36;break;//an
case 218: temp=37;break;//vd
case 224: temp=38;break;//nv
case 225: temp=39;break;//ns
case 226: temp=40;break;//nt
case 228: temp=41;break;//vn
case 230: temp=42;break;//nx
case 232: temp=43;break;//nz
}
c1=c2; flag_c_cx=0;continue;
}
}//end-if
//3处理空格
if(c1==32){continue;}
a[i]=c1;writeddown=1;i++; /* */
}while(c1!=32||writeddown==0);//如果是token前的空格,循环;
if(c1==-1){printf("end-here");break;}
a[i]='\0';
//测试用:显示取词结果
if(i>30)//词长超过15不予处理
{//printf("%s:%d\n",a,temp);
continue;}
//4写入字典(词和词性都已经处理完毕)
//4.1计算地址
if(a[0]<0xa1 && a[0]>0xf7){printf("超出处理范围错误\n");continue;}
if(i>0)//字符数组内容不为空,即词存在
{
int s1=0;
if(a[0]>=0xb0)
{
s1=(a[0]-0xb0)*96+(a[1]-0xa0);if(s1>6920||s1<0)printf("创建字典错误");
}
if(a[0]<0xb0 && a[0]>=0xa1)
{ // continue;
s1=(a[0]-0xa1)*96+(a[1]-0xa0)+7000;
if(s1>8000||s1<0){printf("创建字典标点-错误\n");printf("%d\n",s1);}
}
// printf("%s:%d\t",a,temp);
//4.2判断词是否已经在节点中,这部分作为字典导入内存用可以直接删除
ct *head=ctou[s1].head;
while(head!=NULL)
{
if(compare(head->cc,head->length,a,i)==0)//两词相等
{head->freq++;head->ym_cx[temp]++;break;}
head=head->next;
}
//4.3将新词写入字典
if(head==NULL)//如果词条为空,新建词条,将词条写入
{
struct ct *p=new ct();
p->freq=1;
for(int j=0;j<44;j++)
p->ym_cx[j]=0;
strcopy(p->cc,a,i);
p->next=NULL;
p->length=i/2;
if(ctou[s1].count==0)
{
ctou[s1].head=p;
ctou[s1].tail=p;
}
else{ctou[s1].tail->next=p;ctou[s1].tail=p;}
ctou[s1].count++;
}
}
//4-end 写入词典结束
} //循环结束,字典构建结束。
fclose(fp);
return 1;
}
//------------------------------------------------------
int xl_compute(char * str)
{
unsigned char a[60];//30字符,15词;
FILE *fp;
fp=fopen(str,"r");//读入文件,用于创建字典的语料库文件
if (fp==NULL)
{ printf("cannot open thi file\n");}
//循环处理,字典构建开始
unsigned char c1; int i=0;int temp=0;//用于处理读取词性的结果
while(!feof(fp))
{
int flag_c_cx=0;//处理词,词性标志位;
int writeddown=0;i=0;
int j=0;
for(j=0;j<60;j++)
a[j]=0;
//取token:同时读取词性(读取词 到a[],读取词性 到temp )
do{ //如果不是空格 读入字符到数组.
c1 =fgetc(fp); //读入一位
if(c1==255){break;}//如果是文章结尾则跳出
//1 根据 '/' 和 ' '修改 当前状态(1 词性 0 词 )
if(c1=='/')
{
flag_c_cx=1;continue;//转为处理词性状态
}
if(c1==32 && flag_c_cx==1)
{
flag_c_cx=0;//结束处理词性状态,转为处理词状态
}
//2 处理词性部分;
if(flag_c_cx==1)//处理词性部分;
{
unsigned char c2=fgetc(fp);//取下一词
if(c2==' ' || c2==255)
{ //本字符是单字符
temp=c1-97;
c1=c2; flag_c_cx=0;
continue;
}
else{//本字符是双字符
temp=c2+c1;
switch(temp)
{
case 168: temp=26;break;//Ag
case 169: temp=27;break;//Bg(s)------------存在问题
case 171: temp=28;break;//Dg
case 180: temp=29;break;//180 Mg (s)
case 181: temp=30;break;//Ng
case 185: temp=31;break;//Rg(s)
case 187: temp=32;break;//Tg
case 189: temp=33;break;//Vg
case 192: temp=34;break;//192 Yg(只出现过一次:耳)
case 197: temp=35;break;//ad
case 207: temp=36;break;//an
case 218: temp=37;break;//vd
case 224: temp=38;break;//nv
case 225: temp=39;break;//ns
case 226: temp=40;break;//nt
case 228: temp=41;break;//vn
case 230: temp=42;break;//nx
case 232: temp=43;break;//nz
}
c1=c2; flag_c_cx=0;continue;
}
}//end-if
//3处理空格
if(c1==32){continue;}
a[i]=c1;writeddown=1;i++; /* */
}while(c1!=32||writeddown==0);//如果是token前的空格,循环;
if(c1==-1){printf("end-here");break;}
a[i]='\0';
//4写入字典(词和词性都已经处理完毕)
//4.1计算地址
if(a[0]<0xa1 && a[0]>0xf7){printf("超出处理范围错误\n");continue;}
if(i>0)//字符数组内容不为空,即词存在
{
int s1=0;
if(a[0]>=0xb0)
{
s1=(a[0]-0xb0)*96+(a[1]-0xa0);if(s1>6920||s1<0)printf("创建字典错误");
}
if(a[0]<0xb0 && a[0]>=0xa1)
{
s1=(a[0]-0xa1)*96+(a[1]-0xa0)+7000;
if(s1>8000||s1<0){printf("创建字典标点-错误\n");printf("%d\n",s1);}
}
//4.2判断词是否已经在节点中
ct *head=ctou[s1].head;
while(head!=NULL)
{
if(compare(head->cc,head->length,a,i)==0)//两词相等
{head->freq++;head->ym_cx[temp]++;break;}
head=head->next;
}
}
//4-end 写入词典结束
} //循环结束,字典构建结束。
fclose(fp);
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -