programma - linguaggio c++ pdf




Converti wchar_t in char (5)

Mi stavo chiedendo è sicuro di farlo?

wchar_t wide = /* something */;
assert(wide >= 0 && wide < 256 &&);
char myChar = static_cast<char>(wide);

Se sono abbastanza sicuro che l'ampio char rientrerà nell'intervallo ASCII.


In generale, no. int(wchar_t(255)) == int(char(255)) ovviamente, ma ciò significa che hanno lo stesso valore int. Potrebbero non rappresentare gli stessi personaggi.

Si vedrebbe una tale discrepanza anche nella maggior parte dei PC Windows. Ad esempio, nella pagina Codice di Windows 1250, char(0xFF) lo stesso carattere di wchar_t(0x02D9) (punto sopra), non wchar_t(0x00FF) (piccola y con diaeresi).

Si noti che non tiene nemmeno per l'intervallo ASCII, poiché il C ++ non richiede nemmeno ASCII. In particolare sui sistemi IBM potresti vedere 'A' != 65



Tecnicamente, " char " potrebbe avere lo stesso intervallo di " signed char " o " unsigned char ". Per i caratteri non firmati, l'intervallo è corretto; in teoria, per i personaggi firmati, la tua condizione è sbagliata. In pratica, solo pochi compilatori obietteranno e il risultato sarà lo stesso.

Nitpick: l'ultimo && nell'asserzione è un errore di sintassi.

Se l'asserzione è appropriata dipende da se puoi permetterti di andare in crash quando il codice arriva al cliente, e cosa potresti o dovresti fare se la condizione di asserzione viene violata ma l'asserzione non è compilata nel codice. Per il lavoro di debug, sembra soddisfacente, ma potrebbe essere utile anche un test attivo per il controllo run-time.


Una breve funzione che ho scritto un po 'di tempo fa per confezionare un array wchar_t in un array di caratteri. I caratteri non presenti nella codepage ANSI (0-127) sono sostituiti da "?" caratteri e gestisce correttamente le coppie surrogate.

size_t to_narrow(const wchar_t * src, char * dest, size_t dest_len){
  size_t i;
  wchar_t code;

  i = 0;

  while (src[i] != '\0' && i < (dest_len - 1)){
    code = src[i];
    if (code < 128)
      dest[i] = char(code);
    else{
      dest[i] = '?';
      if (code >= 0xD800 && code <= 0xD8FF)
        // lead surrogate, skip the next code unit, which is the trail
        i++;
    }
    i++;
  }

  dest[i] = '\0';

  return i - 1;

}

assert è garantire che qualcosa sia vero in una modalità di debug, senza che abbia alcun effetto in una build di rilascio. Meglio usare un'istruzione if e avere un piano alternativo per i caratteri che non rientrano nell'intervallo, a meno che l'unico modo per ottenere caratteri al di fuori dell'intervallo sia attraverso un bug del programma.

Inoltre, a seconda della codifica dei caratteri, potresti trovare una differenza tra i caratteri Unicode da 0x80 a 0xff e la loro versione char .







c++