2010-07-28 12 views
8

Come ottengo la dimensione in byte di una stringa di caratteri multibyte in Visual C? Esiste una funzione o devo contare i personaggi personalmente?Come ottenere la dimensione in byte della stringa multibyte

O, più in generale, come ottengo la giusta dimensione in byte di una stringa TCHAR?

Soluzione:

_tcslen(_T("TCHAR string")) * sizeof(TCHAR) 

EDIT:
stavo parlando solo stringhe null-terminated.

+3

Il codice è corretto, per il calcolo della dimensione, in byte, della stringa. L'affermazione "funziona per ... char e wchar_t ... ma non per le stringhe di caratteri multibyte" è tuttavia confusa. – Thanatos

+0

Quindi le stringhe di caratteri multibyte non contengono byte null? – flacs

+0

@Tilka: Potrebbero, ma è necessario conoscere la lunghezza in qualche altro modo, ad esempio memorizzarlo in un numero intero che viene fornito con la stringa. Stringhe terminate da null, che sono quelle che normalmente si incontrano (e cosa richiedono _tcslen, strlen, etc.), non contengono byte null, ad eccezione del terminatore null, ovviamente. – Thanatos

risposta

3

According to MSDN, _tcslen corrisponde a strlen quando è definito _MBCS. strlen restituirà il numero di byte nella stringa. Se si utilizza _tcsclen che corrisponde a _mbslen che restituisce il numero di caratteri multipla .

Inoltre, le stringhe multibyte non (AFAIK) contengono valori nulli incorporati, n.

Vorrei mettere in discussione l'uso di una codifica multibyte, in primo luogo, sebbene ... a meno che non si stia supportando un'app legacy, non c'è motivo di scegliere multibyte su Unicode.

+1

Le stringhe UTF-8 non contengono null incorporati (in particolare: l'unico posto dove si verifica un byte 0 rappresenta il punto di codice 0, quindi se questo è il tuo terminatore allora tu può cercarlo a byte-saggio). Non sono sicuro che UTF-16 sia considerato una "codifica multibyte" in questo contesto, ma può certamente contenere 0 * byte *, ma non 0 byte a doppio byte. Penso che SHIFT-JIS non usi 0 byte tranne quando codifica 0. Un sacco di codifiche nel mondo, ma non sono sicuro di cosa sia possibile in Windows locales ... –

+1

Questo è un po 'confuso: le stringhe UTF-8 possono contenere valori null , * se * stai memorizzando la dimensione in qualcosa di diverso da un terminatore nullo. Le stringhe terminate da null non possono contenere valori nulli, perché sono terminate con null. Una stringa UTF-8 terminata da null non può contenere valori null per lo stesso motivo. Detto questo, non riesco a pensare a uno scopo utile di mettere un valore null in una stringa UTF-8 diverso da quello di terminarlo. – Thanatos

9

Vediamo se riesco a chiarire la situazione:

"stringa di caratteri multi-byte" è un termine vago per cominciare, ma nel mondo di Microsoft, è meants tipicamente "non ASCII, e non UTF 16" . Quindi, potresti usare una codifica di caratteri che potrebbe usare 1 byte per carattere, o 2 byte, o forse più. Non appena lo fai, il numero di caratteri nella stringa! = Il numero di byte nella stringa.

Prendiamo UTF-8 come esempio, anche se non è utilizzato su piattaforme MS. Il carattere é è codificato come "c3 a9" in memoria - quindi, due byte, ma 1 carattere. Se ho la "I" stringa, è:

text: t h é  \0 
mem: 74 68 c3 a9 00 

Questo è un "nullo terminata" stringa, in quanto termina con un nullo. Se volessimo permettere nostra stringa di avere valori nulli in essa, avremmo bisogno di memorizzare la dimensione in qualche altro modo, come ad esempio:

struct my_string 
{ 
    size_t length; 
    char *data; 
}; 

... e una serie di funzioni per contribuire ad affrontare questo. (Questa è una sorta di come std::string opere, piuttosto grossolanamente.)

Per stringhe null-terminated, tuttavia, strlen() calcolerà la loro dimensione in byte , caratteri non. (Ci sono altre funzioni per il conteggio dei caratteri) strlen conta il numero di byte prima di vedere un byte 0 - niente di strano.

Ora, le stringhe "wide" o "unicode" nel mondo di MS si riferiscono alle stringhe UTF-16. Hanno problemi simili in quanto il numero di byte! = Il numero di caratteri. (Anche: il numero di byte/2 = il numero di caratteri!) Lasciate guardare il nuovo:

text: t  h  é  \0 
shorts: 0x0074 0x0068 0x00e9 0x0000 
mem: 74 00 68 00 e9 00 00 00 

Questo è "il" in UTF-16, memorizzata in little endian (che è ciò che il vostro desktop tipico è). Si noti tutti i 00 byte - questi trip up strlen. Quindi, chiamiamo wcslen, che lo considera come 2 byte short s, non singoli byte.

Infine, si dispone di TCHAR s, che sono uno dei due casi precedenti, a seconda se è stato definito UNICODE. _tcslen sarà la funzione appropriata (strlen o wcslen) e TCHAR sarà char o wchar_t. TCHAR è stato creato per facilitare il passaggio a UTF-16 nel mondo Windows.

+0

"(Anche: il numero di byte/2! = Il numero di caratteri)" In che modo? – flacs

+0

@Tilka: Questo è il modo in cui UTF-16 codifica i caratteri. UTF-16 può codificare più di 65.536 caratteri diversi, quindi dovrebbe essere chiaro che 2 byte non sono sufficienti. UTF-16 codifica molti caratteri come solo 2 byte, ma deve usare 4 per alcuni, in una forma nota come "coppie di surrogati" (vedi l'articolo di Wikipedia su UTF-16.) – Thanatos

+0

Ah sì, l'ho confuso con UCS-2. Bella spiegazione, ma l'altra risposta era diretta al punto. – flacs

Problemi correlati