2009-12-03 262 views
3

我期待从字符串中删除所有标点符号并在C中使所有大写字母小写,任何建议吗?如何从字符串中删除标点符号C

+1

你需要做的是就地或者你可以在一个新的缓冲区工作? – jason 2009-12-03 18:08:34

+0

贾森,eliben的答案将正常工作时,源==目的地;-) – 2009-12-03 18:09:50

+2

你在做这个英文吗?一些语言在压缩字符方面存在问题。 – 2009-12-03 18:14:00

回答

10

只需通过使用ctype.h提供的功能的算法的草图:

#include <ctype.h> 

void remove_punct_and_make_lower_case(char *p) 
{ 
    char *src = p, *dst = p; 

    while (*src) 
    { 
     if (ispunct((unsigned char)*src)) 
     { 
      /* Skip this character */ 
      src++; 
     } 
     else if (isupper((unsigned char)*src)) 
     { 
      /* Make it lowercase */ 
      *dst++ = tolower((unsigned char)*src); 
      src++; 
     } 
     else if (src == dst) 
     { 
      /* Increment both pointers without copying */ 
      src++; 
      dst++; 
     } 
     else 
     { 
      /* Copy character */ 
      *dst++ = *src++; 
     } 
    } 

    *dst = 0; 
} 

标准警告应用:完全未测试;改进和优化作为练习留给读者。

+2

不要忘了在最后添加'\ 0'! – 2009-12-03 18:12:19

+0

好的。固定。 – asveikau 2009-12-03 18:13:21

+1

您应该将'is *'或'to *'函数的参数强制转换为'unsigned char'。这不是一个完善或优化! – pmg 2009-12-03 18:14:35

12

循环字符串的字符。无论何时遇到标点符号(ispunct),都不要将其复制到输出字符串中。无论何时遇到“字母字符”(isalpha),请使用tolower将其转换为小写字母。

提及的所有功能都在<ctype.h>

您可以做到就地定义(通过保持独立的写指针和读指针指向字符串),或从它创建一个新的字符串。但是这完全取决于你的应用程序。

+0

更多详细信息在这里:http://stackoverflow.com/questions/421616/best-way-to-strip-punctuation-from-a-string – TStamper 2009-12-03 18:08:25

+0

TStamper,似乎没有C那里的例子! C#,C++,但没有C – 2009-12-03 18:10:24

+0

@ eliben-我的意思是详细的例子,而不是语言特定 – TStamper 2009-12-03 18:12:30

5

在C语言中这样做的习惯做法是有两个指针,一个源和一个目标,并分别处理每个字符:例如,

#include <ctype.h> 

void reformat_string(char *src, char *dst) { 
    for (; *src; ++src) 
     if (!ispunct((unsigned char) *src)) 
      *dst++ = tolower((unsigned char) *src); 
    *dst = 0; 
} 

src和dst可以是相同的字符串,因为目标不会大于源。

尽管它很诱人,但由于tolower可能被实现为宏,因此请尽量不要致电tolower(*src++)

避免搜索要替换字符的解决方案(使用strchr或类似方法),它们会将线性算法变成几何算法。

+0

对'ctype.h'函数的参数必须转换为'unsigned char'。 – 2009-12-03 18:20:58

+0

'* *'和'to *'函数的参数应该转换为'unsigned char'。 – pmg 2009-12-03 18:22:58

+0

谢谢,自从我编写产品C代码 – Ferruccio 2009-12-03 18:24:08

0

这里有一个答案的粗剪给你:

void strip_punct(char * str) { 
    int i = 0; 
    int p = 0; 
    int len = strlen(str); 
    for (i = 0; i < len; i++) { 
     if (! ispunct(str[i]) { 
      str[p] = tolower(str[i]); 
      p++; 
     } 
    } 
} 
+0

请参阅* Shlemiel画家的算法*:http://www.joelonsoftware.com/articles/fog0000000319.html – 2009-12-03 18:20:23

+0

“*”和“*”函数的参数应转换为'unsigned char'。 – pmg 2009-12-03 18:22:25

+0

Shlemiel在这里不适用:'strlen()'函数在循环外部使用一次。 – pmg 2009-12-03 18:26:40