找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 4555|回复: 0

ScorePP-用标准C++实现的自动分词评测程序

[复制链接]
发表于 2012-4-16 23:39:49 | 显示全部楼层 |阅读模式
         中文分词是自然语言处理的基础性关键问题,近一年来一直在进行着分词方面的研究。一开始用的是Sighan backoff 提供的用Perl脚本编写的分词打分程序Score。为了把用C++写的分词程序和评测程序无缝的结合在一起,同时也为了自动的分析分词中的错误原因,参考Score改写了在C++下的评测程序,我自己称它为ScorePP。
        为了分词很长时间都没有休息了。中午走出自动化所的食堂,不知道怎么的,突然想起来看了日历,发现生日就在今天。回想着半年的时间,天天都在跟文字打交道,天天为了提高分词的效果,绞尽脑汁。过的把时间都忘了。今年的生日又是跟往常一样,自己一个人过了。为了纪念这个重要的时间,把自己改写的分词评测程序,发布出来。如果对大家有所帮助,也算是很欣慰的一件事。也算是献给自己的生日礼物。
本分词评测程序有以下几点要注意的:
1 提供分词结果检查,即切分的数据总量要和标准的相同,不能多切,也不能少切。
2 有完善的评测指标接口:准确度、召回率、F值、未登录词比例、未登录词召回率、登录词召回率。
3 分词切分标志可以是空格,也可以是斜杠。

以下为程序源代码:

Score.h
  1. /********************************************************************
  2. * Copyright (C) 2012 Li Yachao
  3. * Contact: liyc7711@gmail.com or harry_lyc@foxmail.com
  4. *
  5. * Permission to use, copy, modify, and distribute this software for
  6. * any non-commercial purpose is hereby granted without fee, provided
  7. * that the above copyright notice appear in all copies and that both
  8. * that copyright notice.
  9. * It is provided "as is" without express or implied warranty.
  10. *
  11. * Version: 0.1
  12. * Last update: 2012-4-13
  13. *********************************************************************/
  14. /*********************************************************************
  15. 用于分析分词结果
  16. *********************************************************************/
  17. #ifndef SCORE_H
  18. #define SCORE_H
  19. #include <iomanip>
  20. #include <iostream>
  21. #include <fstream>
  22. #include <vector>
  23. #include <set>
  24. #include <string>
  25. namespace MyUtility
  26. {
  27.         struct ScoreItem
  28.         {
  29.                 int GoldTotal;
  30.                 int TestTotal;
  31.                 int TestCorrect;
  32.         };
  33.         class Score
  34.         {
  35.         public:
  36.                 /*如果报告、词典文件输入为空,则表示不用*/
  37.                 Score(const std::string& gold_file,const std::string& test_file,
  38.                           const std::string& dic_file ,const std::string& report_file="");
  39.                 Score();
  40.                 ~Score();
  41.                 void Clear();
  42.                 double GetRecall();
  43.                 double GetPrecise();
  44.                 double GetFMeasure();
  45.                 int GetTrueWords();
  46.                 int GetTestWords();
  47.                 double GetTestOOVRate();/*测试语料未登录词比例*/
  48.                 double GetOOVRecallRate();/*未登录词的召回率*/
  49.                 double GetIVRecallRate();/*登录词的召回率*/
  50.         private:
  51.                 std::ofstream fout;/*输出文件流*/
  52.                 //std::ofstream fout1;/*输出文件流*/
  53.                 std::string reportFile;/*报告结果件路径*/
  54.                 std::string goldFile;/*标准文件路径*/
  55.                 std::string testFile;/*测试文件路径*/
  56.                 std::string dictionaryFile;/*词典文件路径*/
  57.                 int totalOOVTokens ;/*未登录tokens数量*/
  58.                 int totalOOVCorrectTokens;/*正确的未登录tokens数量*/
  59.                 int totalIVCorrectTokens;/*正确的登录词tokens数量*/
  60.                 std::vector<std::string>goldLines;/*标准文件的文本行*/
  61.                 std::vector<std::string>testLines;/*测试文件的文本行*/
  62.                 std::vector<struct ScoreItem> listScore;/*每行的评测结果*/
  63.                 std::set<std::string> dictionaryList;/*词典数据结构*/
  64.                 /*************************************************/
  65.                 bool IsPrefix(const std::string &src, const std::string &prefix);
  66.                 bool Postfix(const std::string &src, const std::string &postfix);
  67.                 bool Init();
  68.                 bool InitDict(const std::string& filePath);/*初始化词典*/
  69.                 bool IsEntryExist(const char * entry);
  70.                 bool Parse(const std::vector<std::string>& gold_tokens,const std::vector<std::string>& test_tokens,struct ScoreItem& score);
  71.                 bool FileReader(const std::string& path,std::vector<std::string>& lines);
  72.                 void SplitByTokens(std::vector<std::string> &vecstr, const std::string &str, const std::string tokens[],const  int tokensnumber, bool withtoken);
  73.                
  74.         };
  75. }
  76. #endifScore.cpp
  77. #include "Score.h"
  78. namespace MyUtility
  79. {
  80.         Score::Score()
  81.         {
  82.                
  83.         }
  84.         Score::~Score()
  85.         {
  86.                 dictionaryList.clear();
  87.                 Clear();
  88.                 if(!fout.is_open())
  89.                 {
  90.                         fout.clear();
  91.                         fout.close();
  92.                 }
  93.         }
  94.                 /*  
  95.                 *************************************************
  96.                 功能   :评测分词结果的效果。
  97.                 参数   : gold_file标准的分词结果;test_file用户分词结果;dic_file词典文件;report_file报告文件
  98.                 返回值 :
  99.                 -------------------------------------------------
  100.                 备注   :
  101.                 -------------------------------------------------
  102.                 作者   : Li Yachao
  103.                 时间   : 2012-4-13
  104.                 *************************************************
  105.         */
  106.         Score::Score(const std::string& gold_file,const std::string& test_file,
  107.                           const std::string& dic_file  ,const std::string& report_file)
  108.         {
  109.                 goldFile = gold_file;
  110.                 testFile = test_file;
  111.                 dictionaryFile = dic_file ;
  112.                 if(report_file.empty())
  113.                 {
  114.                         reportFile="";
  115.                 }
  116.                 else
  117.                 {
  118.                         reportFile = report_file;
  119.                 }
  120.                 Clear();
  121.                 if(!Init())
  122.                 {
  123.                         std::cout<<"Use score [gold] [test] [dic] [report]"<<std::endl;
  124.                 }
  125.                
  126.         }
  127.         /*取得分词的准确度*/
  128.         double Score::GetPrecise()
  129.         {
  130.                 double total = 0;
  131.                 double total_c = 0;
  132.                 for(int i=0;i<listScore.size();i++)
  133.                 {
  134.                         total += listScore[i].TestTotal;
  135.                         total_c += listScore[i].TestCorrect;
  136.                 }
  137.                 if(total!= 0)
  138.                 {
  139.                         return total_c/total;
  140.                 }
  141.                 else
  142.                 {
  143.                         return -1;
  144.                 }
  145.         }
  146.         /*取得分词的召回率*/
  147.         double Score::GetRecall()
  148.         {
  149.                 double total = 0;
  150.                 double total_c = 0;
  151.                 for(int i=0;i<listScore.size();i++)
  152.                 {
  153.                         total += listScore[i].GoldTotal;
  154.                         total_c += listScore[i].TestCorrect;
  155.                 }
  156.                 if(total!= 0)
  157.                 {
  158.                         return total_c/total;
  159.                 }
  160.                 else
  161.                 {
  162.                         return -1;
  163.                 }
  164.         }
  165.         /*取得分词的F值*/
  166.         double Score::GetFMeasure()
  167.         {
  168.                 double a = GetPrecise();
  169.                 double b = GetRecall();
  170.                 if((a <= 0)&& (b <= 0))
  171.                 {
  172.                         return -1;
  173.                 }
  174.                 return 2*a*b/(a+b);
  175.         }
  176.         /*取得分词的标准切分数量*/
  177.         int Score::GetTrueWords()
  178.         {
  179.                 int val = 0;
  180.                 for(int i=0;i<listScore.size();i++)
  181.                 {
  182.                         val += listScore[i].GoldTotal;
  183.                 }
  184.                 return val;
  185.         }
  186.         /*取得分词的用户切分数量*/
  187.         int Score::GetTestWords()
  188.         {
  189.                 int val = 0;
  190.                 for(int i=0;i<listScore.size();i++)
  191.                 {
  192.                         val += listScore[i].TestTotal;
  193.                 }
  194.                 return val;
  195.         }
  196.         /*测试语料未登录词比例*/
  197.         double Score::GetTestOOVRate()
  198.         {
  199.                 double t = GetTrueWords();
  200.                 if(t != 0)
  201.                 {
  202.                         return totalOOVTokens/t;
  203.                 }
  204.                 else
  205.                 {
  206.                         return -1;
  207.                 }
  208.         }
  209.         /*未登录词的召回率*/
  210.         double Score:: GetOOVRecallRate()
  211.         {
  212.                 if(totalOOVTokens <= 0)
  213.                 {
  214.                         return 0;
  215.                 }
  216.                 else
  217.                 {
  218.                         return (double)totalOOVCorrectTokens/(double)totalOOVTokens;
  219.                 }
  220.         }
  221.         /*登录词的召回率*/
  222.         double Score::GetIVRecallRate()
  223.         {
  224.                 double t = (GetTrueWords() - totalOOVTokens);
  225.                 if(t==0)
  226.                 {
  227.                         return 0;
  228.                 }
  229.                 else
  230.                 {
  231.                         return (double)(totalIVCorrectTokens)/t;
  232.                 }
  233.         }
  234.         void Score::Clear()
  235.         {
  236.                 totalOOVTokens = 0;
  237.                 totalOOVCorrectTokens = 0;
  238.                 totalIVCorrectTokens = 0;
  239.                 goldLines.clear();
  240.                 testLines.clear();
  241.                 listScore.clear();
  242.                 listScore.clear();
  243.                 dictionaryList.clear();
  244.         }
  245.         bool Score::Init()
  246.         {
  247.                 if(!reportFile.empty())
  248.                 {
  249.                         fout.open(reportFile.c_str());
  250.                         if(!fout.is_open())
  251.                         {
  252.                                 return false;
  253.                         }
  254.                 }
  255.                 if(dictionaryFile.empty())
  256.                 {
  257.                         return false;
  258.                 }
  259.                 else
  260.                 {
  261.                         if(!InitDict(dictionaryFile))
  262.                         {
  263.                                 std::cout<<"Dict Empty!";
  264.                         }
  265.                 }
  266.                 if(!FileReader(goldFile,goldLines))
  267.                 {
  268.                         return false;
  269.                 }
  270.                 if(!FileReader(testFile,testLines))
  271.                 {
  272.                         return false;
  273.                 }
  274.                 if(goldLines.size() != testLines.size())
  275.                 {
  276.                         std::cerr <<"File lines size fault.";
  277.                         return false;
  278.                 }
  279.                 //fout1.open("error.txt");
  280.                 int line_size = goldLines.size();
  281.                 std::vector<std::string>gold_tokens;
  282.                 std::vector<std::string>test_tokens;
  283.                 std::string seg_flags[]={" ","/"};/*分词的切分标志可以是空格,也可以是斜杠*/
  284.                 for(int i=0;i<line_size;i++)
  285.                 {
  286.                         SplitByTokens(gold_tokens,goldLines[i],seg_flags,2,false);
  287.                         SplitByTokens(test_tokens,testLines[i],seg_flags,2,false);
  288.                         struct ScoreItem score;
  289.                         if(!Parse(gold_tokens,test_tokens, score))
  290.                         {
  291.                                 std::cerr<<"Parse error at line "<<i+1<<std::endl;
  292.                         }
  293.                         gold_tokens.clear();
  294.                         test_tokens.clear();
  295.                         /*********Score评分************/
  296.                         listScore.push_back(score);
  297.                         /*S****************************/
  298.                 }
  299.                 if(!reportFile.empty())
  300.                 {
  301.                         fout<<"/**************************************************/"<<std::endl ;
  302.                        
  303.                         fout<<"True Word Count :"<<GetTrueWords()<<std::endl ;
  304.                         fout<<"Test Word Count :"<<GetTestWords()<<std::endl ;
  305.                         fout<<std::fixed<<std::setprecision(4)<<"Precision:"<<GetPrecise()<<std::endl<<"Recall:"<<GetRecall()<<std::endl<<"F Measure:"<<GetFMeasure()<<std::endl ;
  306.                         fout<<"OOV Rate : "<<GetTestOOVRate()<<std::endl ;
  307.                         fout<<"OOV Recall Rate : "<<GetOOVRecallRate()<<std::endl ;
  308.                         fout<<"IV Recall Rate : "<<GetIVRecallRate()<<std::endl ;
  309.                 }
  310.         }
  311.         bool Score::Parse(const std::vector<std::string>& gold_tokens,const std::vector<std::string>& test_tokens, struct ScoreItem& score)
  312.         {
  313.                 if(gold_tokens.size() == 0 || test_tokens.size() == 0)
  314.                 {
  315.                         return false;
  316.                 }
  317.                 //totalGoldTokens += gold_tokens.size();
  318.                 /*****未登录词**************************/
  319.                 for(int i=0;i<gold_tokens.size();i++)
  320.                 {
  321.                         if(!IsEntryExist(gold_tokens[i].c_str()))
  322.                         {
  323.                                 totalOOVTokens ++;
  324.                         }
  325.                 }
  326.                 /******************************/
  327.                 std::vector<bool>gold_val;
  328.                 /*****************************/
  329.                 score.GoldTotal = gold_tokens.size();
  330.                 score.TestCorrect = test_tokens.size();
  331.                 score.TestTotal = test_tokens.size();
  332.                 /*****************************/
  333.                 size_t length_gold = 0;
  334.                 size_t length_test = 0;
  335.                 size_t gold_last_success = 0;
  336.                 size_t gold_cur_pos = 0;
  337.                 size_t gold_cur_prior = 0;
  338.                 size_t test_last_success = 0;
  339.                 size_t test_cur_pos = 0;
  340.                 size_t test_cur_prior = 0;
  341.                 std::string buffer_gold = gold_tokens[0];
  342.                 std::string buffer_test = test_tokens[0];
  343.                 std::string str_out ="";
  344.                 for(int i=0;i<gold_tokens.size();i++)
  345.                 {
  346.                         length_gold += gold_tokens[i].length();
  347.                 }
  348.                 for(int i=0;i<test_tokens.size();i++)
  349.                 {
  350.                         length_test += test_tokens[i].length();
  351.                 }
  352.                 if(length_gold != length_test)
  353.                 {
  354.                         return false;/*切分有误,丢失了数据*/
  355.                 }
  356.                 if(!reportFile.empty())
  357.                 {
  358.                         fout << gold_tokens[gold_cur_pos];
  359.                         fout <<"\t";
  360.                 }
  361.                 if(gold_tokens[gold_cur_pos]  != test_tokens[test_cur_pos])
  362.                 {
  363.                         score.TestCorrect --;
  364.                         gold_val.push_back(false);
  365.                         if(!reportFile.empty())
  366.                         {
  367.                                 fout <<"|"<<test_tokens[test_cur_pos];
  368.                         }
  369.                 }
  370.                 else
  371.                 {
  372.                         if(!reportFile.empty())
  373.                         {
  374.                                 fout <<test_tokens[test_cur_pos];
  375.                         }
  376.                         //if((NULL != dic) && (dic->IsEntryExist(test_tokens[test_cur_pos].c_str())))
  377.                         //{
  378.                         //        //totalOOVCorrectTokens ++;
  379.                         //}
  380.                         gold_val.push_back(true);
  381.                 }
  382.                 if(!reportFile.empty())
  383.                 {
  384.                         fout<<std::endl ;
  385.                 }
  386.                 while(true)
  387.                 {
  388.                         if((gold_last_success < gold_cur_pos) && (gold_cur_prior < gold_cur_pos ))
  389.                         {
  390.                                 buffer_gold += gold_tokens[gold_cur_pos];
  391.                                 gold_cur_prior++;
  392.                                 if(!reportFile.empty())
  393.                                 {
  394.                                         fout <<gold_tokens[gold_cur_pos]<<"\t<"<<std::endl;
  395.                                        
  396.                                 }
  397.                                 gold_val.push_back(false);
  398.                         }
  399.                         if((test_last_success < test_cur_pos) && (test_cur_prior < test_cur_pos ))
  400.                         {
  401.                                 buffer_test += test_tokens[test_cur_pos];
  402.                                 test_cur_prior++;
  403.                                 if(!reportFile.empty())
  404.                                 {
  405.                                         fout <<"\t>"<< test_tokens[test_cur_pos]<<std::endl;
  406.                                 }
  407.                         }
  408.                         if((buffer_gold.length () == buffer_test.length()) && (buffer_gold == buffer_test))
  409.                         {
  410.                                 /************************************/
  411.                                 gold_cur_pos ++;
  412.                                 gold_last_success = gold_cur_pos;
  413.                                 gold_cur_prior = gold_cur_pos;
  414.                                 /************************************/
  415.                                 test_cur_pos ++;
  416.                                 test_last_success = test_cur_pos;
  417.                                 test_cur_prior = test_cur_pos;
  418.                                 /************************************/
  419.                                 if(gold_cur_pos < gold_tokens.size())
  420.                                 {
  421.                                         buffer_gold = gold_tokens[gold_cur_pos] ;
  422.                                         if(!reportFile.empty())
  423.                                         {
  424.                                                 fout << gold_tokens[gold_cur_pos];
  425.                                                 fout <<"\t";
  426.                                         }
  427.                                 }
  428.                                 if(test_cur_pos < test_tokens.size())
  429.                                 {
  430.                                         buffer_test = test_tokens[test_cur_pos] ;
  431.                                         if(buffer_gold != buffer_test)
  432.                                         {
  433.                                                 score.TestCorrect --;
  434.                                         }
  435.                                         else
  436.                                         {
  437.                                                 //if((NULL != dic) && (dic->IsEntryExist(test_tokens[test_cur_pos].c_str())))
  438.                                                 //{
  439.                                                 //        //totalOOVCorrectTokens ++;
  440.                                                 //}
  441.                                         }
  442.                                         if(!reportFile.empty())
  443.                                         {
  444.                                                 if(gold_tokens[gold_cur_pos] != test_tokens[test_cur_pos])
  445.                                                 {
  446.                                                         fout <<"|"<<test_tokens[test_cur_pos];
  447.                                                         gold_val.push_back(false);
  448.                                                 }
  449.                                                 else
  450.                                                 {
  451.                                                         fout <<test_tokens[test_cur_pos];
  452.                                                         gold_val.push_back(true);
  453.                                                 }
  454.                                                 fout <<std::endl ;
  455.                                         }
  456.                                 }
  457.                                 if((gold_cur_pos >= gold_tokens.size()) && (test_cur_pos >= test_tokens.size()))
  458.                                 {
  459.                                         break;
  460.                                 }
  461.                                 continue;
  462.                         }
  463.                         else if(buffer_gold.length () < buffer_test.length())
  464.                         {
  465.                                 /********************************************/
  466.                                 gold_cur_prior = gold_cur_pos;
  467.                                 gold_cur_pos ++;
  468.                         }
  469.                         else if(buffer_gold.length () > buffer_test.length())
  470.                         {
  471.                                 /********************************************/
  472.                                 //fout<<test_tokens[test_cur_pos]<<std::endl;
  473.                                 score.TestCorrect --;
  474.                                 test_cur_prior = test_cur_pos;
  475.                                 test_cur_pos ++;
  476.                         }
  477.                 }
  478.                 if(fout.is_open())
  479.                 {
  480.                         double precise = (double)score.TestCorrect/ (double)score.TestTotal;
  481.                         double recall = (double)score.TestCorrect / (double)score.GoldTotal;
  482.                         double f = 0;
  483.                         if((precise!=0) || (recall != 0))
  484.                         {
  485.                                 f = 2*precise*recall/(recall+precise);
  486.                         }
  487.                         fout<<std::fixed<<std::setprecision(4)<<"Precision:"<<precise<<" Recall:"<<recall<<" F Measure:"<<f<<std::endl ;
  488.                 }
  489.                 /**************************************************/
  490.                
  491.                 if(gold_tokens.size() != gold_val.size())
  492.                 {
  493.                         return false;
  494.                 }
  495.                 for(int i=0;i<gold_tokens.size();i++)
  496.                 {
  497.                         if(gold_val[i])
  498.                         {
  499.                                 if(IsEntryExist(gold_tokens[i].c_str()))
  500.                                 {
  501.                                         totalIVCorrectTokens++;
  502.                                 }
  503.                                 else
  504.                                 {       
  505.                                         totalOOVCorrectTokens++;
  506.                                 }
  507.                        
  508.                         }
  509.                         else
  510.                         {
  511.                                 //fout1<<gold_tokens[i]<<std::endl;
  512.                         }
  513.                 }
  514.                 //fout1<<std::endl ;
  515.                 //fout1.clear();
  516.                 return true;
  517.         }
  518.         bool Score::IsEntryExist(const char * entry)
  519.         {
  520.                 bool val = false;
  521.                 if(NULL == entry)
  522.                 {
  523.                return val;
  524.                 }
  525.                 std::set<std::string>::iterator pos;
  526.                 pos = dictionaryList.find(entry);
  527.                 if(pos != dictionaryList.end())
  528.                 {
  529.                     val = true;
  530.                 }
  531.                 else
  532.                 {
  533.                         /*处理藏文词条中后面有音节点的情况*/
  534.                 /*        if(Postfix(entry,"\xe0\xbc\x8b"))       
  535.                         {
  536.                                 tmp = tmp.substr(0,tmp.size() - 3);
  537.                         }
  538.                         else
  539.                         {
  540.                                 tmp += "\xe0\xbc\x8b";
  541.                         }*/
  542.                         pos = dictionaryList.find(entry);
  543.                         if(pos != dictionaryList.end())
  544.                         {
  545.                                 val = true;
  546.                         }
  547.                 }
  548.                
  549.                 return val;
  550.         }
  551.         /*初始化词典*/
  552.         bool Score::InitDict(const std::string& filePath)
  553.         {
  554.                 std::vector<std::string>lines;
  555.                 if(!FileReader(filePath,lines))
  556.                 {
  557.                         //std::cerr << "Open Dict [" << filePath << "] error!" << std::endl;
  558.                         return false;
  559.                 }
  560.                 for(int i=0;i<lines.size();i++)
  561.                 {
  562.                         dictionaryList.insert(lines[i]);
  563.                 }
  564.                 lines.clear();
  565.                 return true;
  566.         }
  567.         bool Score::FileReader(const std::string& path,std::vector<std::string>& lines)
  568.         {
  569.                 std::ifstream fin;
  570.                 fin.open(path.c_str());
  571.                 if(!fin.is_open())
  572.                 {
  573.                         std::cerr << "Open [" << path << "] error!" << std::endl;
  574.                         return false;
  575.                 }
  576.                 lines.clear();
  577.                 std::string utf8flag = "\xef\xbb\xbf";
  578.                 std::string utf16flag = "\xff\xfe";
  579.                 std::string myLine = "";
  580.                 int lineIndex = 1;
  581.                 while (getline(fin, myLine))
  582.                 {
  583.                         if(lineIndex == 1)
  584.                         {
  585.                                 if(IsPrefix(myLine,utf8flag))
  586.                                 {
  587.                                         myLine = myLine.substr(3,myLine.length() - 3);
  588.                                 }
  589.                                 else if(IsPrefix(myLine,utf16flag))
  590.                                 {
  591.                                         std::cerr <<"["<<path<<"], File type error,need UTF8 or ANSI file."<<std::endl;
  592.                                         return false;
  593.                                 }
  594.                         }
  595.                         lines.push_back(myLine);
  596.                         myLine.clear();
  597.                         lineIndex++;
  598.                         //std::cout<<lineIndex <<"\t";
  599.                 }
  600.                 fin.close();
  601.                 return true;
  602.         }
  603.         bool Score::Postfix(const std::string &src, const std::string &postfix)
  604.         {
  605.                 size_t s1=postfix.size();
  606.                 size_t s2=src.size();
  607.                 if( s1>s2 )
  608.                 {
  609.                         return false;
  610.                 }
  611.                 int i=(int)postfix.size()-1;
  612.                 int j=(int)src.size()-1;
  613.                 while( i>=0 && src[j]==postfix[i])
  614.                 {
  615.                         --i, --j;
  616.                 }
  617.                 return (i == -1);
  618.         }
  619.         bool Score::IsPrefix(const std::string &src, const std::string &prefix)
  620.         {
  621.                 size_t s1=prefix.size();
  622.                 size_t s2=src.size();
  623.                 if(s1 == 0)
  624.                 {
  625.                         return true ;
  626.                 }
  627.                 if( s1>s2 )
  628.                 {
  629.                         return false;
  630.                 }
  631.                 size_t i=0;
  632.                 while( i<s1 && src[i]==prefix[i])
  633.                 {
  634.                         ++i;
  635.                 }
  636.                 return (i == s1);
  637.         }
  638.         void Score::SplitByTokens(std::vector<std::string> &vecstr, const std::string &str, const std::string tokens[],const  int tokensnumber, bool withtoken)
  639.         {
  640.                 vecstr.clear();
  641.                 if((str.empty()) ||tokensnumber <=0 )
  642.                 {
  643.                         return  ;
  644.                 }
  645.                 std::string buffer="";
  646.                 int textLength = str.length();
  647.                 int start = 0;
  648.                 int offset = 0;
  649.                 while(start < textLength)
  650.                 {
  651.                         offset = textLength;
  652.                         int subLength =0;
  653.                         std::string tmp ="";
  654.                         for(int i=0;i< tokensnumber;i++)
  655.                         {
  656.                                 if(tokens[i].empty())
  657.                                 {
  658.                                         continue;
  659.                                 }
  660.                                 int curr = str.find(tokens[i],start);
  661.                                 if((curr >= 0) &&(curr < offset))
  662.                                 {
  663.                                         offset = curr;
  664.                                         subLength  = tokens[i].length();
  665.                                 }
  666.                         }
  667.                         if(start == offset)
  668.                         {
  669.                                 tmp = str.substr(start,0);
  670.                                 start = offset + subLength;
  671.                         }
  672.                         else if(start < offset)
  673.                         {
  674.                                 int len = 0;
  675.                                 if(withtoken)
  676.                                 {
  677.                                         len = subLength + ( offset - start);
  678.                                 }
  679.                                 else
  680.                                 {
  681.                                         len = ( offset - start);
  682.                                 }
  683.                                 tmp = str.substr(start,len);
  684.                                 start = (offset + subLength  );
  685.                         }
  686.                         /*这个影响多个空格连在一块,并且切分标志位空格的情况*/
  687.                         if(!tmp.empty())
  688.                         {
  689.                                 vecstr.push_back(tmp);
  690.                         }
  691.                 }
  692.         }
  693. }
复制代码



作者:Harry_lyc 发表于2012-4-13 17:05:58 原文链接

您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-5-4 14:20 , Processed in 0.026701 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表