【问题标题】:using wregex creates garbage output?使用 wregex 创建垃圾输出?
【发布时间】:2013-07-20 03:36:48
【问题描述】:

我使用正则表达式创建了一个简单的程序来标记文件。对于非 Unicode 内容,它可以正常工作。对于基于 Unicode 的内容,我制作了一个 wregex 版本,但这个版本会产生垃圾输出!

我试图在控制台屏幕上输出 Unicode 字符或字符串,而不是将它们存储在 map<wstring,int> 和 wostream 类型的文件中,以便值完整且正确。 运行应用程序后,包含提取的令牌的文件只包含垃圾!!!

这个程序有什么问题,我该如何解决?

#include "stdafx.h"

#include <iostream>
#include <regex>
#include <fstream>
#include <string>
#include <map>
using namespace std;

int main()
{
    string path="";    

    map<wstring, int> container;
    wifstream file("ftest.txt"); 
    wregex reg(_T("\\w+"));
    wstring s=_T("");
    while (file.good())
    {
        file>>s;
        for ( wsregex_iterator it (s.begin(), s.end(), reg),it_end; it != it_end; ++it)
        {
            container[(wstring)(*it)[0]]++ ;
        }

    }

    cout <<"\nDone..."<< endl;
    wofstream output("list.txt",ios::app);
    for (auto item : container)
    {
        //cout<<item.first<<" : "<<item.second<<endl;
        output<<item.first<<" : "<<item.second<<endl;
    }
    system("pause");
    return 0;
}

这是ftest.txt的内容:

بسم الله الرحمن الرحیم 
واشنگتن پست طی گزارشی اعلام کرد کنگره آمریکا برخلاف رویه سابق، ارسال مصوبه سالانه خود در زمینه تحریم های ایران به کاخ سفید را به تاخیر انداخت و به نظر می رسد انتخاب حسن روحانی به عنوان رئیس جمهوری جدید ایران علت این امر بوده است.
0 0 0 نظر
[-]     اندازه متن  [+]


به دنبال انتخاب حسن روحانی به عنوان رئیس جمهوری جدید ایران، کنگره آمریکا بر اساس برخی ملاحظات ارسال مصوبه سالانه خود در زمینه تحریم های ایران به کاخ سفید را به تاخیر انداخت.

这是list.txt里面的垃圾输出

0 : 3
1 : 1
14 : 1
16 : 1
26 : 1
27 : 1
5 : 2
50 : 1
6 : 1
7 : 1
ط : 475
طھ : 12
طھط : 20
طھطµظ : 1
طھظ : 10
طھغ : 2
ط² : 6
ط²ط : 6
ط²ظ : 6
ط³ : 5
ط³ط : 12
ط³طھ : 8
ط³طھط : 4
ط³طھظ : 2
ط³ظ : 10
ط³غ : 1
طµ : 1
طµط : 1
طµظ : 6
ط¹ط : 1
ط¹ظ : 8
ظ : 291
ع : 54
غ : 95
ï : 1

【问题讨论】:

  • 您确定您的文本文件是 UTF16 吗?而不是 UTF8?
  • 它的 UTF8!我现在该怎么办?
  • 要么将文件转换为 UTF16,要么找到另一个支持 UTF8 字符串的正则表达式库。

标签: c++ regex visual-c++ c++11 wofstream


【解决方案1】:

这个link 解决了我的问题。:) 对于便携式解决方案,请查看这个link

这是完美运行的最终代码:):

#include "stdafx.h"
#include <iostream>
#include <regex>
#include <fstream>
#include <string>
#include <map>
#include <fcntl.h> // for _wfopen_s
#include <io.h> //for _setmode


using namespace std;

int main()
{
    string path = "";    

    map<wstring, int> container;

     FILE* fp;
    _wfopen_s (&fp, L"ftest.txt", L"r");
    _setmode (_fileno (fp), _O_U8TEXT);

    wifstream file(fp);
    wregex reg(L"\\w+");

    wstring s = L"";

    while (file.good())
    {
        getline(file,s);    
        for ( wsregex_iterator it (s.begin(), s.end(), reg), it_end ; it != it_end ; ++it)
        {
            container[(wstring)(*it)[0]]++ ;
        }
    }

    cout <<"\nDone..."<< endl;

    fclose(fp);

    _wfopen_s (&fp, L"list.txt", L"w");
    _setmode (_fileno (fp), _O_U8TEXT);
    wofstream output(fp);

    for (auto item : container)
    {
        wcout<<item.first <<" : "<<item.second <<endl;
        //write output to list.txt
        output<<item.first <<" : "<<item.second <<endl;
    }
    fclose(fp);
    system("pause");
    return 0;
}

【讨论】:

    【解决方案2】:

    您需要将文件的 UTF8 编码转换为 std::wregex 使用的 UTF16 编码。

    使用 C++11,您可以使用 std::codecvt_utf8_utf16

    std::wifstream file("ftest.txt"); 
    file.imbue(std::locale(file.getloc(), new std::codecvt_utf8_utf16<wchar_t>());
    // "file" will now read UTF8 and output UTF16.
    

    Pre C++11 可以使用boost::locale 进行转换:

    例如

    auto w_s = boost::locale::utf_to_utf<char>(s);
    

    【讨论】:

    • 我收到以下错误:错误 1 ​​错误 C2061:语法错误:标识符 'codecvt_utf8_utf16' 错误 2 错误 C2665:'std::locale::locale':9 个重载都不能转换所有参数类型 3 IntelliSense:没有构造函数实例“std::locale::locale”与参数列表参数类型匹配:(std::locale, ) 4 IntelliSense:需要类型说明符 5 IntelliSense:类型名称是不允许 6 IntelliSense:需要一个表达式
    • 我正在使用 Visual Studio 2012 SP3
    猜你喜欢
    • 2012-01-06
    • 2014-12-18
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 1970-01-01
    • 2018-08-22
    相关资源
    最近更新 更多