分词系统——软件工程第一次作业

姓名:张建军 学号:2012211544 班级:0411202


本系统是由VC6.0所写,基于中科院ICTCLAS2010开发包再次开发。由于之前受ICTCLAS限制,授权期限一年,故现在使用,需要将系统时间调整至2010年,而我已经在内部做了改动,不需要手动更换时间了。
本系统具有基本的过滤功能,能有效过滤基本符号,部分虚词和部分英文无重要意义的词;内部采用map自动排序。对于单独的插入数据,map内部能有效的快速排序,但是如果大量的插入数据,map的效率就会降低,因为每次插入都会进行比较排序,对于本程序,如果是采用一次插入,然后再选择高效的排序方式,理论上时间效率会对比较高。但是对于小型的文本文件,效率还是很高的,能在很短时间完成排序并输出。

有需求的同志请留言。
计划时间:一周
实际时间:2 天

通过这次做出实际产品,我学到了很多,如下:

1、通过对代码的编写,加深了对编程语言C++的更加了解。上学期写过很多代码,最开始大部分都是在控制台下面写的,也在控制台下面写过小游戏,熟练掌握了很多写代码的技巧和控制台下面的很多图形图像的处理,但是一直在学新知识而没有时间复习这些代码,这次的分词系统让我复用了大量以前的代码,并且在其基础上改进,很不容易!

2、在此之前,看过一些MFC的书籍,刚开始看头大,不过后来渐渐就习惯了里面的编程方式和函数调用,上学期期末交了一个MFC写的俄罗斯方块,然后好久都再也没动过MFC,这次接到这个作业的时候,第一反应就是一定要写一个MFC的程序,最开始感觉难度很高,毕竟较长时间没碰过MFC了,还好大体思路清晰,程序基本顺利。原计划花一周的,但基本代码只花了1~2天。

3、另外,通过克服写程序中遇到的困难,还是学了很多代码方面的知识,比如有的函数打开文件会默认修改工作路径,造成某些二次开发包的函数初始化就失败。

4、以前只是阅读过 STL 的书籍,但是真正用 STL却很少,这次写程序,第一思路就使用了C++标准模板库里面的MAP类,有之前阅读累积的基础,使用起来比较顺利,但是在编程过后仔细分析MAP类,发现单次插入效率高,但是多次插入效率低这个特性,但是为了代码的简明易懂,我并没有采用更高效的算法,况且MAP类在一般的测试中表现还是相当优秀的。节约了我大量coding的时间。

5、此次的软件开发是基于一个中科院的二次开发包开发的,该二次开发包有授权期限,最开始拿到手里是授权到期的,后来通过一系列的查找资料,解决了这个问题,该分词系统表现得还不错。

6、最初也考虑过如果自己不会做中文的,做个英文的也能应付这次作业。不过后来仔细想想,感觉英文的并不合适,第一是由于我觉得英文的过于简单,这里并不是贬低做英文词汇的同学,做英文的只是在空格和连字符之前进行判断,思路非常清晰,代码也易于编写,为了给自己一些挑战,我最终还是决定基于中科院的ICTCLAS进行开发,其中也编写了一段代码稍加改造即可适合英文词频统计。



克服的问题:

1、才开始做的时候,由于每次从文件读取一个char类型,然后进行输出,导致中文字符全是乱码,主要是由于中文字符占用的字节比英文字符占的字节多造成的,改进之后即可。

2、才开始拿到开发包完全不知道怎么弄,第一次在开发包上面开发,而且为了调试开发包的初始化函数,查看了好多资料,其中包括网上别人的博客和相应的纯英文开发文档。

3、中途为了避免开发包授权到期的问题,百度了许久,最终有网友说修改系统时间能够避免授权到期,最开始的修改系统时间是我手动修改的,经常导致一些证书过期,后来觉得这样不方便,便在代码中添加了相应的修改系统时间的代码,经过一段时间的测试,效果比较好,但是好景不长,后来无缘无故不能修改系统时间,通过分析和百度,发现最终问题出在程序的权限上面。于是我查阅相应资料来提升进程的权限(不是管理员不能自动提升权限和修改系统时间)。但最后我并没有采用这种方式,而是将原来的dll替换为一个破解版本的dll即可。

4、中途遇到一个很隐秘的问题,我分析了很久的代码,知道问题大概出在某个函数上面,但是却始终想不通为什么会错。因为从后面的输出看来,几乎是没有什么问题的。将文件路径保存在一个CString变量中,手动输入路径能正常打开(之前的程序设置有手动输入路径,后来隐藏了),输出CString变量查看也正常,初始化函数也能正常运作。但是当我用一个CFileDialog对象打开路径,CString对象正常,但是放入初始化函数却导致初始化函数失败,而且还会在桌面上创建我中途建立的一些缓存文件,不过这些问题最终都在自己的努力下顺利的解决了,感觉自己这次做得非常不错!


VS2013 性能分析如图 :






主界面






界面按钮:分四个按钮,

1 、“打开指定文件”按钮:
单击打开文件按钮,弹出文件对话框

,自动限制打开txt格式文件。



如果未打开有效文件,会提示错误并返回
分词系统——软件工程第一次作业




2、 “ 确定”按钮:
当输入完毕,单击确定按钮即可自动排序并输出。






3、“ 查看文件”按钮

所有的排序都保存在一个临时文件中,可以通过点击查看文件按钮查看所有排序。




4、“ 退出”按钮:

成功退出程序。




主代码段:
// no1Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "no1.h"
#include "no1Dlg.h"
#include "ICTCLAS50.h"
#include "string"
#include "fstream"
#include "map"
#include "iomanip"
#include "WINDOWS.H"

using namespace std;


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//定义全局对象   ///       
typedef map SIMap;
typedef multimap ISMap;

CString filepath;//="C:\\Users\\CHOSAN\\Desktop\\sort.txt";//CString filepath 声明
string str1=" ";
bool OK = false;
//bool OPENFILE = false;
SIMap strmap;
ISMap aftertem;


void erasemap(); //声明函数
void addspace(string);
void Map();
void DoEx();
void cleartxt(string);
void fullthepath();
void initall();


/
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
CAboutDlg();

// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CNo1Dlg dialog

CNo1Dlg::CNo1Dlg(CWnd* pParent )
: CDialog(CNo1Dlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CNo1Dlg)
// NOTE: the ClassWizard will add member initializationhere
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequentDestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CNo1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CNo1Dlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CNo1Dlg, CDialog)
//{{AFX_MSG_MAP(CNo1Dlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_SURE, OnSure)
ON_BN_CLICKED(IDC_OPENFILE, OnOpenfile)
ON_BN_CLICKED(IDC_READTXT, OnReadtxt)
ON_BN_CLICKED(IDC_Cancle, OnCancle)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CNo1Dlg message handlers

BOOL CNo1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX,strAboutMenu);
}
}

// Set the icon for this dialog.   Theframework does this automatically
//   when the application's main window is nota dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE;   // return TRUE  unless you set the focus to a control
}

void CNo1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// If you add a minimize button to your dialog, you will needthe code below
//   to draw the icon.   ForMFC applications using the document/view model,
//   this is automatically done for you by theframework.

void CNo1Dlg::OnPaint() 
{
CPaintDC dc(this); // device context for painting

if (IsIconic())
{
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(),0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CRect crect;
GetClientRect(&crect);
CRectcrt1(crect.left,crect.bottom,crect.left+250,crect.bottom-50);
CRectcrt2(crect.right,crect.bottom,crect.right-250,crect.bottom-50);
dc.Rectangle(&crt1);dc.Rectangle(&crt2);
CFont font;
font.CreatePointFont(140,_T("Arial"));
dc.SelectObject(&font);
dc.SetBkMode(TRANSPARENT);
CString sli= _T("Designed by 李艾琳"),szhang= _T("Coding by张建军");
crt1.OffsetRect(15,15);
dc.SetTextColor(RGB(192,192,192));
dc.DrawText(sli,&crt1,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
crt1.OffsetRect(-15,-15);
dc.SetTextColor(RGB(0,0,0));
dc.DrawText(sli,&crt1,DT_VCENTER|DT_SINGLELINE|DT_CENTER);



crt2.OffsetRect(15,15);
dc.SetTextColor(RGB(192,192,192));
dc.DrawText(szhang,&crt2,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
crt2.OffsetRect(-15,-15);
dc.SetTextColor(RGB(0,0,0));
dc.DrawText(szhang,&crt2,DT_VCENTER|DT_SINGLELINE|DT_CENTER);



CDialog::OnPaint();
}
}

// The system calls this to obtain the cursor to display whilethe user drags
//   the minimized window.
HCURSOR CNo1Dlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}

void CNo1Dlg::OnSure() 
{
// TODO: Add your control notification handler code here



//读取文本,并且存入 Test_result.txt 初始化文件,文件首部添加空格,将路径显示在静态文本

GetDlgItem(IDC_OUTPUT)->SetWindowText(filepath);
string fpath(filepath.GetBuffer(0)); //声明stringfpath,并且用CString初始化它
filepath.ReleaseBuffer();
 



bool b =ICTCLAS_Init();
if(!b){
MessageBox("初始化失败,请调整时间至2010年!!","ERROR"); //初始化ICTCLAS
// SetLocalTime(&curr_st1);//返回时间
}
else
{

ICTCLAS_FileProcess(fpath.c_str(),"Test_result.txt",CODE_TYPE_GB,1);//调用文件处理函数
ICTCLAS_Exit(); //退出ICTCLAS
// SetLocalTime(&curr_st1);//返回时间
addspace(string("Test_result.txt")); //给文件添加空格
remove("Test_result.txt");

Map(); //读取,存入strmap
strmap.erase("");
erasemap(); //去除虚词等
if(!strmap.empty())
{
DoEx(); //存入multimap
MapPrint();
}
initall();
}
}




void erasemap()
{
strmap.erase("。");
strmap.erase("了");
strmap.erase("Is");
strmap.erase(" ");
strmap.erase("is");
strmap.erase("嗯");
strmap.erase("啊");
strmap.erase("呀");
strmap.erase("哦");
strmap.erase("而");
strmap.erase("而且");
strmap.erase("何");
strmap.erase("乎");
strmap.erase("乃");
strmap.erase("其");
strmap.erase("且");
strmap.erase("并且");
strmap.erase("若");
strmap.erase("所以");
strmap.erase("为");
strmap.erase("以");
strmap.erase("因");
strmap.erase("因为");
strmap.erase("和");
strmap.erase("之");
strmap.erase("者");
strmap.erase("则");
strmap.erase("与");
strmap.erase("也");
strmap.erase("焉");
strmap.erase("都");
strmap.erase("非常");
strmap.erase("最");
strmap.erase("太");
strmap.erase("更");
strmap.erase("极其");
strmap.erase("格外");
strmap.erase("分外");
strmap.erase("一直");
strmap.erase("才");
strmap.erase("总");
strmap.erase("又");
strmap.erase("共");
strmap.erase("的确");
strmap.erase("必须");
strmap.erase("忽然");
strmap.erase("猛然");
strmap.erase("那");
strmap.erase("这");
strmap.erase("at");
strmap.erase("on");
strmap.erase("in");
strmap.erase("for");
strmap.erase("by");
strmap.erase("呢");
strmap.erase("哎");
strmap.erase("唉");
strmap.erase("吧");
strmap.erase("哇");
strmap.erase("噢");
strmap.erase("喔");
strmap.erase("am");
strmap.erase("are");
strmap.erase("was");
strmap.erase("were");
strmap.erase("喽");
strmap.erase("咧");
strmap.erase("叻");
strmap.erase("嘘");
strmap.erase("吁");
strmap.erase("below");
strmap.erase("the");
strmap.erase("a");
strmap.erase("an");
strmap.erase("it");
strmap.erase("he");
strmap.erase("she");
strmap.erase("him");
strmap.erase("her");
strmap.erase("At");
strmap.erase("On");
strmap.erase("In");
strmap.erase("For");
strmap.erase("By");
strmap.erase("Am");
strmap.erase("Are");
strmap.erase("Was");
strmap.erase("Were");
strmap.erase("Below");
strmap.erase("The");
strmap.erase("A");
strmap.erase("An");
strmap.erase("It");
strmap.erase("He");
strmap.erase("She");
strmap.erase("Him");
strmap.erase("Her");
strmap.erase(":");
strmap.erase(")");
strmap.erase("(");
strmap.erase("!");
strmap.erase("、");
strmap.erase(",");
strmap.erase("的");
strmap.erase(".");
strmap.erase("来");
strmap.erase("能");
strmap.erase("会");
strmap.erase("个");
strmap.erase("只");
strmap.erase("值");
strmap.erase("有");
strmap.erase("如");
strmap.erase("该");
strmap.erase("需");
strmap.erase("来");
strmap.erase("用");
strmap.erase("被");
strmap.erase("在");
strmap.erase("已");
strmap.erase("不");
strmap.erase("是");
strmap.erase("就");
strmap.erase("”");
strmap.erase("“");
strmap.erase("你");
strmap.erase("很");
strmap.erase("下");
strmap.erase("上");
strmap.erase("中");
strmap.erase("前");
strmap.erase("后");
strmap.erase("等");
strmap.erase("把");
strmap.erase("它");
strmap.erase("他");
strmap.erase("她");
strmap.erase("您");
strmap.erase("或");
strmap.erase("当");
strmap.erase("于是");
strmap.erase("却");
strmap.erase("’");
strmap.erase("‘");
strmap.erase("再");
strmap.erase("?");
strmap.erase("\"");
strmap.erase("我");
strmap.erase("于");
strmap.erase(";");
strmap.erase("…");
strmap.erase("'");//strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");strmap.erase("");

}



//已完成,已验证
void addspace(string s1)
{
char c;
ifstream infile(s1.c_str());
while(infile.get(c))
{if(c != '\n') str1 += c; }
infile.close();
ofstreamoutfile(s1.c_str(),std::ios::in|std::ios::out|std::ios::trunc);
outfile<<str1;
outfile.close();
}


//读取str1
void Map()
{
string   tem;
int i=0;

while(i != str1.length())
{
switch(str1[i])
{
case ' ':
case ' ':
i++;
OK=true;
break;


case '~': //去除基本符号
case '!':
case '@':
case '_':
case '#':
case '$':
case '%':
case '^':
case '&':
case '*':
case '(':
case ')':
case '+':
case '|':
case '`':
case '·':
case '!':
case '¥':
case '……':
case '(':
case ')':
case '——':
case '-':
case '=':
case '、':
case '{':
case '}':
case '【':
case '】':
case ':':
case ':':
case '“':
case '”':
case '‘':
case '’':
case '《':
case '》':
case '>':
case '<':
case '?':
case '?':
case '\\':
case '[':
case ']':
case ',':
case ',':
case ';':
case ';':
case '。':
i++;
break;



case '/': //如果为 '/'
OK=false;
if(strmap.find(tem) != strmap.end())
{ strmap.find(tem)->second += 1;}
else
strmap[tem]=1;

i++;
tem = string();
break;




default: //默认情况下
if (OK == true)
{
tem += str1[i];
i++;
}

else
i++;

break;
}
}
}



void CNo1Dlg::MapPrint() // map 的显示函数
{
ofstreamoutf("tem.txt",std::ios::in|std::ios::out|std::ios::trunc);
ISMap::iterator ispos(aftertem.end());
CString forprint;int i=1;
outf<<setw(10)<<"TOP  "<<setw(5)<<"频数"<<setw(5)<<", "<<setw(5)<<"词"<<endl<<endl;
for (ispos--;ispos != aftertem.begin();ispos--)
{
forprint.Format("%d,%s!!!",ispos->first,ispos->second.c_str());
GetDlgItem(IDC_OUTPUT)->SetWindowText(forprint);
outf<<setw(10)<<i<<"  "<<setw(5)<<ispos->first<<setw(5)<<", "<<setw(5)<<_T(ispos->second)<<endl;
i++;
}
outf<<setw(10)<<i<<"  "<<setw(5)<<ispos->first<<setw(5)<<", "<<setw(5)<<_T(ispos->second)<<endl;

outf.close();


ifstream inf("tem.txt");
char c;CString s(CString());
while(inf.get(c))
{
s += c;
}

GetDlgItem(IDC_OUTPUT)->SetWindowText(s);
}



void CNo1Dlg::OnReadtxt() 
{
// TODO: Add your control notification handler code here
ShellExecute(NULL,"open","tem.txt",NULL,NULL,SW_SHOWNORMAL);
}



void DoEx()
{

SIMap::iterator sipos(strmap.begin());

for(;sipos != strmap.end();sipos++)
{
aftertem.insert(make_pair(sipos->second,_T(sipos->first)));
}

}






void fullthepath()
{
CString temppath(CString());
int i=0;
for(;i < filepath.GetLength();i++ )
{
if ( filepath.GetAt(i) != '\\')
{
temppath += filepath.GetAt(i);
}
else 
{ temppath += "\\\\";//[++y,'/'] ;
}
}
filepath = temppath;
}




void CNo1Dlg::OnOpenfile() 
{
// TODO: Add your control notification handler code here
remove("tem.txt");
remove("Test_result.txt");
initall();
CString cs=L"";
TCHAR currentdir[1024]={0};
GetCurrentDirectory(1024,currentdir);
cs=currentdir;


CFileDialog dlg(TRUE,
NULL,
NULL,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
(LPCTSTR)_TEXT("txt文件|*.txt||"),
NULL
);

if(dlg.DoModal()==IDOK)
    {
        filepath = dlg.GetPathName();//文件名保存在了FilePathName里
fullthepath();
    }
     
else
    {
MessageBox("输入有误!");
    }
::SetCurrentDirectory(currentdir);
}


void CNo1Dlg::OnCancle() 
{
// TODO: Add your control notification handler code here
CDialog::OnCancel();
}



void initall()
{

str1=" ";
OK = false;
strmap.clear();
aftertem.clear();

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值