2016-08-03 10 views
2

Ich schreibe ein C-Programm, das durch eine TXT-Datei geht und alle druckbaren Zeichen (oder möglicherweise grafische Zeichen), die nicht in der Datei verwendet werden. Ich weiß, dass die Header-Datei ctype.h mehrere Zeichenklassen definiert (zB Ziffern, Kleinbuchstaben, Großbuchstaben usw.) und bietet Funktionen, um zu prüfen, ob ein bestimmtes Zeichen zu jeder Klasse gehört oder nicht, aber ich bin mir nicht sicher ob es möglich ist, das Inverse zu machen (dh alle die Zeichen in einer Klasse für etwas zu überprüfen). Ich brauche etwas, das alle Zeichen in jedem Typ auflistet oder definiert, idealerweise ein Array oder einen Aufzählungstyp.Gibt es eine Möglichkeit zu sehen, welche Zeichen in den Typen in ctype.h enthalten sind?

+2

Warum nimmst du nicht einen Blick auf 'selbst ctype.h'? – user3078414

+0

Sind die Namen und Beschreibungen der Makros nicht ausreichend? – usr2564301

+1

Die Anzahl der verfügbaren Zeichen ist begrenzt, und abhängig von Ihrer Kodierung kann so niedrig wie 128 sein. Sie können nur die 'ctype' Funktionen mit jedem von ihnen aufrufen. – rodrigo

Antwort

4

Weiß nicht, ob dies hilfreich ist, aber ich schrieb ein Programm, um Zeichen basierend auf denen in einer bestimmten Datei zu klassifizieren. Es wäre nicht schwer, es zu reparieren, um die Zeichen (Bytes) im Bereich 0..255 bedingungslos zu durchlaufen.

#include <stdio.h> 
#include <ctype.h> 
#include <limits.h> 

static void classifier(FILE *fp, char *fn) 
{ 
    int c; 
    int map[UCHAR_MAX + 1]; 
    size_t i; 

    printf("%s:\n", fn); 
    for (i = 0; i < UCHAR_MAX + 1; i++) 
     map[i] = 0; 

    printf("Code Char Space Upper Lower Alpha AlNum Digit XDig Graph Punct Print Cntrl\n"); 

    while ((c = getc(fp)) != EOF) 
    { 
     map[c] = 1; 
    } 

    for (c = 0; c < UCHAR_MAX + 1; c++) 
    { 
     if (map[c] == 1) 
     { 
      int sp = isspace(c) ? 'X' : ' '; 
      int up = isupper(c) ? 'X' : ' '; 
      int lo = islower(c) ? 'X' : ' '; 
      int al = isalpha(c) ? 'X' : ' '; 
      int an = isalnum(c) ? 'X' : ' '; 
      int dg = isdigit(c) ? 'X' : ' '; 
      int xd = isxdigit(c) ? 'X' : ' '; 
      int gr = isgraph(c) ? 'X' : ' '; 
      int pu = ispunct(c) ? 'X' : ' '; 
      int pr = isprint(c) ? 'X' : ' '; 
      int ct = iscntrl(c) ? 'X' : ' '; 
      int ch = (pr == 'X') ? c : ' '; 
      printf("0x%02X %-4c %-6c%-6c%-6c%-6c%-6c%-6c%-6c%-6c%-6c%-6c%-6c\n", 
        c, ch, sp, up, lo, al, an, dg, xd, gr, pu, pr, ct); 
     } 
    } 
} 

Der zusätzliche Trick, der mein Code gezogen setlocale() wurde mit in den aktuellen Locale zu arbeiten, anstatt die C-locale:

#include <locale.h> 

int main(int argc, char **argv) 
{ 
    setlocale(LC_ALL, ""); 
    filter(argc, argv, 1, classifier); 
    return(0); 
} 

Die filter() Funktion die Argumente von argv[1] verarbeitet (in der Regel wird optind statt weitergegeben von 1, aber es gibt keine bedingte Argument Verarbeitung in diesem Code) zu argv[argc-1], Lesen der Dateien (oder lesen Standardeingabe, wenn es keine benannten Dateien gibt). Er fordert classifier() für jede Datei öffnet - und übernimmt die Öffnen, Schließen usw.

+1

Ok, das ist ziemlich glatt - eine nette tabellarische Ausgabe jeder * Zeichenklasse *, die für jedes Zeichen in jeder Datei (oder 'stdin') gilt. –

0

Mein Vorschlag:

  1. eine Reihe von unsigned long s mit 256 Elementen erstellen, die kann alt die Anzahl der Male eine char tritt in der Datei auf.

  2. Lesen Sie den Inhalt der Datei Zeichen für Zeichen und aktualisieren Sie die Daten im Array.

  3. Nachdem Sie alle Zeichen der Datei verarbeitet haben, gehen Sie durch die Elemente des Arrays und drucken Sie die erforderlichen Informationen aus.


int main() 
{ 
    unsigned long charOccurrences[256] = {0}; 

    // open the file. 
    FILE* fin = fopen(....); 

    int c; 
    while ((c = fgetc(fin)) != EOF) 
    { 
     // Increment the number of occurrences. 
     charOccurrences[c]++; 
    } 

    // Process the data. 
    for (int i = 0; i < 256; ++i) 
    { 
     if (isprint(i) && charOccurrences[i] == 0) 
     { 
     printf("%c was not found in the file.\n", i); 
     } 
    } 

    // Close the file 
    fclose(fin); 
} 
+0

Ich tippte ein bisschen langsamer als du ;-) Darf ich vorschlagen, ein Array von long anstelle von einem Array von int zu verwenden, um mit der maximalen Anzahl von Zeichen, die in einer Datei erwartet werden konnten (mindestens nach dem Rückgabewert von ftell())? – Christophe

+0

@Christophe, ausgezeichneter Vorschlag. Ich habe es in "unsigned long" geändert. –

+2

Fehlendes Argument in 'printf ("% s wurde in der Datei nicht gefunden. \ N ");' und vermutlich auch falsches Format. – chqrlie

2

Es gibt keine feste Zeichenliste in ctype.h, die Ihnen helfen könnten. Tatsächlich hängt isprint() vom Gebietsschema ab.

Unter der Annahme, dass Sie von char und nicht breit Zeichen sind gesprochen, ein Weg, um Ihr Problem zu lösen, wäre eine Tabelle mit 256 Elementen zu initialisieren, die jeweils ein Zeichen:

char mychars[256]; 
memset(mychars, 0, 256); 

dann Ihre Datei öffnen und lesen Sie alle Zeichen und Fahne jene, die vorhanden sind:

... 
int c; 
while ((c=fgetc(fp)) != EOF) { 
    mychars[c] |= 1; 
} 

dann später können Sie nur durch die druckbaren iterieren:

for (int i=0; i<256; i++) { 
    if (isprint(i) && !mychars[i]) 
     printf ("%c not found\n", (char)i); 
} 
+1

Die 'isprint()' (oder 'isgraph()' für diese Angelegenheit) scheint der Schlüssel zur Beantwortung der Frage zu sein. –

0

Sie können 0-UCHAR_MAX und prüfen jede Funktion von <ctype.h> durch alle Werte des unsigned char Typ, iterieren, um zu bestimmen, was die Klassen sind.

Zum Beispiel können Sie alle Ziffern mit dieser Liste:

printf("digits: "); 
for (int c = 0; c <= UCHAR_MAX; c++) { 
    if (isdigit(c)) 
     putchar(c); 
} 
printf("\n"); 
Verwandte Themen