您的位置:首页 > 其它

英文词频分析器

2013-10-02 01:59 295 查看
转载请标明出处:http://blog.csdn.net/u012027907

有时经常有统计一篇文章中有多少个单词,这时候就需要词频分析器来解决了。

基本思想:

将文件中或用户输入的字符串先存起来,然后从第一个字符开始依次向后扫描,遇到字母,则将其先添加到一个字符串中,然后在向后扫描,若还是字母,则将此字符串连接到刚才的字符串中,若不是字母,则刚才的字符串就是一个单词,这样依次扫描完所有字符。当然,在扫描时,还要与已经存储的单词依次比较,若相同则不再添加,刚才那个单词的词数加一即可。

先截个图SeeSee:





我还将查询的结果保存至Access的数据库中,这里就用到ADO访问数据库的问题,上次我已经将ADO连接类(ADOConn)分装好了,这次只拿来用就行了。

代码:

void ADOConn::OnInitADOConn()
{

   // CString sysPath = "C:\\fg\\MuscicPlayer\\";

	
	HRESULT hr;

   ::CoInitialize(NULL);       //初始化OLE/COM环境
	hr=m_pConnection.CreateInstance("ADODB.Connection");  //创建connection对象
	
	// 在ADO操作中建议语句中要常用try...catch()来捕获错误信息, 
	// 因为它有时会经常出现一些意想不到的错误。
	try                 
	{    
		if(SUCCEEDED(hr))
		{
			char *dbPath="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=WordData.mdb";
	        hr=m_pConnection->Open(_bstr_t(dbPath),"","",adModeUnknown);
		}
	//	_bstr_t strConnect="Provider=SQLOLEDB;Server=LENOVO-PC;DataBase=Study;uid=sa;pwd=zyc123";
	//	m_pConnection->Open(strConnect,"","",adModeUnknown);
	} 
    //捕获异常
	catch(_com_error e)
	{
		
	    e.Description();
	}

}

void ADOConn::ExitConnect()
{
	//关闭记录集和连接
   if(m_pRecordset!=NULL)
		m_pRecordset->Close();
	m_pConnection->Close();
	//释放环境
	::CoUninitialize();

}
_RecordsetPtr& ADOConn::GetRecordSet(_bstr_t bstrSQL)
{
  try
  {
	  //连接数据库,如果conection对象为空,则重新连接数据库
	  if(m_pConnection==NULL)
		  OnInitADOConn();
	  //创建记录集对象
	  m_pRecordset.CreateInstance(__uuidof(Recordset));
	  //取得表中的记录
	  m_pRecordset->Open(bstrSQL,m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
  }
  catch(_com_error e)
  {
	  e.Description();
  }
  //返回记录集
  return m_pRecordset;
}
BOOL ADOConn::ExecuteSQL(_bstr_t _bstrSQL)
{
	_variant_t RecordsAffected;
	try
	{
		//是否已连接数据库
		if(m_pConnection==NULL)
			OnInitADOConn();
		m_pConnection->Execute(_bstrSQL,NULL,adCmdText);
		return true;
	}
	catch(_com_error e)
	{
		e.Description();
		return false;
	}
}


当然用数据结构来存最好了。

///////////////存放分出的所有单词的结构体/////////
typedef struct WordStore
{
	char  word[30]; 
}wordstore;
/////////存储排好序的单词及个数的结构体///////////
typedef struct WordStoreAll
{
	float frequency;
	int   number;
	char  word[30]; 
}wordstoreall;



主类:

//////////////////////////////////////////
class ReadWord
{
	int AllWord;
	int Count;
	bool AddTrue;
	wordstore WordNode[MAX];
	wordstoreall Word[MAX];
	/////数据库操作使用
	ADOConn m_AdoConn;
	_RecordsetPtr  m_pRecordset;
	_ConnectionPtr m_pConnection;
	char *tablename;
public:
	int Choice;
public:
	ReadWord();
	int GetCount(){	return Count;}
	bool GetAddTrue(){return AddTrue;}
	char *ReadFromText();
	char *ReadFromScreen();
	void strcopy(char *dest,const char *sour);
	void Transform(char *str);
	void GetEveryWord();
	void Countword();
	void Frequency();
	void Order();
	void Print(int X);
	void color(int a);
    ///-------数据库操作----------------
	void IsAddToAccess();  //判断用户是否将分析结果添加到数据库
	void AddToAccess();    //将分析结果添加到数据库
	void Select();         //查询数据库中的数据
	void CreateTable();
	void GetTableName(int n);
	void ReadTableName();
	void WriteTNameToFile();
};

///////////////////////////////
#include "Readword.h"
///////////////////////////////
///////构造函数//////////////
 ReadWord::ReadWord()
{
	AddTrue = false;
}
//////////////////加点颜色SeeSee/////////////////////////////
void ReadWord::color(int a)              //颜色函数
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a);
}
/////////////从屏幕上读取信息到字符串中/////////////
char *ReadWord::ReadFromScreen()
{
	char *string;
	string = (char*)malloc(1000);
	printf("请输入:");
//	fflush(stdout);
	gets(string);
	return string;
}
/////////////////////////////////////////

/////////////从文件中读取信息到字符串中/////////////
char *ReadWord::ReadFromText()
{
	FILE *fp;
	char *string;
	char FileName[30];
	string = (char*)malloc(5000);
	if(NULL == string)
	{
		printf("内存分配失败!\n");
		return NULL;
	}
	printf("请输入文件名(不用输后缀名):");
	scanf("%s",FileName);
//	gets(FileName);
	strcat(FileName,".txt");
	fp = fopen(FileName,"rb");
	if( NULL == fp)
	{
		printf("文件打开错误\n");
		return NULL;
	}
	fgets(string,5000,fp);
	fclose(fp);
    
	return string;
}

////////////////将非单词的字符转化为空格////////////
void ReadWord::Transform(char *str)
{
	while(*str != '\0')
	{
		if(*str<'a'||*str>'z')
			*str=' ';
		str++;
	}
}

//////////////拷贝函数/////////////////
void ReadWord::strcopy(char *dest,const char *sour)
{
	while(*sour != '\0')
	{
		*dest++=*sour++;
	}
	*dest='\0';
}
//////////////将每个单词分离出来//////////////////
void ReadWord::GetEveryWord()
{
	char tempw[30];
	char tempc[2];
    char *String;
	bool m_flag=false;
	int i=0,n=0;
	if(1 == Choice)
	     String = ReadFromText();
	else
		String = ReadFromScreen();
	strlwr(String); ///将大写字母转化为小写字母
    Transform(String);
	
	while(1)
	{
		if(*String != '\0')
		{
			tempc[0]=*String;
			if(' ' != *String)
			{	
				tempw[i++]=tempc[0];m_flag = true;
			}
			else
			{
				if(m_flag)
				{
					m_flag = false;
					tempw[i]='\0';
					strcopy(WordNode
.word,tempw);
					n++;
					for(;i>=0;i--)
						tempw[i]=0;
					i=0;
				}
			}
		}
		else if(*(--String) != ' ')  //这时为了将文件最后一个单词因为没加标点,而未能统计的最后一个单词统计进去
		{
			tempw[i]='\0';
			strcopy(WordNode
.word,tempw);
			n++;
			for(;i>=0;i--)
				tempw[i]=0;
			i=0;
			break;
		}
		else
			break;
		String++;		
	}	
	AllWord=n;  //得到分离出的总词数
}
//////////////////////对提取出的所有单词计数////////
void ReadWord::Countword()
{
	int i,j;
	int count=0,m_flag=0;
    for(i=0;i<AllWord;i++)
		Word[i].number=1;
	
	for(i=0;i<AllWord;i++)
	{
		m_flag=0;
		for(j=0;j<AllWord;j++)
		{
			if(!strcmp(Word[j].word,WordNode[i].word)) //若有相同的单词,其相应的number加一
			{	Word[j].number++;m_flag=1;}
		}
		if(0 == m_flag)                                //若原有的单词中没有相同的,则添加此单词到Word中
		{
			strcopy(Word[count].word,WordNode[i].word);
			count++;
		}
		
	}
	Count=count;
}
////////////////计算每个单词的频率//////////////
void ReadWord::Frequency()
{
	int i;
	for(i=0;i<Count;i++)
	{
		Word[i].frequency=(float)Word[i].number/Count;
	}
}
////////////////冒泡排序/////////////////////////
void ReadWord::Order()
{
	char tempstr[30];
	int  tempnum;
	float tempfre;
	int m,n;
	for(m=1;m<Count;m++)
		for(n=0;n<Count-m;n++)
		{
			if(strcmp(Word
.word,Word[n+1].word)>0)
			{
				//////交换单词
				strcopy(tempstr,Word
.word);
				strcopy(Word
.word,Word[n+1].word);
				strcopy(Word[n+1].word,tempstr);
				////////交换词数
                tempnum = Word
.number;
				Word
.number = Word[n+1].number;
				Word[n+1].number = tempnum;
				/////////交换频率
				tempfre = Word
.frequency;
				Word
.frequency = Word[n+1].frequency;
				Word[n+1].frequency = tempfre;
			}
		}
}
///////////////////输出结果//////////////////////
void ReadWord::Print(int X)
{
	int i;
	printf("对该文本的词频分析如下:\n");
	printf("序号\t单词\t       个数\t频率\n");
    for(i=0;i<X;i++)
	{
		printf("%-3d\t%-10s\t%d\t%.2f%%\n",i+1,Word[i].word,Word[i].number,Word[i].frequency*100);
	}
}
///////////////从数据库中选择查询结果//////////////
void ReadWord::Select()
{
	m_AdoConn.OnInitADOConn();  //初始化链接库类
//	char *sql="Select * From Wordtable";
	char *q=" ";
	char Sql[50];
	char *Sql1 ="SELECT * FROM ";
	strcopy(Sql,Sql1);
	strcat(Sql,tablename);
	strcat(Sql,q);

	m_pRecordset=m_AdoConn.GetRecordSet((_bstr_t)Sql); //打开并获得记录集
	m_pConnection.CreateInstance(__uuidof(Connection));  //创建connection对象
	_variant_t var; 
	char strword[30];
	int number;
	double frequen;
	int i=0;
	try		
	{ 		
		if(!m_pRecordset->adoBOF) 			//表中数据不为空,将记录及指针移到第一条
			m_pRecordset->MoveFirst();
		else
		{
			printf("\n数据表为空!\n");
			m_AdoConn.ExitConnect();
			return ; 			
		} 
		printf("对该文本的词频分析如下:\n");
    	printf("序号\t单词\t       个数\t频率\n");
		// 读入库中各字段并输出       
		while(!m_pRecordset->adoEOF) 			
		{ 			
			var = m_pRecordset->GetCollect("Word"); 		 	//获得一条记录的Word字段信息
			if(var.vt != VT_NULL) 				
				strcopy(strword,(LPCSTR)_bstr_t(var)); 
			var = m_pRecordset->GetCollect("Num");            //获得一条记录的Num字段信息
			if(var.vt != VT_NULL) 				
				number = var.intVal; 		
				var = m_pRecordset->GetCollect("Frequency");            
			if(var.vt != VT_NULL) 				
				frequen = var.dblVal; 	
			printf("%-3d\t%-10s\t%d\t%.2lf%%\n",i+1,strword,number,frequen*100);	    
			i+=1;
			m_pRecordset->MoveNext(); 
		} 
	
	} 
	catch(_com_error *e) 	
	{ 	
	//	AfxMessageBox(e->ErrorMessage());   
		e->Description();
	}
	m_AdoConn.ExitConnect();
}
//////////////////用户是否同意将结果添加到数据库/////////
void ReadWord::IsAddToAccess()
{
	char button;
	printf("\n是否将结果添加到数据库?是按[Y],否按其他键。\n");
	fflush(stdin);
	scanf("%c",&button);
	if(button == 'Y' || button == 'y')
	{
		AddTrue = !AddTrue;
		GetTableName(1);
		CreateTable();
		AddToAccess();
	}
}
////////////////将结果添加到数据库中/////////////////////////
void ReadWord::AddToAccess()
{
	m_AdoConn.OnInitADOConn();
	char *q=" ";
	char Sql[50];
	char *Sql1 ="SELECT * FROM ";
	strcopy(Sql,Sql1);
	strcat(Sql,tablename);
	strcat(Sql,q);
	m_pRecordset=m_AdoConn.GetRecordSet((_bstr_t)Sql); //打开并获得记录集
	m_pConnection.CreateInstance(__uuidof(Connection));  //创建connection对象
	_variant_t var;
    int i;
    try
	{
		if(AddTrue)
		{
			for(i=0;i<Count;i++)
			{
				m_pRecordset->AddNew();
				m_pRecordset->PutCollect("Word",_variant_t(Word[i].word));
				m_pRecordset->PutCollect("Num",_variant_t((long)Word[i].number));			
				m_pRecordset->PutCollect("Frequency",_variant_t((float)Word[i].frequency));
				m_pRecordset->Update();
			}
		}
		printf("\n添加成功!\n\n");
		m_AdoConn.ExitConnect();
	}
	catch(...)
	{
     printf("操作失败\n");
	}

}

//////////////将用户输入的表名存储到文件中////////////////
void ReadWord::WriteTNameToFile()
{
	char *Table,*str=" ";
	Table = (char*)malloc(20);
	strcopy(Table,str);
	strcat(Table,tablename);
	strcat(Table,str);
	FILE *fp;
	if((fp = fopen("TableNameList.txt","ab+")) == NULL)
	{
		printf("不能打开文件\n");
		return;
	}
	if(fwrite(Table,strlen(Table)*sizeof(char),1,fp) != 1)
		printf("文件写出错!\n");
	fclose(fp);
}

////////////////////存文件中读取表名////////////////////////
void ReadWord::ReadTableName()
{
	FILE *fp;
	char *string;
	char *FileName="TableNameList.txt";
	string = (char*)malloc(300);
	if(NULL == string)
	{
		printf("内存分配失败!\n");
		return;
	}

	fp = fopen(FileName,"rb");
	if( NULL == fp)
	{
		printf("文件打开错误\n");
		return;
	}
	fgets(string,300,fp);
	fclose(fp);
	printf("可供查询的表名如下:\n");
    printf("%s\n",string);
}

//////////////获得要创建表的名称或获得要查询表的名称////////////
void ReadWord::GetTableName(int n)
{
	tablename = (char*)malloc(20);
	fflush(stdin);
	if(1 == n)
	{
		printf("请输入要创建的表名:");
		gets(tablename);
		WriteTNameToFile();
	}
	else
	{
		ReadTableName();
		printf("请输入您要查询的表名:");
		gets(tablename);
		 /////////判断
    }		
}
//////////////////////创建表//////////////////
void ReadWord::CreateTable()
{
	m_AdoConn.OnInitADOConn();
//	_bstr_t sql;
	char Sql[100];
	char *Sql1 = "CREATE TABLE ";
	char *Sql2 = " (Word varchar(30),Num int,Frequency float)";
	strcopy(Sql,Sql1);
	strcat(Sql,tablename);
	strcat(Sql,Sql2);
	if(!m_AdoConn.ExecuteSQL((_bstr_t)Sql))
	{	
		printf("\n创建表失败!\n");
		return;
	}
	m_AdoConn.ExitConnect();

}

转载请标明出处:http://blog.csdn.net/u012027907
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: