欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用C++實現(xiàn)簡單的文章生成器

 更新時間:2024年03月22日 11:28:31   作者:武的階乘  
這篇文章主要為大家詳細介紹了鵝湖使用C++實現(xiàn)簡單的狗屁不通文章生成器,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以了解下

1 前言

繼上次【C++】狗屁不通文章生成器之后,很久不想看一眼這個代碼,因為當時寫這個代碼深受中文字符的處理煩惱。而且現(xiàn)在回看,程序的模塊化、可讀性使我大受震驚,是在想不到當時的我為什么要這樣做。于是昨天無心工作,想到了把這堆樂色改進一下,至少做到能看的水平。遂記之。

2 改進

2.1 字詞的前后關系

為了表示字詞的前后關系,即將句子劃分為前綴詞+后綴詞的關系,依然需要定義一個class wordpair,這里去除一些數(shù)據(jù)上的冗余,強化了類的封閉性。

class wordpair
{
private:
    string preword;            // 前綴
    map<string, int> sufwords; // 后綴,次數(shù)
    int count;                 // 總次數(shù)

public:
    wordpair(string pre);
    wordpair(string pre, string suf);
    wordpair(string pre, map<string, int> suf);
    ~wordpair();
    string getPreword() const;
    map<string, int> getSufwords() const;
    void setPreword(string pre);
    void setSufwords(map<string, int> suf);
    string toJson() const;

    void addSufword(string suf);
    string chooseSufword() const;
};

采用map記錄后綴的出現(xiàn)次數(shù),數(shù)據(jù)的結構性更強,也易于查找。記錄所有后綴出現(xiàn)的總次數(shù)是為了在生成文章時選擇后綴提供方便(具體作用看3.1.3)

2.2 文章生成系統(tǒng)

將太多的操作塞進main()函數(shù)的做法不夠美觀,且容易忘記各個部分的功能。于是這里將文章生成的功能抽象出來,作為一個類。主要的工作是記錄所有的字詞對、記錄生成的、文件流操作、文章生成等邏輯。

class createArticle
{
private:
    vector<wordpair> wordpairlist;
    string article;

public:
    createArticle();
    ~createArticle();

    void importWords(string filename, int len_pre = 1, int len_suf = 1);
    void exportWords(string filename);
    void addWordPair(string pre, string suf);
    void generateArticle(string startword, int lenout = 10000);
    void printArticle(string filename);
};

3 實現(xiàn)(部分)

由于大多函數(shù)都很簡單,這里只貼出部分比較重要的函數(shù)。

3.1 class wordpair

除去構造函數(shù)、類成員輸出輸入等函數(shù),我們直接進入主題。

3.1.1 轉化為 json

這個函數(shù)主要是為了輸出格式化的詞對,而文本文件中json格式的結構性且簡單。

ps: 其實這個函數(shù)不太重要,主要目的是檢查。不過也可以為直接讀詞對做準備(雖然這里沒有從文件導入詞對的功能)

string wordpair::toJson() const
{
    string str = "\"";
    str += this->preword + "\" : {";

    for (auto &it : this->sufwords)
    {
        str += "\"" + it.first + "\"" + ":" + to_string(it.second) + ",";
    }
    str += "}";
    return str;
}

效果演示:

3.1.2 添加后綴詞

添加后綴的函數(shù),邏輯是:

if 這個后綴已經(jīng)有記錄 then count++;

else 添加新的后綴到map中

void wordpair::addSufword(string suf)
{
    for (auto &it : this->sufwords)
    {
        if (it.first == suf)
        {
            it.second++;
            return;
        }
    }
    this->sufwords[suf] = 1; // if the word is not in the map, add it with a count of 1
}

3.1.3 選擇后綴詞

這個函數(shù)的主要功能是從眾多后綴詞中選取一個(語料庫大的話就會多啦),選擇的策略是隨機數(shù)的方案,類似于轉盤抽獎。實現(xiàn)方法如下:

string wordpair::chooseSufword() const
{
    if (this->sufwords.size() == 1)//如果只有一個后綴詞就直接輸出,減少算力負擔
    {
        return this->sufwords.begin()->first;
    }
    else
    {
        // 隨機選擇一個后綴詞
        random_device rd;
        ranlux48 engine(rd());
        uniform_int_distribution<> dist(0, this->count);//在類中定義了count,這里就省掉了遍歷
        int random_number = dist(engine);//產生一個隨機數(shù)

        std::string result;
        for (auto &it : this->sufwords)//抽獎
        {
            if (random_number < it.second)
            {
                result = it.first;
            }
            else
                random_number -= it.second;
        }
        return result;
    }
}

3.2 class createArticle

3.2.1文本分割

vector<string> charlist = splitchar(filestr);//先將從文件讀到的字符串分割
    string preword = "", sufword = "";
    for (int i = 0; i < charlist.size() - len_suf - len_pre; i++)//每次向后移動一個字符,進行切割
    {
        preword = "", sufword = "";
        for (int j = i; j < i + len_pre + len_suf; j++)
        {
            if (j - i < len_pre)
            {
                preword += charlist[j];//從第i個字符開始,到第i+len_pre個字符連接起來作為前綴
            }
            else
            {
                sufword += charlist[j];//從第i+len_pre個到字符開始,到第i+len_pre+len_suf個字符連接作后綴
            }
        }
        this->addWordPair(preword, sufword);//添加進wordpairlist
    }

3.2.2生成文章

/*
startword——啟動詞
lenout——長度限制(避免無限循環(huán))
*/
void createArticle::generateArticle(string startword, int lenout)
{
    this->article += startword;
    bool stop; // 加一個停止標志,當無法匹配到前綴時停止
    int prewordlen = this->wordpairlist.front().getPreword().length();
    int sufwordlen = this->wordpairlist.front().getSufwords().begin()->first.length();
    string lastword;
    for (int i = 0; i < lenout; ++i)
    {
        stop = true;
        if (this->article.length() >= prewordlen) // 如果文章長度大于詞對中前綴詞的長度,則直接拼接
        {
            lastword = this->article.substr(this->article.length() - prewordlen, prewordlen);//article最后的len_pre個字符,作為前綴
            for (auto &it : this->wordpairlist)
            {
                if (it.getPreword() == lastword)//通過lastword匹配詞對
                {
                    this->article += it.chooseSufword();
                    stop = false;
                    break;
                }
            }
            if (stop)//遍歷了一邊詞對的list沒有匹配的詞對時,退出循環(huán)
                break;
        }
        else//啟動詞長度小于詞對前綴的情況,例如詞對分割為3+2時,啟動詞長度為2,小于前綴長度3,無法正常拼接,于是走此處
        {
            lastword = this->article;
            for (auto &it : this->wordpairlist)//同上遍歷
            {
                int position = it.getPreword().find(lastword);
                if (position != string::npos)
                {
                    this->article += (it.getPreword() + it.chooseSufword()).substr(position+lastword.length(), sufwordlen);//先將前后綴連接,再從匹配到的位置開始截取
                    stop = false;
                    break;
                }
            }
            if (stop)
                break;
        }
    }
}

4演示

4.1 wordpair(3x2), 啟動詞(春天)

4.2 wordpair(2x1),啟動詞(春天)

4.3 wordpair(2x2),啟動詞(春天)

可見,加了長度限制的重要性。

5總結

目前,這個版本的處理方法不會出現(xiàn)中文亂碼,即使是中英文混合字符串也能正確讀取和分割。而且拼接時采用的隨機數(shù)策略,在語料庫足夠大的情況下可以有較好的靈活性。但是任然無法產出具備可讀性的文章。

到此這篇關于使用C++實現(xiàn)簡單的文章生成器的文章就介紹到這了,更多相關C++文章生成器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++瓦片地圖坐標轉換的實現(xiàn)詳解

    C++瓦片地圖坐標轉換的實現(xiàn)詳解

    常見的瓦片地圖有矩形、菱形、正六邊形幾種。此文章主要討論菱形瓦片,也就是大家常說的2.5D,斜45度瓦片地圖。比如《紅警2》、《帝國時代2》都是采用這種技術
    2022-09-09
  • C與匯編混合編程的實現(xiàn)示例

    C與匯編混合編程的實現(xiàn)示例

    本文主要介紹了C與匯編混合編程的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • 擴展KMP算法(Extend KMP)

    擴展KMP算法(Extend KMP)

    我們這里說的KMP不是拿來放電影的(雖然我很喜歡這個軟件),而是一種算法。KMP算法是拿來處理字符串匹配的。今天我們談到的是對KMP算法的拓展
    2014-08-08
  • C/C++中可變參數(shù)的用法詳細解析

    C/C++中可變參數(shù)的用法詳細解析

    可變參數(shù)的使用方法遠遠不止以下介紹的幾種,不過在C,C++中使用可變參數(shù)時要小心,在使用printf()等函數(shù)時傳入的參數(shù)個數(shù)一定不能比前面的格式化字符串中的’%’符號個數(shù)少,否則會產生訪問越界,運氣不好的話還會導致程序崩潰
    2013-09-09
  • C++實現(xiàn)簡單的信息管理系統(tǒng)

    C++實現(xiàn)簡單的信息管理系統(tǒng)

    這篇文章主要為大家介紹了C++實現(xiàn)簡單的信息管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-04-04
  • C語言中sizeof函數(shù)踩過的坑總結

    C語言中sizeof函數(shù)踩過的坑總結

    sizeof是C語言的一種單目操作符,如C語言的其他操作符++、--等。它并不是函數(shù)。sizeof操作符以字節(jié)形式給出了其操作數(shù)的存儲大小。操作數(shù)可以是一個表達式或括在括號內的類型名。操作數(shù)的存儲大小由操作數(shù)的類型決定
    2022-04-04
  • C語言詳細講解樹狀數(shù)組與線段樹

    C語言詳細講解樹狀數(shù)組與線段樹

    顧名思義,樹狀數(shù)組就是用數(shù)組來模擬樹形結構唄。那么衍生出一個問題,為什么不直接建樹,因為樹狀數(shù)組能處理的問題就沒必要建樹。線段樹是一種二叉搜索樹,與區(qū)間樹相似,它將一個區(qū)間劃分成一些單元區(qū)間,每個單元區(qū)間對應線段樹中的一個葉結點
    2022-04-04
  • C++ for循環(huán)與nullptr的小知識點分享

    C++ for循環(huán)與nullptr的小知識點分享

    這篇文章主要是來和大家介紹一些C++中的小知識點,本文分享的是for循環(huán)與nullptr,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-05-05
  • C語言數(shù)據(jù)結構中二分查找遞歸非遞歸實現(xiàn)并分析

    C語言數(shù)據(jù)結構中二分查找遞歸非遞歸實現(xiàn)并分析

    這篇文章主要介紹了C語言數(shù)據(jù)結構中二分查找遞歸非遞歸實現(xiàn)并分析的相關資料,需要的朋友可以參考下
    2017-03-03
  • C語言new操作的安全性分析

    C語言new操作的安全性分析

    這篇文章主要介紹了C語言new操作的安全性分析,需要的朋友可以參考下
    2014-07-07

最新評論