Chinaunix

标题: 想弄一个函数去掉字符串左边空格, 出问题啦 [打印本页]

作者: sunshine1750    时间: 2007-04-19 17:37
标题: 想弄一个函数去掉字符串左边空格, 出问题啦
偶是菜鸟, 路过的请指点一下

int ltrim(char *ss) {
  while( *ss == ' ') {
   ss = ss+1;
   printf("%p\n", ss);      
}
  return(0);                    /* 到这里, ss已经变成"abc"了 */
}


main()
{
  char *s;
  s = "  abc";
  ltrim(s);
  printf("---%s---",s);   /* 为什么还是"  abc"啊? */
  getchar();
  return (0);
}

[ 本帖最后由 sunshine1750 于 2007-4-19 22:17 编辑 ]
作者: rxpmcb    时间: 2007-04-19 17:38
这样的问题交给Perl吧
作者: epegasus    时间: 2007-04-19 17:43
s = (char *)malloc( 20 );
  s = "  abc";
这样写不觉得多余吗?
ltrim(s);
这里上传值传给了函数里的一个栈变量ss;
ss = ss+1;
你改变的只栈变量ss,而不是s
作者: Edengundam    时间: 2007-04-19 17:44
传指针的指针
作者: yuangong    时间: 2007-04-19 18:03
int ltrim(char *ss) {
  int i;
  while( *ss == ' ') {
   ss = ss+1;
   printf("%p\n", ss);      /* 循环能看到ss首地址加1 */
  }
  if (*ss == 0) {*ss=' '; *(ss+1)=0;}      //这句有什么作用,程序跑不到这.
  return(0);                    /* 到这里, ss已经变成"abc"了 */
}


main_()
{
  char *s;
  s = (char *)malloc( 20 );        //没用处
  s = "  abc";
  ltrim(s);
  printf("---%s---",s);   /* 为什么还是"  abc"啊? */
  getchar();          //编译工具 turbo c?
  return 0;
}


实现有2种方法1:传双指针  2:ltrim 返回 指针.
PS:虽然初学,编码格式还是需要注意的.
作者: shello    时间: 2007-04-19 18:14

  1. /* 去掉 s中所有的空格,\n,\t  */
  2. char*        trim(char* s)
  3. {
  4.         long        lLen;
  5.         register        i, k;

  6.         //        输入为空则直接返回
  7.         if(!s) return NULL;

  8.         lLen = (long)strlen(s);
  9.         for(i = 0, k = 0; i < lLen; i++)
  10.         {
  11.                 if(s[i] != ' ' && s[i] != 9 && s[i] != 10 && s[i] != 13)
  12.                         s[k++] = s[i];
  13.         }
  14.         s[k] = 0;
  15.         return s;
  16. }
复制代码

满足楼主需求否?
作者: rainballdh    时间: 2007-04-19 18:31
  1. #include <stdio.h>
  2. #include <string.h>

  3. void ltrim(char *str);

  4. int main()
  5. {
  6.   char s[]="      abcda";

  7.   ltrim(s);

  8.   printf("----%s----\n",s);

  9.   return 0;
  10. }

  11. void ltrim(char *str)
  12. {
  13.   int i=0,j=0;

  14.   int len=strlen(str);

  15.   while(str[i] == ' '){
  16.        for(j=i;j<len;j++)
  17.            str[j]=str[j+1];
  18.   }

  19. }
复制代码

作者: sunshine1750    时间: 2007-04-19 18:42
谢谢楼上各位了~~~

to: yuangong
多谢提醒, 写的是proc程序, 用turbo c方便调试
双指针是指向指针的指针吗? 我的理解ltrim(char *ss)已经是传址了;
作者: yuangong    时间: 2007-04-19 18:46
何必这么麻烦!
char *ltrim(char *ss) {
        char *p;
        p = ss + 2;
        return p;
}
搞定
作者: jist12321    时间: 2007-04-19 18:51
你这里定义的是char *s,这时的s是一个变量,是一个指向指针的变量,你要改变他的地址,那么你就得把指针这个变量的地值传进去,也就是说参数里应该是int ltrim(char **ss), 这时,你再试试看.

[ 本帖最后由 jist12321 于 2007-4-19 18:59 编辑 ]
作者: sunshine1750    时间: 2007-04-19 23:25
改好了, 虽然ltrim(char *ss)传入地址, 但本质上还是传值,
因为形参和实参占用不同的内存地址, 但它们指向同一地址

方法一:返回字符指针:
char *ltrim(char *ss) {
  char *p;
  while( *ss == ' ') {
   ss = ss+1;
   printf("%p\n", ss);
  }
  p = ss;
  return p;
}

main()
{
  char *s;
  s = "  abc";  /* 比如s指向FFD0 */
  s = ltrim(s); /* 现在s指向FFD2 */
  printf("---%s---\n",s);
  getchar();
  return 0;
}

方法二:
void ltrim(char *ss);
int main()
{
  char *s;   s = (char *)malloc(10);
  strcpy(s, "  abc";   /* 比如s指向FFD0 */
  ltrim(s); /* 现在s仍指向FFD0, 但FFD0开始的字符串由"  abc"\0变成了"abc"\0\0 */
  printf("---%s---\n",s);
  getchar();
  free(s);
  return 0;
}

void ltrim(char *ss)
{
  int j=0;
  int len=strlen(ss);
  while(ss[0] == ' '){
       for(j=0;j<len;j++)
           ss[j]=ss[j+1];
  }
}

方法一调用较麻烦,运行效率高;
方法二调用方便, 运行效率差;
有没可能综合方法一,二的优点,用指向指针的指针来实现?

[ 本帖最后由 sunshine1750 于 2007-4-20 15:51 编辑 ]
作者: sunshine1750    时间: 2007-04-20 00:17
原帖由 jist12321 于 2007-4-19 18:51 发表
你这里定义的是char *s,这时的s是一个变量,是一个指向指针的变量,你要改变他的地址,那么你就得把指针这个变量的地值传进去,也就是说参数里应该是int ltrim(char **ss), 这时,你再试试看.


不知道怎么做, 能给个DEMO吗?
作者: snow888    时间: 2007-04-20 00:20
这个问题是刚刚开始学 C 的朋友经常性犯的错误。
作者: sunshine1750    时间: 2007-04-20 08:43
顶一把
作者: cugb_cat    时间: 2007-04-20 09:02
其实指针变量和普通变量是一样的,在向函数传参数的时候也是一样的,统一对待~
在函数中改变指针的值和在函数中改变指针指向地址单元的值是不一样的
改变指针的值是不会反映给调用者的~
作者: zghover    时间: 2007-04-20 09:28
方法二:
void ltrim(char *ss);
int main()
{
  char *s="  abc"; /* 比如s指向FFD0 */
  ltrim(s); /* 现在s仍指向FFD0, 但FFD0开始的字符串由"  abc"\0变成了"abc"\0\0 */
  printf("---%s---\n",s);
  getchar();
  return 0;
}

void ltrim(char *ss)
{
  int j=0;
  int len=strlen(ss);
  while(ss[0] == ' '){
       for(j=0;j<len;j++)
           ss[j]=ss[j+1];
  }
}


这里的方法二是错误的,不知道你在机器上跑过没有。
char *s="  abc"
你这里定义了一个指向常量字符串"  abc"的字符串指针,而这里的"  abc"是放在只读存储区里的,是不能写,和修改的, 象这样 s[0]='d' 给这段内存区重新赋值是错误的。会出现 "段错误"

而前面rainballdh兄写的是 char s[]="  abc"和你写的是不一样的,这里定义的是一个字符串数组,内核是要为该数组分配内存空间的(而上面定义的只是一个指针)。

[ 本帖最后由 zghover 于 2007-4-20 09:31 编辑 ]
作者: snow888    时间: 2007-04-20 09:43
原帖由 zghover 于 2007-4-20 09:28 发表
void ltrim(char *ss)
{
  int j=0;
  int len=strlen(ss);
  while(ss[0] == ' '){
       for(j=0;j<len;j++)
           ss[j]=ss[j+1];
  }
}


这个如下改,就可以了.

  1. char *ltrim(char *ss)
  2. {
  3.   int j=0,i=0;
  4.   int flag = FALSE;
  5.   int len=strlen(ss);
  6.   for(j=0;j<len;j++)
  7.   {
  8.        if( ss[j] == ' ' && flag == FALSE)
  9.            i++ ;
  10.        else {
  11.            ss[j]=ss[j+i];
  12.            if ( ss[j] != ' ')
  13.                 flag = TRUE ;
  14.        }
  15.     }
  16.     ss[j-i] = '\0';
  17.     return(ss);
  18. }

复制代码


写得好混乱,大概可以满足要求吧.  ^_^.
作者: slay78    时间: 2007-04-20 09:57
显然要移动内存吧,只是改一下字符串头的位置另外弄个字符串出来早晚会弄些野指针出来
还有如果是 trim(char ** str),传出来的字符串你还敢free么
作者: sunshine1750    时间: 2007-04-20 15:44
原帖由 cugb_cat 于 2007-4-20 09:02 发表
其实指针变量和普通变量是一样的,在向函数传参数的时候也是一样的,统一对待~
在函数中改变指针的值和在函数中改变指针指向地址单元的值是不一样的
改变指针的值是不会反映给调用者的~

顶这个~~~

原帖由 zghover 于 2007-4-20 09:28 发表
方法二:
void ltrim(char *ss);
int main()
{
  char *s="  abc"; /* 比如s指向FFD0 */
  ltrim(s); /* 现在s仍指向FFD0, 但FFD0开始的字符串由"  abc"\0变成了"abc"\0\0 */
...

说得对, 我修改了那一贴




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2