吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 956|回复: 4
收起左侧

[经验求助] C++狗屁不通文章生成器读取中文乱码

[复制链接]
红月亮 发表于 2024-3-13 18:40
70吾爱币
本帖最后由 红月亮 于 2024-3-13 19:41 编辑

c++代码如下,从article.txt读取的中文带有乱码,输入的启动词也为乱码,代码与文章的编码均为utf_8,在VsCode使用mingw64编译
[C++] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
 
// 类Wordpair用于存储前缀词和对应的后缀词列表
class Wordpair
{
private:
    vector<string> suffix; // 后缀词列表
    vector<int> freq;      // 对应后缀词的频率列表
 
public:
    string prefix; // 前缀词
    int length;    // 后缀词列表的长度
 
    // 默认构造函数
    Wordpair()
    {
        this->prefix = "";
        this->length = 0;
    }
 
    // 构造函数,初始化前缀词和一个后缀词
    Wordpair(string prefix, string suffix)
    {
        this->prefix = prefix;
        this->suffix.push_back(suffix);
        this->freq.push_back(1);
        this->length = 1;
    }
 
    // 检查给定的词是否在后缀词列表中
    int hasRecord(string word);
 
    // 在后缀词列表中添加一个词
    void pushRecord(string word);
 
    // 获取频率最高的后缀词
    string maxFreq();
};
 
// 检查给定的词是否在后缀词列表中,如果在,返回其索引,否则返回-1
int Wordpair::hasRecord(string word)
{
    for (int i = 0; i < this->length; i++)
    {
        if (word == this->suffix[i])
        {
            return i;
        }
    }
    return -1;
}
 
// 在后缀词列表中添加一个词,如果该词已存在,增加其频率
void Wordpair::pushRecord(string word)
{
    int num = this->hasRecord(word);
    if (num == -1)
    {
        this->suffix.push_back(word);
        this->freq.push_back(1);
        this->length++;
    }
    else
    {
        this->freq[num]++;
    }
}
 
// 获取频率最高的后缀词
string Wordpair::maxFreq()
{
    int maxIndex = 0;
    int maxFreq = this->freq[0];
 
    for (int i = 1; i < length; i++) // 从1开始,因为0已经初始化了
    {
        if (freq[i] > maxFreq)
        {
            maxIndex = i;
            maxFreq = freq[i];
        }
    }
    return this->suffix[maxIndex];
}
 
// 从指定路径读取文章
string getArticle(string path)
{
    ifstream file(path);
    string temp, article = "";
    if (!file.is_open())
    {
        cout << "读取文件出错!" << endl;
        return "";
    }
    while (getline(file, temp))
    {
        article.append(temp);
    }
    file.close();
    return article;
}
 
// 在 vector 列表中新增一个新的前缀词和对应的后缀词
void createPrefix(vector<Wordpair> &pairList, string prefix, string suffix)
{
    Wordpair temp(prefix, suffix);
    pairList.push_back(temp);
}
 
// 将文章转化为前缀词和后缀词的列表
void articleToWordpair(vector<Wordpair> &pairList, string &article, int prefixLen, int suffixLen)
{
    for (int i = 0; i < article.size() / ((prefixLen + suffixLen) * 3); i++)
    {
        string slide, prefixTemp, suffixTemp;
        bool found = false;
 
        slide = article.substr(i * (prefixLen + suffixLen) * 3, (prefixLen + suffixLen) * 3);
        prefixTemp = slide.substr(0, prefixLen * 3);
        suffixTemp = slide.substr(prefixLen * 3, suffixLen * 3);
 
        for (auto &pair : pairList)
        {
            if (prefixTemp == pair.prefix)
            {
                pair.pushRecord(suffixTemp);
                found = true;
                break; // 找到后立即退出循环
            }
        }
 
        if (!found)
        {
            createPrefix(pairList, prefixTemp, suffixTemp);
        }
    }
}
 
// 生成新的文章
string generateArticle(vector<Wordpair> &pairList, string startWord, int prefixLen, int suffixLen)
{
    string article = startWord, prefix = startWord, suffix;
 
    while (1) // 无限循环,直到新生成的后缀没有对应的后缀为止
    {
        bool found = false;
        for (auto &pair : pairList)
        {
            if (prefix == pair.prefix)
            {
                suffix = pair.maxFreq();
                found = true;
                break;
            }
        }
 
        if (!found)
        {
            return article;
        }
 
        article.append(suffix);
        prefix = suffix;
    }
}
 
int main()
{
    string path, article, startword, newarticle;
    vector<Wordpair> pairList;
    int prefixLen, suffixLen;
    path = "article.txt";
    cout << "请输入前缀长度、后缀长度和起始词,以空格分隔:" << endl;
    cin >> prefixLen >> suffixLen >> startword;
    article = getArticle(path);
    articleToWordpair(pairList, article, prefixLen, suffixLen);
    newarticle = generateArticle(pairList, startword, prefixLen, suffixLen);
    cout << newarticle;
    return 0;
}

最佳答案

查看完整内容

代码中并没有直接显示中文乱码处理的部分,但通常乱码问题是由于编码不一致导致的。在C++中,处理中文乱码通常需要确保你的文件、输入/输出流以及字符串处理都使用相同的编码格式,通常是UTF-8。 在C++中处理中文文本时,你需要注意以下几点: 文件编码:确保你的文本文件(如article.txt)是以UTF-8编码保存的。 流设置:如果你在C++中使用ifstream或ofstream来读取或写入文件,需要确保流以正确的编码方式打开 ...

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

pp67868450 发表于 2024-3-13 18:40
代码中并没有直接显示中文乱码处理的部分,但通常乱码问题是由于编码不一致导致的。在C++中,处理中文乱码通常需要确保你的文件、输入/输出流以及字符串处理都使用相同的编码格式,通常是UTF-8。

在C++中处理中文文本时,你需要注意以下几点:

    文件编码:确保你的文本文件(如article.txt)是以UTF-8编码保存的。

    流设置:如果你在C++中使用ifstream或ofstream来读取或写入文件,需要确保流以正确的编码方式打开。对于UTF-8编码,通常不需要特殊设置,因为UTF-8是兼容ASCII的,但如果你在处理非ASCII字符时遇到问题,可以尝试设置locale。

    字符串处理:使用标准C++字符串类型std::string时,UTF-8编码的字符串是可以安全存储的,只要你不对字符串进行字节级别的操作(如直接访问某个字符的ASCII值)。如果你需要对字符串中的每个字符进行操作(比如Unicode字符处理),那么你可能需要使用支持Unicode的字符串库,比如ICU库。

    控制台输出:控制台输出中文乱码的问题通常是由于控制台的编码设置与你的程序使用的编码不匹配导致的。确保你的控制台也使用UTF-8编码。在某些操作系统和IDE中,你可能需要设置控制台的编码。

    宽字符与多字节字符:如果你遇到特定平台或库的兼容性问题,可以考虑使用宽字符wchar_t和多字节字符处理函数。但这通常只在需要兼容老旧平台或特定库时使用,现代C++代码更倾向于使用UTF-8编码的std::string。

针对你的代码,如果你只是希望在控制台输出中文时不出现乱码,那么你可能只需要设置控制台的编码为UTF-8。但请注意,这不是一个通用的解决方案,因为不同的操作系统和IDE有不同的设置方法。

如果你正在使用Windows控制台,并且你的程序在输出中文时出现乱码,你可以尝试以下步骤:

    打开命令提示符(CMD)或PowerShell。
    右键点击标题栏,选择“属性”。
    在“选项”标签页中,找到“字体”部分,选择一个支持中文的字体,如“新宋体”。
    在“代码页”部分,选择“65001”(UTF-8编码)。
    应用并保存设置。

然后重新运行你的程序,看看是否解决了乱码问题。

如果你是在IDE(如Visual Studio、CLion等)中运行程序,那么你可能需要在IDE的设置中查找与控制台编码相关的选项,并进行相应的设置。

对于文件读取和写入,只要你的文件是以UTF-8编码保存的,并且你没有对读取到的字符串进行字节级别的操作,通常不应该出现乱码问题。如果仍然出现问题,那么可能需要检查你的文件是否确实是以UTF-8编码保存的,以及你的程序是否在读取文件时使用了正确的编码。
 楼主| 红月亮 发表于 2024-3-14 10:53
pp67868450 发表于 2024-3-14 09:09
代码中并没有直接显示中文乱码处理的部分,但通常乱码问题是由于编码不一致导致的。在C++中,处理中文乱码 ...

在使用VsCode的集成终端时。终端的编码默认为UTF-8,但是当我在终端输入"startword"并重新输出时,startword输出的中文文本变为为'pp'。但是第一个cout语句中输出的中文是正常的,但是当我在编码为GBK的cmd中输入"startword"并重新输出时,输出的startword是正常的,但是第一个cout语句输出文本为乱码,我尝试将代码文件和article.txt文件的编码都改为GBK,但是在使用VsCode的集成终端输出时,会出现乱码。但在cmd中直接运行.exe文件时正常运行,请问有什么方法可以使得在UTF8中输入正常,或者将VsCode的集成终端编码改为GBK?
pp67868450 发表于 2024-3-14 11:11
[C++] 纯文本查看 复制代码
1
const char* chineseText = "这是一段中文文本";

当从文件读取或向文件写入中文时,确保文件是以UTF-8编码打开的。在C++中,你可以使用<fstream>库来处理文件I/O。
[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
#include <fstream> 
#include <iostream> 
#include <string> 
   
int main() { 
    std::ifstream inputFile("example.txt", std::ios::binary); // 以二进制模式打开文件 
    std::string content((std::istreambuf_iterator<char>(inputFile)), 
                         std::istreambuf_iterator<char>()); 
    inputFile.close(); 
       
    std::cout << content << std::endl; // 输出内容到控制台 
    return 0; 
}

注意,这里使用了std::ios::binary来确保文件以二进制模式打开,这通常可以避免在文本模式和二进制模式之间转换时可能出现的编码问题。

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
红月亮 + 1 + 1 谢谢@Thanks!

查看全部评分

VnYzm 发表于 2024-3-14 13:14
C++有一套处理unicode宽字符串的机制wstring,输入输出估计得通过对应的wcin、wcout来完成。然后读取中文文件应该也是先读成字节串然后用utf-8转wstring的方法。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-7-29 09:22

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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