Frage

Ich habe eine Multi-Byte-Zeichenfolge, die eine Mischung aus japanischen und lateinischen Schriftzeichen enthält. Ich versuche, Teile dieser Zeichenfolge in einen separaten Speicherplatz zu kopieren. Da es sich um ein Multi-Byte-String ist, verwendet einige der Zeichen ein Byte und andere Zeichen verwendet zwei. Wenn Teile der Zeichenfolge zu kopieren, muss ich nicht „halb“ japanische Zeichen kopieren. Um dies richtig zu tun, ich muss in der Lage zu bestimmen, wo in den Multi-Byte-String-Zeichen beginnt und endet.

Als Beispiel, wenn der Zeichenfolge 3 Zeichen enthält, die erfordert [2 Byte] [2 Byte] [1 Byte], muß ich kopieren entweder 2, 4 oder 5 Bytes an dem anderen Ort und nicht 3, da, wenn ich 3 kopieren ich würde nur die Hälfte der zweiten Zeichen kopieren.

, um herauszufinden, wo in dem Multi-Byte-String-Zeichen beginnt und endet, Ich versuche, den Windows-API-Funktion CharNext und CharNextExA zu verwenden, aber ohne Glück. Wenn ich diese Funktionen zu verwenden, navigieren sie durch meinen String ein Byte zu einem Zeitpunkt, eher als ein Zeichen zu einem Zeitpunkt. Laut MSDN wird CharNext soll Die CharNext Funktion einen Zeiger auf das nächste Zeichen in einer Zeichenfolge abruft. .

Hier ist ein Code, um dieses Problem zu veranschaulichen:

#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include <string.h>

/* string consisting of six "asian" characters */
wchar_t wcsString[] = L"\u9580\u961c\u9640\u963f\u963b\u9644";

int main() 
{
   // Convert the asian string from wide char to multi-byte.
   LPSTR mbString = new char[1000];
   WideCharToMultiByte( CP_UTF8, 0, wcsString, -1, mbString, 100,  NULL, NULL);

   // Count the number of characters in the string.
   int characterCount = 0;
   LPSTR currentCharacter = mbString;
   while (*currentCharacter)
   {
      characterCount++;

     currentCharacter = CharNextExA(CP_UTF8, currentCharacter, 0);
   }
}

(bitte Speicherverlust und Ausfall ignoriert Fehlerprüfung zu tun.)

Nun, in dem obigen Beispiel würde ich erwarten, dass characterCount 6 wird, da die Anzahl der Zeichen in der asiatischen Zeichenfolge ist. Aber stattdessen wird characterCount 18, da mbstring 18 Zeichen enthält:

門阜陀阿阻附

Ich verstehe nicht, wie es funktionieren soll. Wie wird CharNext soll wissen, ob „é- € é“ in der Zeichenfolge ist eine codierte Version eines japanischen Charakters, oder in der Tat der Zeichen é - € und é

Einige Hinweise:

  • Ich habe Joels Blog-Post zu lesen, was jeder Entwickler über Unicode wissen muss. Ich mag zwar etwas darin falsch verstanden.
  • Wenn alles, was ich die Zeichen tun wollte zählen sollte, ich direkt die Zeichen in dem asiatischen String zählen konnte. Beachten Sie, dass mein eigentliches Ziel ist Teile des Multi-Byte-String in einem anderen Ort zu kopieren. Die separate Lage unterstützt nur Multi-Byte, nicht WideChar.
  • Wenn ich den Inhalt von mbstring zurück in weiten char mit MultiByteToWideChar konvertieren, erhalte ich die richtige Zeichenfolge (門 阜 陀 阿 阻 附), die, dass es gibt nichts falsch mit mbstring.

EDIT: Apparantly die CharNext Funktionen nicht unterstützt UTF-8, aber Microsoft vergessen, dass zu dokumentieren. Ich warf / copiedpasted zusammen meine eigene Routine, die ich nicht verwenden und welche Bedürfnisse zu verbessern. Ich vermute, es ist leicht zerbrechbare.

  LPSTR CharMoveNext(LPSTR szString)
  {
     if (szString == 0 || *szString == 0)
        return 0;

     if ( (szString[0] & 0x80) == 0x00)
        return szString + 1;
     else if ( (szString[0] & 0xE0) == 0xC0)
        return szString + 2;
     else if ( (szString[0] & 0xF0) == 0xE0)
        return szString + 3;
     else if ( (szString[0] & 0xF8) == 0xF0)
        return szString + 4;
     else
        return szString +1;
  }
War es hilfreich?

Lösung

Dies ist eine wirklich gute Erklärung, was hier vor sich geht im Sortierung it All Out Blog : Ist CharNextExA gebrochen ?. Kurz gesagt, ist CharNext nicht entwickelt, um mit UTF8-Strings zu arbeiten.

Andere Tipps

Soweit ich erkennen kann (wie Google und Experimentieren), CharNextExA tatsächlich funktioniert nicht mit UTF-8, nur multibyte Kodierungen unterstützt, die kürzeren Vorlauf / Trail Byte Paare oder Single-Byte-Zeichen verwendet werden.

UTF-8 ist eine ziemlich normale Codierung, es gibt eine Menge von Bibliotheken, die das tun, was Sie wollen, aber es ist auch ziemlich einfach, Ihre eigene Rolle.

Haben Sie einen Blick in hier unicode.org , insbesondere Tisch 3-7 für gültige Folge bildet.

const char* NextUtf8( const char* in )
{
    if( in == NULL || *in == '\0' )
        return in;

    unsigned char uc = static_cast<unsigned char>(*in);

    if( uc < 0x80 )
    {
        return in + 1;
    }
    else if( uc < 0xc2 )
    {
         // throw error? invalid lead byte
    }
    else if( uc < 0xe0 )
    {
        // check in[1] for validity( 0x80 .. 0xBF )
        return in + 2;
    }
    else if( uc < 0xe1 )
    {
        // check in[1] for validity( 0xA0 .. 0xBF )
        // check in[2] for validity( 0x80 .. 0xBF )
        return in + 3;
    }
    else // ... etc.
    // ...
}

Da CharNextExA doesn‘ t Arbeit mit UTF-8 , können Sie es selbst analysieren. überspringen Sie die Zeichen über die mit 10 in den oberen zwei Bits haben. Sie können das Muster in der Definition von UTF-8 finden Sie unter: http://en.wikipedia.org / wiki / UTF-8

LPSTR CharMoveNext(LPSTR szString)
{
    ++szString;
    while ((*szString & 0xc0) == 0x80)
        ++szString;
    return szString;
}

Dies ist keine direkte Antwort auf Ihre Frage, aber Sie können das folgende Tutorial hilfreich, ich habe sicher. In der Tat können die Angaben hier ist genug, dass Sie in der Lage sein sollte, die Multi-Byte-String, sich mit Leichtigkeit zu durchqueren:

String Tutorial Füllen

Versuchen 932 für die Codepage verwenden. Ich glaube nicht, CP_UTF8 eine echte Codepage ist, und es kann für WideCharToMultiByte () und zurück nur arbeiten. Sie können auch versuchen IsLeadByte (), aber das erfordert entweder das Gebietsschema richtig einstellen oder die Standard-Codepage korrekt einstellen. Ich habe erfolgreich verwendet IsDBCSLeadByteEx (), aber nie mit CP_UTF8.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top