2011-01-03 20 views
5

sto provando a eseguire la mia versione di wc (filtro unix), ma ho problemi con caratteri non ASCII. Ho fatto un dump HEX di un file di testo e ho scoperto che questi caratteri occupano più di un byte, quindi non si adattano al char. C'è un modo in cui posso leggere questi caratteri dal file e gestirli come un singolo carattere (quindi posso contare i caratteri nel file) in C? Ho cercato un po 'su google e ho trovato un po' di tipo wchar_t, ma non c'era un semplice esempio su come usarlo con i file.Gestione di caratteri multibyte (non ASCII) in C

+2

Avrete bisogno di conoscere Unicode e in particolare le codifiche. Sai cosa significano questi termini? –

+0

Inoltre, è possibile conoscere le codifiche a singolo byte non ASCII, come le varie codifiche ISO, Windows 1252, ecc. Come forse sapete, ASCII è in realtà una codifica a 7 bit di larghezza. –

+0

@Joey grazie, così usato per ASCII, ISO, ANSI ecc. Ho formato una cattiva abitudine! –

risposta

2

Vai a dare un'occhiata a ICU. Quella libreria è ciò di cui hai bisogno per affrontare tutti i problemi.

8

Ho cercato un po 'su google e ho trovato un po' di tipo wchar_t, ma non c'era un semplice esempio su come usarlo con i file.

Ben soddisfatti. Non ci sono stati esempi semplici perché, sfortunatamente, il corretto set di caratteri supportati non è   semplice.

A parte: in un mondo ideale, tutti userebbero UTF-8 (una codifica Unicode che è efficiente in termini di memoria, robusta e retrocompatibile con ASCII), la libreria C standard includerebbe la codifica-decodifica UTF-8 supporto e la risposta a questa domanda (e relativa al testo in generale) sarebbe semplice e diretta.

La risposta alla domanda "What is the best unicode library for C?" è quello di utilizzare la libreria ICU. Potresti voler dare un'occhiata a ustdio.h, dato che ha una funzione u_fgetc e l'aggiunta del supporto Unicode al tuo programma richiederà probabilmente poco più che digitare u_ un paio di volte.

Inoltre, se è possibile risparmiare alcuni minuti per alcune letture leggere, è possibile leggere The Absolute Minimum Every Software Developer Absolutely, Positively Must Know about Unicode and Character Sets (No Excuses!) da Joel   su   Software.

Io, personalmente terapia intensiva, non hanno mai usato, ma probabilmente sarà d'ora in poi :-)

+0

Mi è davvero piaciuto il tuo: "Il minimo assoluto Ogni sviluppatore di software deve assolutamente conoscere positivamente Unicode e Set di caratteri (nessuna scusa!)". Ottimo post !. – JosEduSol

4

Se si vuole scrivere una versione standard C dell'utilità wc che rispetta l'impostazione della lingua corrente quando viene eseguito , quindi puoi effettivamente utilizzare le versioni wchar_t delle funzioni stdio. All'avvio del programma, si dovrebbe chiamare setlocale():

setlocale(LC_CTYPE, ""); 

Questo farà sì che le funzioni di carattere di larghezza di utilizzare il set di caratteri appropriato definito dall'ambiente - ad es. su sistemi Unix, la variabile di ambiente LANG. Ad esempio, questo significa che se la tua variabile LANG è impostata su un locale UTF8, le funzioni di carattere ampio gestiranno l'input e l'output in UTF8. (Questo è il modo in cui l'utilità POSIX wc viene specificata per funzionare).

È quindi possibile utilizzare le versioni wide-character di tutte le funzioni standard. Ad esempio, se si dispone di codice come questo:

long words = 0; 
int in_word = 0; 
int c; 

while ((c = getchar()) != EOF) 
{ 
    if (isspace(c)) 
    { 
     if (in_word) 
     { 
      in_word = 0; 
      words++; 
     } 
    } 
    else 
    { 
     in_word = 1; 
    } 
} 

...si converte alla versione di caratteri estesi modificando c ad un wint_t, getchar()-getwchar(), EOF-WEOF e isspace()-iswspace():

long words = 0; 
int in_word = 0; 
wint_t c; 

while ((c = getwchar()) != WEOF) 
{ 
    if (iswspace(c)) 
    { 
     if (in_word) 
     { 
      in_word = 0; 
      words++; 
     } 
    } 
    else 
    { 
     in_word = 1; 
    } 
} 
+4

È scortese il downvote senza un commento esplicativo. – caf

0

Sei sicuro si ha realmente bisogno il numero di caratteri ? wc conta il numero di byte.

~$ echo 'דניאל' > hebrew.txt 
~$ wc hebrew.txt 
1 1 11 hebrew.txt 

(11 = 5 caratteri a due byte + 1 byte per '\ n')

Tuttavia, se davvero si vuole contare caratteri piuttosto che byte e può supporre che i file di testo sono codificato in UTF-8, quindi l'approccio più semplice è quello di contare tutti i byte che sono non byte (cioè nell'intervallo da 0x80 a 0xBF).

Se non sipuò assumere UTF-8, ma possibile supporre che tutti i file non UTF-8 sono in una codifica a singolo byte, quindi eseguire un controllo di convalida UTF-8 sui dati. Se passa, restituire il numero di byte lead UTF-8. Se fallisce, restituire il numero di byte totali.

(Si noti che l'approccio di cui sopra è specifico per wc. Se si sta effettivamente facendo qualcosa con i personaggi e non solo loro a contare, è necessario conoscere la codifica.)

+3

Si noti che 'wc -m' conta effettivamente * caratteri * in contrapposizione a * byte * -' wc -m ebraico.txt' fornisce l'output '6 hebrew.txt'. – caf

1

La maggior parte del risposte finora hanno merito, ma che si utilizza dipende sulla semantica che si desidera:

  • Se si desidera elaborare il testo nella codifica della lingua configurata, e non si cura di completo fallimento nel caso di incontrare sequenze non validi , usando getwchar() va bene.
  • Se si desidera elaborare il testo nella codifica delle impostazioni locali configurate, ma è necessario rilevare e ripristinare da sequenze non valide, è necessario leggere i byte e utilizzare manualmente mbrtowc.
  • Se si desidera elaborare il testo sempre come UTF-8, è necessario leggere i byte e inviarli al proprio decodificatore. Se si conosce in anticipo il file sarà UTF-8 valido, è possibile contare i byte negli intervalli 00-7F e C2-F4 e ignorare il conteggio di tutti gli altri byte, ma ciò potrebbe dare risultati errati in presenza di sequenze non valide. Un approccio più robusto sarebbe la decodifica del decodificatore nei codepoint Unicode e il conteggio del numero di decodifiche riuscite.

Spero che questo aiuti.

Problemi correlati