2016-08-03 120 views
2

我正在編寫一個C程序,它涉及通過.txt文件並查找文件中使用的所有可打印字符(或可能是圖形字符),這些字符是而不是。我知道頭文件ctype.h定義了幾個字符類(例如數字,小寫字母,大寫字母等),並提供了檢查給定字符是否屬於每個類的函數,但我不確定是否可以做相反的事情(例如,檢查某個類中的字符全部)。我需要列出或定義每種類型中所有字符的東西,理想情況下是數組或枚舉類型。有沒有辦法查看ctype.h中的哪些字符?

+2

你爲什麼不看看'ctype.h'自己? – user3078414

+0

宏名稱和描述不夠? – usr2564301

+1

可用的字符數量是有限的,並且根據您的編碼可能會低至128.您可以調用每個函數的'ctype'函數。 – rodrigo

回答

4

不知道這是否有幫助,但是我編寫了一個程序來根據給定文件中的字符對字符進行分類。解決這個問題並不難,無條件地檢查範圍爲0..255的字符(字節)。

#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); 
     } 
    } 
} 

額外的技巧,我的代碼拉用setlocale()當前區域設置,而不是C語言環境中的工作:

#include <locale.h> 

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

filter()功能從argv[1]處理參數(通常optind,而是隻傳遞1,但在此代碼中沒有條件參數處理)至argv[argc-1],讀取文件(或者在沒有命名文件時讀取標準輸入)。它要求classifier()爲它打開每個文件 - 並處理打開,關閉等

+1

好的,這非常漂亮 - 每個*字符類*的一個很好的表格輸出適用於每個文件(或stdin)中的每個字符。 –

0

我的建議:

  1. 有256個元素創建的unsigned long秒的陣列,可以次的char老數發生在文件中。

  2. 按字符讀取文件內容並更新數組中的數據。

  3. 處理文件的所有字符後,遍歷數組的元素並打印必要的信息。


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

我輸入的速度比你慢一點;-)我可以建議使用long數組而不是int數組,以便與文件中可能預期的最大字符數一致(至少根據ftell()的返回值)? – Christophe

+0

@Christophe,很好的建議。我將它改爲'unsigned long'。 –

+2

'printf(%s在文件中找不到\ n「);'並且可能不正確的格式。 – chqrlie

2

有一個在ctype.h沒有固定的字符列表,可以幫助你。實際上isprint()取決於語言環境。

假設你說的char而不是寬字符,解決您的問題一個辦法是初始化256個元素表中,每一個代表一個字符:

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

然後打開你的文件,閱讀所有的字符,並標記那些存在:

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

再後來,你可以通過打印那些只是想迭代10

+1

'isprint()'(或'isgraph()')似乎是回答這個問題的關鍵。 –

0

您可以迭代unsigned char類型的所有值,從0UCHAR_MAX,並檢查<ctype.h>中的每個函數以確定類是什麼。

例如,您可以列出這一切的數字:

printf("digits: "); 
for (int c = 0; c <= UCHAR_MAX; c++) { 
    if (isdigit(c)) 
     putchar(c); 
} 
printf("\n"); 
相關問題