Perché l'alfabeto è suddiviso in più intervalli in questo codice C?


161

In una libreria personalizzata ho visto un'implementazione:

inline int is_upper_alpha(char chValue)
{
    if (((chValue >= 'A') && (chValue <= 'I')) ||
        ((chValue >= 'J') && (chValue <= 'R')) ||
        ((chValue >= 'S') && (chValue <= 'Z')))
        return 1;
    return 0;
}

È un uovo di Pasqua o quali sono i vantaggi rispetto al metodo C / C ++ standard?

inline int is_upper_alpha(char chValue)
{
    return ((chValue >= 'A') && (chValue <= 'Z'));
}

Si noti che in EBCDIC, l'intervallo di caratteri per le lettere minuscole precede l'intervallo di caratteri per le lettere maiuscole ed entrambi precedono le cifre - che è esattamente l'opposto dell'ordine nelle codifiche basate su ASCII (come l'8859- serie x o Unicode o CP1252 o ...).
Jonathan Leffler,

1
Nota: se 'J' - 'I'ed 'S' - 'R'entrambi sono uguali 1, mi aspetto che un ragionevole ottimizzatore trasformi il primo in quest'ultimo.
Matthieu M.,

Risposte:


214

L'autore di questo codice doveva presumibilmente per sostenere EBCDIC ad un certo punto, in cui i valori numerici delle lettere non sono contigui (esistono spazi tra I, Je R, Scome si può immaginare).

Vale la pena notare che la standard C ++ unica garanzia che i caratteri C e 0ad 9avere valori numerici contigui proprio per questo motivo, quindi nessuno di questi metodi è strettamente conforme agli standard.


64
Il vero WTF è il motivo per cui non l'ha fatto l'autore originale messo in un commento: // In the EBCDIC coding, the alphabet has gaps between these values. See URL: xxxx for details. Quindi non dovresti nemmeno fare la domanda. Avresti la risposta integrata nel codice.
abelenky,

66
@abelenky Se il codice era originariamente per un sistema in cui viene normalmente utilizzato ebcdic, in quel momento potrebbe sembrare ovvio e non necessitare di un commento, sfortunatamente le cose che sembrano andare bene nel codice legacy adesso sembrano strane.
Vality

26
@abelenky: Il vero WTF è il motivo per cui l'autore originale non ha usato la funzionalità standard, cioè return ( isalpha( chValue ) && isupper( chValue ) )...
DevSolar

4
@Damon: non è questo il problema. Potrebbe essere necessario elaborare una codifica "aliena" anche su un sistema che non utilizza tale codifica in modo nativo. Quindi imposti le tue impostazioni locali sulla codifica specificata e poi tieni le dita incrociate sul fatto che il programmatore abbia effettivamente utilizzato funzioni standard invece di fare una codifica "intelligente" come quella sopra, pensando di sapere che ogni codifica che il suo programma incontrerà mai ...
DevSolar,

6
Se è stato scritto per supportare EBCDIC dagli anni '70, isalpha e isupper erano addirittura ANSI o supportati dalla maggior parte dei compilatori di allora?
Nickalh,

54

Sembra che tenti di coprire sia EBCDIC che ASCII. Il tuo metodo alternativo non funziona per EBCDIC (ha falsi positivi, ma non falsi negativi)

C e C ++ non richiedono che '0'-'9'sono contigui.

Si noti che le chiamate di libreria standard, non so se su cui girano ASCII, EBCDIC o altri sistemi, in modo che siano più portatile e forse più efficace.


5
std::isupperinterroga effettivamente la locale C globale attualmente installata.
Lingxi,

1
Si hai ragione. Il metodo è scritto per coprire entrambe le codifiche. Grazie per la risposta!
Vladimir Ch.

4
@Lingxi: vero, ma ciò non significa che puoi cambiare le impostazioni internazionali da ASCII a EBCDIC. 'A'deve rimanere 'A'indipendentemente dalle impostazioni locali. Da ASCII a UTF-8, sarebbe possibile.
MSalters

2
@Lingxi: std::isupperinterroga la locale C globale attualmente installata, sì, ma la fase di compilazione che interpreta i caratteri letterali no.
Razze di leggerezza in orbita

1
@Lingxi - Solo una breve nota. È discutibile se std::isuppersia realmente necessario nella maggior parte dei casi. Rispetta i locali utilizzati per l'input dell'utente. Ma quando analizzi i file, interagendo con i database di solito ti aspetti qualche altra localizzazione. Inoltre, almeno su Linux, queste chiamate relative alle impostazioni locali sono molto lente - ad esempio, std::isalphachiama dynamic_cast due volte per "trovare" un'implementazione delle impostazioni locali corretta prima di confrontare effettivamente un singolo carattere.
ibre5041,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.