2016-06-22 8 views
0

Was ist die empfohlene Methode zum Iterieren über alle Dateien in einem geöffneten Dateidialog OFN_ALLOWMULTISELECT mit Unicode aktiviert?Iterieren über alle Dateien in OFN_ALLOWMULTISELECT mit Unicode

Meine erste Idee war so etwas wie dieses:

TCHAR *tmp = ofn.lpStrFile + ofn.nFileOffset; 

while(*tmp) { 
    wprintf("Got file: %s\n", tmp); 
    tmp += wcslen(tmp) + 1; 
} 

Aber dann fiel mir ein, dass dies dort nicht in Fall funktioniert Zeichen im String-Puffer sind, die in 16 Bits dargestellt wird, kann nicht sein. Für einen sicheren Ansatz müsste ich zuerst die Byte-Länge der TCHAR Zeichenfolge herausfinden, dann den TCHAR Zeiger auf char umwandeln und diese Byte-Länge in jeder Iteration hinzufügen. Etwas wie folgt aus:

TCHAR *tmp = ofn.lpStrFile + ofn.nFileOffset; 

while(*tmp) { 
    wprintf("Got file: %s\n", tmp); 
    tmp = (TCHAR *) (((char *) tmp)) + get_byte_len_of_tstr(tmp)); 
} 

Beachten Sie, dass get_byte_len_of_tstr() ist nur ein Platzhalter für eine Funktion, die für diesen Zweck geschrieben werden hätte. Da dieser Ansatz etwas ungeschickt aussieht, möchte ich zunächst nach Feedback fragen, ob das wirklich der richtige Weg ist oder ob ich etwas verpasst oder missverstanden habe ...

+0

Sie haben kein echtes Problem, alle Zeichen können mit 16 Bit dargestellt werden. Einige brauchen nur zwei von ihnen, das wird deinen Code nicht stolpern. –

+0

Aber AFAIU wcslen() gibt die Anzahl der Zeichen in einem TSTR zurück. Wenn also ein Zeichen 32 Bit im TSTR benötigt (dh zwei 16bit-Paare), gibt wcslen() immernoch 1 zurück, was meinen Zeiger durcheinander bringt Arithmetik in dem Code, den ich oben gepostet habe. – Andreas

+0

Sie * müssen * dies wirklich versuchen, um zu sehen, dass dies nicht der Fall ist. wcslen() zählt wchar_t, keine Codepunkte. Wenn wchar_t zu einem Codepoint wird, der ein einzelnes Symbol auf dem Bildschirm darstellt, ist dies der Job des Textrenderers. Es wird ziemlich oft ein einzelnes Glyph aus zwei wchar_t erzeugen, selbst wenn sie nicht in den oberen Bitebenen sind. Passiert für akzentuierte Zeichen. –

Antwort

2

Ihr erstes Beispiel war auf dem richtigen Weg , hat aber ein paar Fehler:

  1. Ihre Variable sollte WCHAR* statt TCHAR* deklariert werden.

  2. wprintf() akzeptiert keine char* Formatzeichenfolge als Eingabe, stattdessen wird eine wchar_t* verwendet.

WCHAR *tmp = ofn.lpStrFile + ofn.nFileOffset; 
while (*tmp) 
{ 
    wprintf(L"Got file: %s\n", tmp); 
    tmp += (wcslen(tmp) + 1); 
} 

Wenn Sie verwenden TCHAR wollen (und Sie sollten wirklich nicht, es sei denn, Sie Win9x/ME unterstützen müssen), dann würde es so aussehen, anstatt:

TCHAR *tmp = ofn.lpStrFile + ofn.nFileOffset; 
while (*tmp) 
{ 
    _tprintf(_T("Got file: %s\n"), tmp); 
    tmp += (_tcslen(tmp) + 1); 
} 

Das gesagt, Ihr Verständnis von wcslen() ist falsch (aber Ihre Verwendung ist richtig). In Windows wird eine Unicode-Zeichenfolge in UTF-16 codiert, wobei jedes WCHAR Element eine UTF-16 Codeeinheit ist. wcslen() zählt die Anzahl der WCHAR Elemente in der Zeichenfolge, nicht die Anzahl der Unicode Codepoints, die sie darstellen, wie Sie denken. Wenn also ein gegebener Codepunkt ein UTF-16-Ersatzpaar benötigt, verwendet er zwei WCHAR Elemente in der Zeichenfolge und wcslen() zählt 2 dafür. Andernfalls wird 1 WCHAR verwendet und wcslen() zählt 1 dafür.

Das gleiche gilt für strlen() und MBCS-Strings, wenn ein bestimmter Unicode-Codepunkt mit mehr als 1 codeunit (char -Element) in der Zeichenfolge codiert ist.

+0

Was ist so schlimm an der Verwendung von' TCHAR'? Wird es nicht einfach 'WCHAR' zugeordnet, wenn 'UNICODE' definiert ist? (was in meinem Programm der Fall ist) – Andreas

+0

Das stimmt. 'TCHAR' und die anderen Funktionen in' 'wären vollkommen in Ordnung, wenn Sie eine Unicode-Anwendung erstellen. Was ist * nicht * in Ordnung ist es Cas char, @andreas. –