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

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

  • 1 前言
  • 2 改进
    • 2.1 字词的前后关系
    • 2.2 文章生成系统
  • 3 实现(部分)
    • 3.1 class wordpair
      • 3.1.1 转化为 json
      • 3.1.2 添加后缀词
      • 3.1.3 选择后缀词
    • 3.2 class createArticle
      • 3.2.1文本分割
      • 3.2.2生成文章
  • 4演示
    • 4.1 wordpair(3x2), 启动词(春天)
    • 4.2 wordpair(2x1),启动词(春天)
    • 4.3 wordpair(2x2),启动词(春天)
  • 5总结

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;
}

效果演示:
在这里插入图片描述

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;}elserandom_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), 启动词(春天)

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述可见,加了长度限制的重要性。

5总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/282596.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言笔记:函数与程序结构

目录 ACM金牌带你零基础直达C语言精通-课程资料 一.作用域的基本概念 二.函数 1. 函数的定义和使用 2.为什么一定要有函数结构 3.形参与实参 4.函数的声明和定义 5.递归函数 此代码中递归函数执行流程&#xff1a; 练习&#xff1a;求斐波那契数列第n项的值&#xff1a; 欧几里…

CSDN个人简介优化 html font属性

CSDN个人简介优化 html font属性 个人简介个人简介优化字体21种样式选择字体大小设置4号字体 字体颜色设计渐变色&#xff08;可惜不能显示&#xff09; 字体加粗设置 <b>标签 个人简介 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光…

mysql查询条件包含IS NULL、IS NOT NULL、!=、like %* 、like %*%,不能使用索引查询,只能使用全表扫描,是真的吗???

不知道是啥原因也不知道啥时候, 江湖上流传着这么一个说法 mysql查询条件包含IS NULL、IS NOT NULL、!、like %* 、like %*%,不能使用索引查询&#xff0c;只能使用全表扫描。 刚入行时我也是这么认为的&#xff0c;还奉为真理&#xff01; 但是时间工作中你会发现还是走索引…

Games101Homework【0】Build an environment

Preface: I just want 放洋屁&#xff0c;and then learn graphics. So,This essay is born. I will show you the whole process of my study,Including the bugs I created. Cool lets begin! Download: BaiduNetworkDisk:from bilibili comment https://pan.baidu.com/…

Java后端八股-------并发编程

图中的 synchronized方法如果没有锁&#xff0c;那么可能会有超卖&#xff0c;数据错误等情况。 加锁之后会按顺序售卖。 synchronized的底层是monitor。 线程没有竞争关系的时候&#xff0c;引入了轻量级锁&#xff0c;当需要处理竞争关系的时候一定要用到重量级锁(线程的…

Java学习笔记(20)

可变参数 输入的参数数量不确定 底层就是把输入的参数放进一个数组里 只能写一个可变参数如果还有其他形参&#xff0c;可变参数要放在最后写 可变参数在底层就是一个数组 Collections Addall shuffle 练习 package exercise;import java.util.ArrayList; import java.util.C…

递增四元组

解法&#xff1a; 首先都可以想到dp[i]&#xff1a;第i个元素结尾的递增四元组有dp[i]个 然后发现有一组数据&#xff1a;2,3,6,1,5,8。会出现6结尾和5结尾的递增三元组&#xff0c;也就是未来的决策受过去影响&#xff0c;专业的说就是有后效性。需要强化约束条件&#xff0…

1.2 编译型语言和解释型语言的区别

编译型语言和解释型语言的区别 通过高级语言编写的源码&#xff0c;我们能够轻松理解&#xff0c;但对于计算机来说&#xff0c;它只认识二进制指令&#xff0c;源码就是天书&#xff0c;根本无法识别。源码要想执行&#xff0c;必须先转换成二进制指令。 所谓二进制指令&…

使用gimp制作头像

1.裁剪图像 &#xff08;1&#xff09;用GIMP打开图像。 &#xff08;2&#xff09;在工具箱中选中剪裁工具。 &#xff08;3&#xff09;在工具箱下边的工具选项中&#xff0c;勾选 固定→宽高比&#xff0c;并在下面的数值框中输入1:1。 &#xff08;4&#xff09;在图像中…

ginblog博客系统/golang+vue

ginblog博客系统 前台&#xff1a; 后台&#xff1a; Gitee的项目地址&#xff0c;点击进入下载 注意&#xff1a; 数据库文件导入在model里面&#xff0c;直接导入即可。 admin和front前后台系统记住修改https里的地址为自己的IP地址&#xff1a; front同上。

Springboot+vue的大学生选修选课系统的设计与实现(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的大学生选修选课系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;control…

显卡基础知识及元器件原理分析

显卡应该算是是目前最为火热的研发方向了&#xff0c;其中的明星公司当属英伟达。 当地时间8月23日&#xff0c;英伟达发布截至7月30日的2024财年第二财季财报&#xff0c;营收和利润成倍增长&#xff0c;均超市场预期。 财报显示&#xff0c;第二财季英伟达营收为135.07 亿美…

第十四届蓝桥杯JavaB组省赛真题 - 阶乘求和

/ 10^9考虑前九位&#xff0c;% 10^9保留后9位 解题思路: 求获取结果的后九位数字&#xff0c;需要对10^9取余&#xff0c;因为202320232023这个数字的阶乘太大&#xff0c;必须要减少计算量&#xff0c;因为当一个整数乘以10^9后对其取余&#xff0c;那么结果都为0。 所以我…

模拟B\S服务器(扩展知识点)

3.2 模拟B\S服务器(扩展知识点) 模拟网站服务器&#xff0c;使用浏览器访问自己编写的服务端程序&#xff0c;查看网页效果。 案例分析 准备页面数据&#xff0c;web文件夹。 复制到我们Module中&#xff0c;比如复制到day08中 我们模拟服务器端&#xff0c;ServerSocket类…

【C++ leetcode】双指针问题

1. 611. 有效三角形的个数 题目 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 题目链接 . - 力扣&#xff08;LeetCode&#xff09; 画图 和 文字 分析 判断是否是三角形要得到三边&#xff0c;由于遍历三边要套三层循环&#x…

VC++ error C1001: 内部编译器错误 c\error.h”,第 1291 行) 原因和解决

原因是使用模板时实现方法没写分号 #include <iostream>template <class T> class A { public:A() {};~A() {};void GetName() {return}; };int main(int argc, char* argv[]) {return 0; }

ARM 点灯

实现三个LED灯灰 .text .global _start _start: 使能GPIOE GPIOF的外设时钟 RCC_MP_AHB4ENSETR的第[4][5]设置为1即可使能GPIOE GPIOF时钟 LDR R0,0X50000A28 指定寄存器地址 LDR R1,[R0] 将寄存器原来的数值读取出来&#xff0c;保存到R1中 ORR R1,R1,#(0x3<<4) …

Python Flask框架 -- 加载静态文件

在项目中&#xff0c;一般都会把静态文件放在 static 目录下&#xff0c;如 images、css、js 等&#xff0c;html 放在 templates 目录下。 .py&#xff1a; from flask import Flask, render_templateapp Flask(__name__)app.route(/static) def static_demo():return rend…

鸿蒙Harmony应用开发—ArkTS-全局UI方法(时间滑动选择器弹窗)

以24小时的时间区间创建时间滑动选择器&#xff0c;展示在弹窗上。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 本模块功能依赖UI的执行上下文&#xff0c;不可在UI上下文不明确的地方使用&…

matlab simulink 二自由度机器手臂

1、内容简介 略 73-可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略