从字符数组中删除某些元素

时间:2018-07-16 00:20:38

标签: c string

我有一个函数,可以从给定的字符串中删除标点符号,并将其所有内容都转换为小写:

void stripPunctuators(char *str)
{
  int i, j, len = strlen(str);


  for (i = 0; i < len; i++)
  {
     if (!isalpha(str[i]))
     {
       for (j = i; j < len; j++)
       {
         str[j] = str[j + 1];
       }
       len--;
     }

     str[i] = tolower(str[i]);
  }
}

但是由于某种原因,当我连续有两个非字母字符时会遇到麻烦... 这是我的主要功能:

 int main(void)
 {
   char str[50] = "Hello.";

   printf("Before strip: %s\n", str);
   stripPunctuators(str);
   printf("After strip: %s\n", str);

   char str2[50] = "Hello.!";

   printf("Before strip: %s\n", str2);
   stripPunctuators(str2);
   printf("After strip: %s\n", str2);

   return 0;
}

最后,这是我的输出:

Before strip: Hello.
After strip: hello
Before strip: Hello.!
After strip: hello!

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

考虑诸如a!@b之类的短字符串可能会有所帮助。由于使用了0..3循环,因此索引变量将遍历值for。现在按照以下顺序进行操作:

0123     <- indexes
----
a!@b     starting point, index = 0
a!@b     index 0 was a, no shift, set index to 1
a@b      index 1 was !, shift, set index to 2 ***
a@b      index 2 was b, no shift, set index to 3, exit loop

由此,您应该能够看到,移动字符串的其余部分 并增加索引将导致跳过下一个字符(有关位置,请参见***标记出了错)。

您可以通过使用循环来解决此问题,该循环在进行移位时这段时间内索引不会递增(可能使用while而不是for一个好主意)。这样,无增量移位将使您重新检查相同索引,该索引是 next 字符(由于移位)。

但是,每次您想删除一个字符时都要对字符串余数进行一次完全移位是很低效的,因为很有可能您需要再次更改这些字符。

您最好使用带有(伪代码)之类的源和目标指针:

set src and dst to address of first character
while character at src is not end-of-string:
    if character at src is not punctuation:
        set character at dst to be character at src
        increment dst
    increment src
set character at dst to be end-of-string

而且,如果您希望在C语言中使用它,将遵循以下原则:

void stripPunctuators(char *str) {
    char *src = str;
    char *dst = str;
    while (*src != '\0') {
        if (isalpha(*src)) {
            *dst = *src;  // or combine:
            dst++;        //   "*dst++ = *src"
        }
        src++;
    }
    *dst = '\0';
}
  

请注意,我在代码中使用了isalpha只是因为那是您在原始代码中使用的那个。由于这将去除标点符号(例如,数字)之外的内容,因此您可能需要重新检查它是否适合使用。 isalnum函数可能更合适,但也取决于您的用例。您可能还需要保留空间。

     

否则,可能会变得杂乱而难以阅读:-)

答案 1 :(得分:2)

您在函数 stripPunctuators 中犯了一个错误。

  

FOR LOOP 中,您使用过:

str[j] = str[j+1];
  

上面的语句是错误的,因为在For循环中运行时,不应在语句的两边使用循环的相同变量。

尝试更改

str[j] = str[j+1] TO str[i] = str[j+1]
  

代码是

void stripPunctuators(char *str){

int i, j, len = strlen(str);
for (i = 0; i < len; i++){
 if (!isalpha(str[i]))
 {
   for (j = i; j < len; j++)
   {
     str[i] = str[j + 1];
   }
   len--;
 }
 str[i] = tolower(str[i]);} }
  

尝试使用上面的代码,问题将得到解决。