------------------------------------------
本文为本人原创,欢迎转载!
雪夜流星
------------------------------------------
本文针对实现去除字符串左右空格的功能进行探讨,在牛人代码的基础上进行改进并加以注释。本文参照了cu论坛flw的精华帖,在此表示感谢:
源实现如下:
- #include <stdio.h>
- #include <stdlib.h>
- /*****************************************************************
- *函数功能:去除字符串左右两边的空格
- *传入参数:str:需要处理的字符串
- *传出参数:无(由于传入的是指针,形参指向元素的改变将影响实参)
- *返回值:无
- *******************************************************************/
- void trim( char *str )
- {
- char *copied, *tail = NULL;
-
- /*判空*/
- if ( str == NULL )
- return;
-
- /*去除字符串左边空格,并找到字符串右边的第一个空格*/
- for( copied = str; *str; str++ )
- {
- /*当前字符不为空格时,将当前字符拷贝到新的字符串中,并更新tail指针指向的空间
- 为新字符串的尾部*/
- if ( *str != ' ' && *str != '\t' )
- {
- *copied++ = *str;
- tail = copied;
- }
- else
- {
- /*当tail不为空时,将当前字符拷贝到新的字符串中:由于tail初值为NULL,
- 找到第一个非空格字符时才会将其值更新,所以能够保证去除字符串左边
- 的空格,而保留中间和右边的空格*/
- if ( tail )
- *copied++ = *str;
- }
- }
-
- /*去除字符串右边的空格:如果tail非空,则将tail赋'\0'(将其后的字符截断);
- 否则将字符串清空(即传入字符串全为空格)*/
- if ( tail )
- *tail = 0;
- else
- *copied = 0;
- return;
- }
- int main(void)
- {
- char string[100] = " abcd ef gh -- ijk ";
- trim(string);
- printf(string);
- printf("\n");
- return 0;
- }
由于上面的代码需要移动字符串中元素,可能效率较慢,本人的思路是将第一个非空格字符处做一
标记(将一局部指针指向此处),找到右边第一个空格并将其赋值为字符串结束符。最后返回局部指针。程序实现如下:
- #include <stdio.h>
- #include <stdlib.h>
- /*************************************************
- *函数功能:去除字符串左右两边的空格
- *传入参数:str:需要处理的字符串
- *传出参数:无
- *返回值:处理后的字符串
- ************************************************/
- char * trim( char *str )
- {
- char *head, *tail = NULL;
-
- if ( str == NULL )
- return str;
-
- for( head = str; *str; str++ )
- {
- if ( *str != ' ' && *str != '\t' )
- {
- if (tail == NULL)
- {
- head = str;//tail为NULL时,此处为第一个非空格字符,将此位置保存下来
- }
- tail = str+1;//更新tail指针的指向为非空格字符的下一个位置
- }
- }
- /*由于tail始终指向非空格字符的下一个位置,当循环退出时,tail指向右边第一个空格*/
- if ( tail )
- *tail = 0;
- else
- *head = 0;
-
- return head;
- }
- int main(void)
- {
- char string[100] = " abcd ef gh -- ijk ";
- char * p = trim(string);
- printf(p);
- printf("\n");
- return 0;
- }
除了上面这种思路,还有一种思路是“从前往后数掉前面的空格”,再“从后往前数掉后面的空格”,等“数”出了实际有效的第一个字符和最后一个字符之后,再用 strcpy 或者 memcpy 拷贝过去。
本人思路:
char *trim(char *str)
{
int i = 0;
int j = 0;
int len = strlen(str);
assert(str !=NULL && len>0);
for (i = 0; i
{
if (*(str+i) != ' ' && *(str+i) != '\t')
{
break;
}
}
for (j = len-1; j>=0; j--)
{
if (*(str+j) !=' ' && *(str+j) != '\t')
{
break;
}
}
*(str+j+1) = '\0';
return str+i;//等价于return memmove(str,str+i,j-i+2);此处其实亦可以用memcpy(参考其实现)
}
事实上,Trim 从算法上来讲,也就这两个思路,大多数人采用的是后面的这个思路,好像依赖于 strlen、memcpy 等库函数的效率后,反而要更快些。而上面的那个思路,似乎没有多少人去想,结果就吃亏在“效率”问题上了。
关于第二种思路在此不再继续探讨,如果有兴趣可以参照文章:
上面这边文章中的不足是,最后的memcpy函数源和目的地址存在重叠情况,结果依赖于实现,应该使用memmove。
阅读(8671) | 评论(0) | 转发(0) |