2010-03-11 124 views
1

如何過濾c中的字符串?我想刪除任何不是​​的東西。C中的過濾器字符串

int main(int argc, char ** argv) { 
    char* name = argv[1]; 
    // remove anything that isn't [a-z0-9_] 

    printf("%s", name); 
} 
+0

聽起來像作業,爲什麼不先刺探解決方案。 – Tom 2010-03-11 05:31:49

+0

我完全可以行走字符串並替換字符,然後壓縮空字符,但是我希望能夠維護一些東西。 – 2010-03-11 05:34:22

回答

1
char *src, *dst; 
for (src = name, dst = name; *src; src++) { 
    if ('a' <= *src && *src <= 'z' 
    || '0' <= *src && *src <= '9' 
    || *src == '_') *dst++ = *src; 
} 
*dst = '\0'; 

編輯:多個小的修訂版。我希望現在有這個錯誤。

+0

絕大多數世界計算機不是問題,但C標準決不要求a-z是連續的字符。 – paxdiablo 2010-03-11 05:46:44

+0

夠正確。我想在這種情況下真正安全的做法是建立一個256'布爾值'的數組(如ctype中的內容),'true'設置爲所需的字符,並用它來執行檢查。或者更好的是,像caf一樣使用'islower()'和'isdigit()'。他的解決方案確實更好。 – 2010-03-11 06:18:05

+0

我去了這個,除了我用'islower'和'isdigit'代替範圍測試。謝謝! – 2010-03-11 06:32:23

0

C標準庫不支持正則表達式。
您需要下載一個C語言正則表達式庫(一個非常常見的例子是PCRE),或者在一個循環中執行此操作(由於搜索的表達式都是單個字符,因此不會回溯) 。

循環的方法看起來是這樣的:在C語言

int main(int argc, char ** argv) { 
    char* name = argv[1]; 

    // remove anything that isn't [a-z0-9_] 
    char strippedName[200]; 
    int iIn, iOut; // subscript in Name and StrippedName respectively 

    iIn = iOut = 0; 
    while (name[iIn] != '\0' && iOut < (sizeof(strippedName) + 1)) { 
     // some condition defining a desirable character 
     // BTW, this condition should actually be 
     // if (islower(name[iIn]) || isdigit(name[iIn] || name[iIn] == '_') 
     // to match the OP's requirement exactly 
     if (isalnum(name[iIn]) || name[iIn] == '_') 
     strippedName[iOut++] = name[iIn]; 
     iIn++; 
    } 
    strippedName[iOut++] = '\0'; 

    printf("%s", strippedName); 
} 

其他正則表達式(比PCRE其他前面提到的):

+0

一個正則表達式引擎總是在你的倉庫中有好處,但我懷疑它就像在這種情況下試圖用火箭發射器殺死蒼蠅:-) – paxdiablo 2010-03-11 06:02:00

+0

@paxdiablio:agree;由於不確定OP的問題的背景,我列出了這兩個問題。 – mjv 2010-03-11 06:14:54

+0

在思考OP的背景下,它聽起來越來越像作業......我希望我的直接反應不那麼直接(或者完全不計入)。 – mjv 2010-03-11 06:17:14

0

檢出ctype函數來測試循環中的每個字符。

+0

'cctype'是一個C++頭文件,但問題被標記爲'c',所以他應該使用的頭文件是'ctype.h'。 – dreamlax 2010-03-11 06:54:04

+0

@dreamlax:更正了錯誤。但是,如果仔細觀察網頁,則會顯示cctype(ctype.h)。他們是一樣的東西。 – 2010-03-11 14:52:31

+0

@ C.D。 Reimer:他們不是一回事,因爲你不能使用C編譯器包含'cctype'。 'cctype'頭文件可能包含特定於C++的語法;在我的系統上是這樣的。實際上,我的'ctype.h'頭文件還在我的'cctype'頭文件中定義了一個更多的函數(在C99中引入了'isblank')。 – dreamlax 2010-03-11 21:39:30

1
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 

int main(int argc, char ** argv) 
{  
    char *name, *inp, *outp; 

    if (argc < 2) 
    { 
     fprintf(stderr, "Insufficient arguments.\n"); 
     return 1; 
    } 

    inp = argv[1]; 
    name = malloc(strlen(inp) + 1); 
    outp = name; 

    if (!name) 
    { 
     fprintf(stderr, "Out of memory.\n"); 
     return 2; 
    } 

    while (*inp) 
    { 
     if (islower((unsigned char)*inp) || isdigit((unsigned char)*inp) || *inp == '_') 
      *outp++ = *inp; 
     inp++; 
    } 

    *outp = '\0'; 

    puts(name); 
    free(name); 

    return 0; 
} 
+0

任何理由讓一個新的字符串,而不是在原地做? – 2010-03-11 05:42:28

+1

不是真的,修改'* argv'只是顯得有些粗俗;) – caf 2010-03-11 05:58:31

+0

爲什麼你需要修改任何東西?只要檢查每個字符的輸入和輸出只有有效的。 – dreamlax 2010-03-11 06:43:44

1

如果您只是想從第一個參數中去除那些不需要的字符,那麼不需要分配內存,只需逐個字符地逐個輸入字符串即可。而且,如果您知道您將在ASCII環境(或任何其他支持連續az)的工作環境中工作,您甚至可以用檢查字符範圍的更快版本替換函數調用。

但是,我看不到速度的增加,因爲它足以證明非可移植代碼的合理性。

#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 
int main(int argc, char ** argv) { 
    int i; 
    char *p; 
    if (argc > 1) { 
     for (p = argv[1]; *p != '\0'; p++) { 
      if (islower(*p) || isdigit(*p) || *p == '_') { 
       putchar (*p); 
      } 
     } 
     putchar ('\n'); 
    } 
    return 0; 
} 
+0

我喜歡你的循環除了putchar。我會把它放回原來的字符串中。 – 2010-03-11 06:12:59