【C++】狗屁不通文章生成器2.0

这篇具有很好参考价值的文章主要介绍了【C++】狗屁不通文章生成器2.0。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 前言

继上次【C++】狗屁不通文章生成器之后,很久不想看一眼这个代码,因为当时写这个代码深受中文字符的处理烦恼。而且现在回看,程序的模块化、可读性使我大受震惊,是在想不到当时的我为什么要这样做。于是昨天无心工作,想到了把这堆乐色改进一下,至少做到能看的水平。遂记之。

2 改进

2.1 字词的前后关系

为了表示字词的前后关系,即将句子划分为前缀词+后缀词的关系,依然需要定义一个class wordpair,这里去除一些数据上的冗余,强化了类的封闭性。

class wordpair
{
private:
    string preword;            // 前缀
    map<string, int> sufwords; // 后缀,次数
    int count;                 // 总次数

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记录后缀的出现次数,数据的结构性更强,也易于查找。记录所有后缀出现的总次数是为了在生成文章时选择后缀提供方便(具体作用看3.1.3)

2.2 文章生成系统

将太多的操作塞进main()函数的做法不够美观,且容易忘记各个部分的功能。于是这里将文章生成的功能抽象出来,作为一个类。主要的工作是记录所有的字词对、记录生成的、文件流操作、文章生成等逻辑

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 实现(部分)

由于大多函数都很简单,这里只贴出部分比较重要的函数。

3.1 class wordpair

除去构造函数、类成员输出输入等函数,我们直接进入主题。

3.1.1 转化为 json

这个函数主要是为了输出格式化的词对,而文本文件中json格式的结构性且简单。
ps: 其实这个函数不太重要,主要目的是检查。不过也可以为直接读词对做准备(虽然这里没有从文件导入词对的功能)

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

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

效果演示:
【C++】狗屁不通文章生成器2.0,C/C++,c++,算法

3.1.2 添加后缀词

添加后缀的函数,逻辑是:

  • if 这个后缀已经有记录 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 选择后缀词

这个函数的主要功能是从众多后缀词中选取一个(语料库大的话就会多啦),选择的策略是随机数的方案,类似于转盘抽奖。实现方法如下:

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);//产生一个随机数

        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——长度限制(避免无限循环)
*/
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没有匹配的词对时,退出循环
                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), 启动词(春天)

【C++】狗屁不通文章生成器2.0,C/C++,c++,算法

4.2 wordpair(2x1),启动词(春天)

【C++】狗屁不通文章生成器2.0,C/C++,c++,算法

4.3 wordpair(2x2),启动词(春天)

【C++】狗屁不通文章生成器2.0,C/C++,c++,算法可见,加了长度限制的重要性。

5总结

目前,这个版本的处理方法不会出现中文乱码,即使是中英文混合字符串也能正确读取和分割。而且拼接时采用的随机数策略,在语料库足够大的情况下可以有较好的灵活性。但是任然无法产出具备可读性的文章。文章来源地址https://www.toymoban.com/news/detail-849011.html

到了这里,关于【C++】狗屁不通文章生成器2.0的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AI仿写软件-仿写文章生成器

    AI仿写软件:高效出色的营销利器 作为互联网时代的营销人员,我们不仅需要品牌意识,还必须深谙营销技巧。万恶的时限压力使得我们不得不在有限的时间内输出更多的文本内容,以便吸引更多的关注。那么,如何解决这个问题呢?这时,AI仿写软件应运而生。本文将探索

    2024年02月08日
    浏览(99)
  • 神码ai伪文章生成器软件【php源码】

    大家好,本文将围绕python二级用哪个版本的软件展开说明,二级python 值不值得考是一个很多人都想弄明白的事情,想搞清楚python二级用什么软件需要先了解以下几个事情。 火车头采集ai伪原创插件截图: 问题一:安装python第一个遇到的问题就是有旧版或者新版的python 解决方

    2024年02月13日
    浏览(43)
  • AI写作智能生成器盘点,AI文章创作平台盘点

    AI人工智能原创文章写作平台已经逐渐成为越来越多企业和个人的必备工具。在这些平台中,搭画快写、触站、文心一言、轻微课和约触可以说是目前市场上非常受欢迎的几个平台。下面我们针对这些平台的主要特点进行详细分析。 AI智能写作平台推荐: 第1个:搭画快写 搭

    2024年02月16日
    浏览(86)
  • AIGC系列文章目录 第三章 AIGC 简单易用免费的AI图像生成器: Stable Diffusion

    目前亲测体验的AI图像生成器有NovelAI、MJ和Stable Diffusion。其中, 支持免费、无限生成、超高专业级画质 的只有 Stable Diffusion 。 Stable Diffusion 由 Stable Diffusion XL 提供支持,是一款最先进的工具,可以将您的想象力变为现实。 只需点击几下和简单的文本输入,您就可以创建令人

    2024年02月03日
    浏览(67)
  • C++设计模式-生成器(Builder)

    目录 C++设计模式-生成器(Builder) 一、意图 二、适用性 三、结构 四、参与者 五、代码 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。 当构造过程必须允许被

    2024年02月07日
    浏览(52)
  • 【16】c++设计模式——>建造者(生成器)模式

    建造者模式(Builder Pattern)是一种 创建型设计模式 ,它允许你构造复杂对象步骤分解。你可以不同的步骤中使用不同的方式创建对象,且对象的创建与表示是分离的。这样,同样的构建过程可以创建不同的表示。 在 C++ 中,建造者模式通常涉及到以下几个关键部分: 1. 产品

    2024年02月07日
    浏览(46)
  • 手机通话记录生成器在线,通话记录生成器下载,通话记录生成器app

    在了解通话记录生成器app的时候,铁牛通话记录生成器是一个为用户一键自动生成通话记录的app。如何得到“铁牛通话记录生成器”?在手机上进去佰渡baidu搜嗦,铁牛通话记录生成器,这几个字就可以,其他的不用输入。或者你看这个几个字母jp155再加上一个点com,手动输入

    2024年02月08日
    浏览(91)
  • python3 生成器与生成器表达式

    在 Python3 中,生成器表达式是一种语言结构,它可以快速地创建一个可迭代对象。生成器表达式类似于列表推导式,但使用圆括号而不是方括号,并且返回的是一个生成器对象而不是一个列表。 在 Python3 中,生成器表达式有两种类型:生成器函数和生成器表达式。 生成器函

    2024年02月02日
    浏览(86)
  • 关键词生成器在线-在线免费关键词生成器

    生成,什么是生成,生成就是根据你输入的一个生成成千上百的核心,围绕着你输入的核心词来生成的,优先生成大量用户搜索的,今天就给大家分享一款免费生成工具,生成的来源主要是用户都在搜索的词,相关搜索的

    2024年02月04日
    浏览(240)
  • ai论文生成器哪家好用?ai写作生成器免费

    AI论文生成器的好坏取决于具体的需求和场景,因此很难一概而论。以下是一些常见的AI论文生成器,供您参考: AIPaperPass:这是一款全智能自动写作平台,拥有自主模型并对外开放API接口。它可以根据用户提供的和要求,自动生成高质量的文章内容,并且支持批量写作

    2024年01月19日
    浏览(92)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包