2013-07-21 4 views
1

Я создал простую программу с использованием regex для tokenize файла. Для контента nonUnicode он отлично работает. Для контента на основе Юникода я сделал версию wregex, но эта версия создает вывод мусора!Использование 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 
+0

Вы уверены, что ваш текстовый файл является UTF16? а не UTF8? – ronag

+0

его UTF8! Что мне теперь делать? – Breeze

+0

Либо вы конвертируете файл в UTF16, либо найдете другую библиотеку регулярных выражений, которая поддерживает строки UTF8. – ronag

ответ

2

Это 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; 
} 
0

Вам необходимо конвертировать из UTF8 кодирования файла в UTF16 кодировка, которую использует std::wregex.

С 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); 
+0

я получаю эти ошибки: Ошибки \t \t 1 Ошибка C2061: синтаксическая ошибка: идентификатор «codecvt_utf8_utf16 » Ошибки \t \t 2 ошибки C2665: 'станд :: локаль :: локали: ни один из 9 перегрузкам не может преобразовать все аргументы типы IntelliSense: нет экземпляра конструктора "станд :: локали :: локали" совпадает со списком аргументов типов аргументов: (станд :: локали, ) \t IntelliSense: ожидаемый в спецификатор типа IntelliSense: имя типа не разрешено ed IntelliSense: ожидается выражение – Breeze

+0

Я использую Visual Studio 2012 SP3 – Breeze

 Смежные вопросы

  • Нет связанных вопросов^_^