2013-04-03 19 views
5

Ich habe eine breite Zeichenfolge (Std :: wstring) in meinem Code, und ich muss breite Zeichen darin suchen.wstring :: find() funktioniert nicht mit nicht-lateinischen Symbolen?

ich find() Funktion für sie:

wcin >> str; 
    wcout << ((str.find(L'ф') != wstring::npos)? L"EXIST":L"NONE"); 

L'ф' ein kyrillischer Buchstabe ist.

Aber find() in demselben Anruf gibt immer npos zurück. In einem Fall mit lateinischen Buchstaben funktioniert find() korrekt.

Es ist ein Problem dieser Funktion? Oder mache ich etwas falsch?

UPD

ich MinGW verwenden und Quelle in UTF-8 speichern. Ich setze auch Locale mit setlocale(LC_ALL, "");. Code same wcout << L'ф'; funktioniert coorectly. aber gleich

wchar_t w; 
wcin >> w; 
wcout << w; 

funktioniert nicht korrekt.

Es ist seltsam. Zuvor hatte ich keine Probleme mit der Codierung, mit setlocale().

+0

Ich nehme dies nicht richtig durchgeführt werden kann direkt und diese Funktion wird nützlich sein: http://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx – BlackCat

+0

Warum? 'basic_string :: find()' arbeitet mit charT, das ist für einen Fall eines wstring - mit einem wcahr_t. 'L'ф 'ist ein wchar_t, oder? –

Antwort

3

Die Kodierung Ihrer Quelldatei und der Kodierung der Ausführungsumgebung kann sich stark unterscheiden. C++ übernimmt hierfür keine Gewähr. Sie können dies überprüfen, indem Sie den hexadezimalen Wert Ihrer Zeichenfolge ausgibt wörtliche:

std::wcout << std::hex << L"ф"; 

Bevor C++ 11, Sie, indem sie ihre Hex-Werte Nicht-ASCII-Zeichen im Quellcode verwenden:

"\x05" "five" 

C++ 11 bietet die Möglichkeit, ihre Unicode-Wert angeben, würde die in Ihrem Fall sein

L"\u03A6" 

Wenn du gehst voll C++ 11 (und Umgebung sorgt dafür, diese in UTF- * codiert werden), Sie können eine verwenden ny von char, char16_t oder char32_t, und zu tun:

const char* phi_utf8 = "\u03A6"; 
const char16_t* phi_utf16 = u"\u03A6"; 
const char32_t* phi_utf16 = U"\u03A6"; 
+0

Ich benutze MinGW, Windows-Konsole und speichere meine Quellen in UTF-8. Aber ich rufe setlocale (LC_ALL, ""); vor jeder Eingabe/Ausgabe. Ich nehme an, es verhindert ähnliche Probleme, oder? –

+0

Nein. Das Problem ist nicht das globale C-Gebietsschema des laufenden Programms, sondern die Übersetzung der Bytes, aus denen das PHP-Zeichen in der Quelldatei besteht. Diese Übersetzung ist implementierungsdefiniert und somit nicht portierbar. – rubenvb

1

Sie müssen die Codierung der Konsole eingestellt.

Dies funktioniert:

#include <iostream> 
#include <string> 
#include <io.h> 
#include <fcntl.h> 
#include <stdio.h> 

using namespace std; 

int main() 
{  
    _setmode(_fileno(stdout), _O_U16TEXT); 
    _setmode(_fileno(stdin), _O_U16TEXT); 
    wstring str; 
    wcin >> str; 
    wcout << ((str.find(L'ф') != wstring::npos)? L"EXIST":L"NONE"); 
    system("pause"); 
    return 0; 
} 
+0

Wenn ich dies in einer Windows-Konsole versuche und einen Eingabe-String eintippe und die Eingabetaste drücke, bleibt das Programm hängen (ich muss STRG + C drücken, um fortzufahren). –

+0

Ich benutze Windows 7 und Visual Studio 2012 und es funktioniert gut. –

+0

Ich benutze Windows 7 und VS2010 ... vielleicht gibt es einen Fehler in VS2010, der 2012 (?) Behoben wurde. –

0

, die wahrscheinlich eine Codierung Problem ist. wcin funktioniert mit einer Codierung, die sich von den Quellcodes Ihres Compilers unterscheidet. Versuche das ф in die Konsole/wcin einzugeben - es wird funktionieren. Versuchen Sie, das ф über wcout zu drucken - es wird ein anderes Zeichen oder gar kein Zeichen angezeigt.

Es gibt keine plattformunabhängige Möglichkeit, dies zu umgehen, aber wenn Sie auf Windows verfügbar sind, können Sie manuell die Konsole Codierung ändern, entweder mit dem chchp Kommandozeilen-Befehl oder programmatisch mit SetConsoleCP() (Eingang) und SetConsoleOutputCP() (Output).

Sie können auch die Codierung der Quelldatei/des Compilers ändern.Wie das gemacht wird, hängt von Ihrem Editor/Compiler ab. Wenn Sie MSVC verwenden, könnte diese Antwort Ihnen helfen: https://stackoverflow.com/a/1660901/2128694

+0

Nein, 'wcout << L'ф ';' funktioniert gut. –

1

std::wstring::find() funktioniert gut. Aber Sie müssen den Eingabe-String richtig lesen.

der folgende Code läuft auf Windows-Konsole in Ordnung (die Eingabe Unicode-String gelesen wird, mit ReadConsoleW() Win32 API):

#include <exception> 
#include <iostream> 
#include <sstream> 
#include <stdexcept> 
#include <string> 
#include <windows.h> 
using namespace std; 

class Win32Error : public runtime_error 
{ 
public: 
    Win32Error(const char* message, DWORD error) 
     : runtime_error(message) 
     , m_error(error) 
    {} 

    DWORD Error() const 
    { 
     return m_error; 
    } 

private: 
    DWORD m_error; 
}; 

void ThrowLastWin32(const char* message) 
{ 
    const DWORD error = GetLastError(); 
    throw Win32Error(message, error); 
} 

void Test() 
{ 
    const HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); 
    if (hStdIn == INVALID_HANDLE_VALUE) 
     ThrowLastWin32("GetStdHandle failed."); 

    static const int kBufferLen = 200; 
    wchar_t buffer[kBufferLen]; 
    DWORD numRead = 0; 

    if (! ReadConsoleW(hStdIn, buffer, kBufferLen, &numRead, nullptr)) 
     ThrowLastWin32("ReadConsoleW failed."); 

    const wstring str(buffer, numRead - 2); 

    static const wchar_t kEf = 0x0444; 
    wcout << ((str.find(kEf) != wstring::npos) ? L"EXIST" : L"NONE"); 
} 

int main() 
{ 
    static const int kExitOk = 0; 
    static const int kExitError = 1; 

    try 
    { 
     Test(); 
     return kExitOk; 
    }  
    catch(const Win32Error& e) 
    { 
     cerr << "\n*** ERROR: " << e.what() << '\n'; 
     cerr << " (GetLastError returned " << e.Error() << ")\n"; 
     return kExitError; 
    } 
    catch(const exception& e) 
    { 
     cerr << "\n*** ERROR: " << e.what() << '\n'; 
     return kExitError; 
    }   
} 

Ausgang:

C:\TEMP>test.exe 
abc 
NONE 
C:\TEMP>test.exe 
abcфabc 
EXIST