题目:在字符串中删除特定字符。删除后字符串变为"hi i a",即将原串中包含t、e、s中的都删除掉了。
分析:方法(1):从头扫描原串,每遇到一个字符,在要删的串中比一遍,有的话就删除当前字符,然后继续下一个字符的判断。方法(2):由于方法(1)由三步完成:第一:扫描原串 第二:拿着原串中的字符在要删的串中找一遍第三:找到后删除。方法(2)的思路是优化第二、第三步。第二步我们可以用一个数组exits统计要删的字符有哪些,即拿要删串的每个字符为下标,并将以该下标的元素值置1(如果要删的字符中有a,那么将exits[97]置1,),这样的话扫描原串的时候就不要一遍一遍扫描要删的串了,直接用下标对应的数组元素判断。至于第三步的优化,我们不是找到要删的元素,将后面的移前来,下一次又找到一个要删除的,再将剩下的移前来,这样会导致很多字符要移动很多次,我们可以用两个下标dest,src控制,src负责遍历原串,dest负责指向要留下的,遇到要留下的,src赋给dest,二者都往后移,遇到要删除的,src往后移,dest不动(也就是说,dest放过去的都是要最后留下的,并且这将是每个字符最终应该所在的位置)。
方法(1):
void remove_chars1(char str[], const char remove[])
{
assert(str);
assert(remove);
int len1 = strlen(str);
int len2 = strlen(remove);
for (int i = 0; i < len1; i++)
{
int j = 0;
for (j = 0; j < len2; j++)
{
if (str[i] == remove[j])
{
strcpy(str+i, str +i+1);
i--;//当后一个拷前来时,如果不减1的话,上去i++就会跳过当前位置(当前位置就被忽略了)
break;
}
}
}
}
方法(2):
void remove_chars2(char str[], const char remove[])
{
int exits[256] = {0};
//将remove数组中的字符作为下标,将exits对应元素置1
for (int i = 0; remove[i] != '\0'; i++)
{
exits[remove[i]] = 1;
}
int dest = 0;
int src = 0;
while (str[src] != '\0')//遍历原串
{
if (exits[str[src]] == 0)//不要删除
{
str[dest] = str[src];
dest++;
}
//无论如何src要加加(遍历)
src++;
}
str[dest] = '\0';
}