2010-03-16 99 views
3
void RemoveSpace(char *String) 
{ 
    int i=0,y=0; 
    int leading=0; 

    for(i=0,y=0;String[i]!='\0';i++,y++) 
    { 
     String[y]=String[i]; // let us copy the current character. 

     if(isspace(String[i])) // Is the current character a space? 
     { 
      if(isspace(String[i+1])||String[i+1]=='\0'||leading!=1) // leading space 
       y--; 
     } 
     else 
      leading=1; 
    } 
    String[y]='\0'; 
} 

这样做是否可以消除前导和尾随空格以及用单个空格替换多个空格? 我测试它为空字符串,所有空格,领先的空白和尾随空格。将单个空格替换为单个空格并消除前导空格和尾部空格

您认为这是一种高效的一次性解决方案吗?

回答

0

根据你的代码,假设你的字符iswhite()是有效率的, (你可能不让它分开,因为它是所谓过于频繁) 承担字符串传递是有效的本身(应该是较为抗跌)

=======================

void RemoveSpace(char *String) 
{ 

    int i=0, j=0; 

    int inWhite=0; 

    char c = String[i++]; 
    while(c) 
    { 
     if (isspace(c)) 
     { 
      inWhite= 1; 
     } 
     else 
     { 
      // there are space before, and not beginning 
      if (inWhite && j > 0) 
      { 
       String[j++] = ' '; 
      } 
      String[j++] = c; 
      inWhite = 0; 
     } 

     c = String[i++]; 
    } 
    String[j]='\0'; 
} 

没有测试,请测试自己...

0

下面的代码应该做的它:

void rem_space(char *str) 
{ 
    int len = strlen(str) - 1; 
    int i = 0; 
    int spaces = 0; 

    if(str == NULL) return; 
    while(i < len){ 
     while(str[i] == ' ') {spaces++; i++;} 
     while(str[i] != ' ' && str[i] != '\0') {str[i - spaces] = str[i]; i++;} 
     if(str[i + spaces - 1] != '\0') { 
      str[i - spaces] = ' '; spaces--; 
     } else { 
      break; 
     } 
    } 
    str[i - spaces] = '\0'; 
    return; 
} 
+0

由于strlen,这是两次通过。 – 2016-02-16 15:40:00

0

这样做的办法是去除前导空白和尾随空白并用单个空格替换多个空格吗?

回答该问题的最佳方法是测试它。

void Test(const char *input, const char *expected_output) { 
    char buffer[80]; 
    strcpy(buffer, input); 
    RemoveSpace(buffer); 
    assert(strcmp(buffer, expected_output) == 0); 
} 

int main() { 
    Test(" Leading spaces removed.", "Leading spaces removed."); 
    Test("Trailing spaces removed. ", "Trailing spaces removed."); 
    Test("Inner spaces  trimmed.", "Inner spaces trimmed."); 
    Test(" A little of everything. ", "A little of everything."); 
    Test(" \tTabs \t\tare \t spaces, too.", "Tabs are spaces, too."); 
    return 0; 
} 

在OP中的代码没有通过最后的测试,所以答案是没有

您是否认为这是一种高效的单程解决方案?

这是一次性解决方案。如果你试图挤出每盎司的效率,那么你想尽量减少操作和条件分支的数量。

在C语言中使用C字符串时,通常使用指针而不是索引来使用指针。根据编译器和目标平台的不同,使用指针可能比索引效率更高或更低,但两者的成本都很低。由于这已经是一次单一的线性通过,所以最好的办法是使用惯用的代码模式尽可能清楚地写出它。

这里是我的解决方案:

#include <assert.h> 
#include <ctype.h> 
#include <string.h> 

void RemoveSpace(char *string) { 
    char *target = string; 
    char *last = target; 
    int skipping_spaces = 1; 

    for (const char *source = string; *source != '\0'; ++source) { 
     if (isspace(*source)) { 
      if (!skipping_spaces) { 
       *target++ = *source; 
       skipping_spaces = 1; 
      } 
     } else { 
      *target++ = *source; 
      last = target; 
      skipping_spaces = 0; 
     } 
    } 
    *last = '\0'; 
} 

它本质上是一个小的状态机,这意味着,在每一步,我们决定基于当前输入字符和当前状态做什么。对于这个问题,我们的状态就是我们是否正在跳过空格(还有一个书签记录最后一个结束字符串的合法点)。

0

首先,显然它是一次性的。但是,如果输入有多个前导空格,则会出现问题。例如:

输入:" text"输出:" text"

幸运的是,它很容易修复。你只需要一个额外的循环:

void RemoveSpace(char *string) 
{ 
     int i = 0, y = 0; 
     while(isspace(string[i]))   // Discard leading spaces. 
       i++; 
     for(y = 0; string[i]!='\0'; i++) 
     { 
       string[y] = string[i]; // let us copy the current character. 

       if(!isspace(string[i]) || !isspace(string[i+1]) && !string[i+1]=='\0') 
         y++;    // This character shall not be covered. 
     } 
     string[y] = '\0'; 
} 

我也做了一些修改,使你的代码看起来更好,这实际上是不相关的。

相关问题