+ -
当前位置:首页 → 问答吧 → 谁来帮我纠正一下!

谁来帮我纠正一下!

时间:2010-07-27

来源:互联网

Linux C我是自学的.学习过程中留下不少的毛病.
比如,我要写一个类似于strcpy的函数func吧,我可能就这么写

#include <stdio.h>

char aa[1024];

char * func(char *src)
{
      ......                 //把src的字符一个一个写入到aa
      aa[end]=0;    //end为aa拷贝完成后的下标+1
      return aa;
}


请问各位高手,你们写这类函数也会定义一个全局变量aa,然后在函数中return 这个aa吗?
请show一下你们是怎么写的?

作者: kwaz   发布时间: 2010-07-27

  1. /* copy: copy 'from' into 'to'; assume to is big enough */
  2. void copy(char to[], char from[])
  3. {
  4.       int i;
  5.       i = 0;
  6.       while ((to[i] = from[i]) != '\0')
  7.              ++i;
  8. }
复制代码

作者: pandaiam   发布时间: 2010-07-27

这样的设计不好吧,看一下glibc中的吧。

作者: ecjtubaowp   发布时间: 2010-07-27



QUOTE:
pandaiam 发表于 2010-07-27 09:15




    可是这样的话,就不能这样写了:

   strcpy(another,func("123"));

作者: kwaz   发布时间: 2010-07-27

本帖最后由 zhangsuozhu 于 2010-07-27 09:29 编辑
  1. char *copy(char *to, char *from)
  2. {
  3.       char *ret = to;
  4.        while (*from!= '\0')  
  5.                     *to ++ =  *from ++;

  6.         *to = '\0';
  7.         return ret;
  8. }
复制代码

作者: zhangsuozhu   发布时间: 2010-07-27

本帖最后由 kwaz 于 2010-07-27 09:25 编辑


QUOTE:
这样的设计不好吧,看一下glibc中的吧。
ecjtubaowp 发表于 2010-07-27 09:15




    好难看啊,想看看你们怎样做的.

    要求目前就两个.

    1.一个字符一个字符的赋值

 2.char * func(char *src)

作者: kwaz   发布时间: 2010-07-27



QUOTE:
zhangsuozhu 发表于 2010-07-27 09:22




    问一下兄弟,如果只想要一个参数呢?

   char * func (char *src)

    函数该怎么写呢?

作者: kwaz   发布时间: 2010-07-27

回复 kwaz


    这涉及到内存分配的不对称释 放。。。相当于 strdup() 函数

作者: zhangsuozhu   发布时间: 2010-07-27

本帖最后由 davelv 于 2010-07-27 09:39 编辑

C语言的函数库中大多数有这么一个规定,谁分配谁释放。
如果一个函数使用了堆分配空间的话,它一般都有一个说明,用自己包装的destroy之类的函数或者free去释放资源。

作者: davelv   发布时间: 2010-07-27

本帖最后由 zhangsuozhu 于 2010-07-27 09:40 编辑
  1. char *strdup(char *from)
  2. {
  3.       char *buf = NULL;
  4.       char *p = NULL;
  5.        unsigned int size;

  6.         if (!form)
  7.                return NULL;
  8.          size = strlen(form);
  9.          if(!size)
  10.                 return NULL;
  11.           size ++;
  12.          
  13.           if ((buf = malloc(size)) = NULL)
  14.                                 return NULL;
  15.          
  16.         p = buf;
  17.        while (*from!= '\0')  
  18.                     * p++ =  *from ++;

  19.         *p = '\0';
  20.         return buf;
  21. }
复制代码
格式对不齐了。将就的看吧

作者: zhangsuozhu   发布时间: 2010-07-27

本帖最后由 kwaz 于 2010-07-27 09:59 编辑

试了一下,是我想要的效果.

程序如下:
#include <stdio.h>
#include <string.h>
#include <malloc.h>

char *strkb(char *from)
{
      char *buf=NULL;
      char *p=NULL;
      unsigned int size;
      if(!from)
        return NULL;
      size=strlen(from);
      if(!size)
        return NULL;
      size ++;
      if ((buf=malloc(size))==NULL)
         return NULL;
      p=buf;
      while(*from!='\0')  
         *p++=*from++;
      *p='\0';
      return buf;
}

main()
{
           char *tt=strkb("I love china");
           printf("%s\n",tt);
}


再问2个问题:
1.那strkb中buf还需要自己另外写代码去释放吗?
2.如果这个程序不允许使用string.h,那么strlen就不能用,又应该怎么改?
  难道是
  int len=0;
  while(*from++!=0)
        len++;
   这样来得到它的长度?
  还是另外有什么更好的办法?

  不好意思,比较罗嗦。

作者: kwaz   发布时间: 2010-07-27

1 没听过strkb这个函数, 如果是strdup函数的话, 是要自己手动free的
2 要得到它的长度好像只有这么干

作者: mgqw   发布时间: 2010-07-27



QUOTE:
1 没听过strkb这个函数, 如果是strdup函数的话, 是要自己手动free的
2 要得到它的长度好像只有这么干
mgqw 发表于 2010-07-27 10:02




    strkb是前面那位老兄给的函数,我只是改个名字而已啊。
   
   你看一下,strkb不是出现在我的程序中吗?


   还有,你说的free,应该怎么free?在什么地方free呢?

   不好意思,我实在是不清楚这些东东。想好好学习一下!请不吝赐教!

作者: kwaz   发布时间: 2010-07-27

在函数中看到这个malloc了吧, 只有malloc没有free的话肯定是要泄漏内存的
if ((buf=malloc(size))==NULL)

作者: mgqw   发布时间: 2010-07-27



QUOTE:
在函数中看到这个malloc了吧, 只有malloc没有free的话肯定是要泄漏内存的
if ((buf=malloc(size))==NULL)
mgqw 发表于 2010-07-27 10:12



兄弟,那个程序你帮我修改一下可以吗?
我想看看你是怎么free的?

作者: kwaz   发布时间: 2010-07-27

if ((buf=malloc(size))==NULL)
         return NULL;
      p=buf;
      while(*from!='\0')  
         *p++=*from++;
      *p='\0';
      return buf;
其实就是这一段代码说的是malloc, 而free的地方则是调用这个函数返回的字符串已经使用完成了, 就对这个字符串free就ok了
char *strkb(char *from)
比如:
char *p;
p = strkb("aabbcc");
…………中间一些处理过程
free(p);

作者: mgqw   发布时间: 2010-07-27

哦,就是说,要在main函数中free.

明白了一些。

可是我觉得,在函数中malloc,后在main中free,
有时候还不如我定义一个全局变量,
这样,就不用我每次去free了。

但这样也有缺点:
1.定义这个变量名怕在程序中重复了
2.有时候,在一个语句中多次使用一个func函数,多次的结果是一样的,都是最后一次func的结果.

太乱了!

作者: kwaz   发布时间: 2010-07-27



QUOTE:
哦,就是说,要在main函数中free.

明白了一些。

可是我觉得,在函数中malloc,后在main中free,
效果上 ...
kwaz 发表于 2010-07-27 10:25


这是是一个封装/模块化的问题,如果封装度不够高,东西很容易使用,也很容易产生混乱。反之,使用必须按照某种特定规则,也减少了混乱的产生。
封装在百千的小程序中来说并不是很重要,如果程序更复杂就很必要了,自己按需取舍。

作者: davelv   发布时间: 2010-07-27

写代码切记:
能不用全局变量就别用全局变亮
可以用static const等关键字限制变量的, 就一定要使用
能不用malloc/free的地方, 就千万别用这个, 就像上面那个函数, 完全可以在main函数中定义char str[64];这样的字符数组来代替。

乱七八糟写代码,代码量小无所谓,等上万行了, 你再回回头去看你自己写的代码, 你会有想自杀的冲动。

作者: mgqw   发布时间: 2010-07-27



QUOTE:
再问2个问题:
1.那strkb中buf还需要自己另外写代码去释放吗?
2.如果这个程序不允许使用string.h,那么strlen就不能用,又应该怎么改?
  难道是
  int len=0;
  while(*from++!=0)
        len++;
   这样来得到它的长度?
  还是另外有什么更好的办法?

  不好意思,比较罗嗦。
kwaz 发表于 2010-07-27 09:58



1.是的。在用完strkb后,要free掉strkb分配的内存
  1. int main()
  2. {
  3.         char *p = strkb("aaaaa");
  4.          /* ........ */
  5.          if(p)
  6.                  free(p);
  7.          p = NULL;
  8.          return0;
  9. }
复制代码
2.如果这个程序不允许使用string.h,那么strlen就不能用,又应该怎么改?
象你一样。可以把这个函数改名。之所以起strdup这个名子,是想用一个人人皆知的libc string函数让你知道,这个函数中会分配内存!要手动释放.

3. strlen 函数可用多种写法实现.
如:
  1. int len=0;
  2. while(from[len ++]!='\0'){};

  3. len --;


  4.         
复制代码

作者: zhangsuozhu   发布时间: 2010-07-27

一返回马上就要复制走的,可以利用栈空间,

char* xxx(){
char buf[0x4000];
carh* ret = buf+0x1000;
memcpy(ret, "abc...", n); // n < 0x2000
return ret;
}

马上复制走,返回是写在buf中间,不管栈生长方向,有点保证吧

作者: zliming   发布时间: 2010-07-27

这哪是类似 strcpy() 的函数。你这函数是用来干什么的?

作者: langue   发布时间: 2010-07-27

上面不是在说有时要用空间,又不知道谁免责清的。

我是之前做字符集转换时,为了效率不想在中间再分配复制多一次,就直接用了栈里的空间返回

作者: zliming   发布时间: 2010-07-27

本帖最后由 kwaz 于 2010-07-27 11:46 编辑

是这样的,我的程序比较大,用到很多字符串函数,这些字符串函数大部分是要自己写的,不能直接用string.h
如:在字符串中按空格区分,取第n个“字段”的函数等等等等。

同时,我的程序不下于1000次调用这些函数,我就是想按自己的方式去实现这些函数。

如:

char * strfld(char *src,int n)               //在src中,按空格区分,取第n个字段返回

char * myupper(char *src)                 //在src小些转大写

....

这类的函数一多,在main中针对每个函数或每次调用都定义变量就太罗嗦了。

因此才有定义全局变量一说。
首先,不要free,由程序自动free,
其次,在函数中可以retrun 全局变量,那么在main中可以直接使用全局变量,不需要复制。(当然也可以复制)

作者: kwaz   发布时间: 2010-07-27

那你直接参考库里面的字符串函数是怎么写的, 怎么调用的, 自己模拟实现就是了

作者: mgqw   发布时间: 2010-07-27

本帖最后由 zhangsuozhu 于 2010-07-27 14:01 编辑
  1. /* 用全局,别有这样的调用.  */

  2. sprintf("%s %s", strkb("aaaa"), strkb("bbbb");
复制代码
如果存在这样的调用.你会发现printf出的全是bbbb.  ???


全是aaa吧! 我记不清了.

作者: zhangsuozhu   发布时间: 2010-07-27



QUOTE:
如果存在这样的调用.你会发现printf出的全是bbbb.
zhangsuozhu 发表于 2010-07-27 12:13




对,就是会出现这样啊。

作者: kwaz   发布时间: 2010-07-27

继续求好的解决方案!!!

作者: kwaz   发布时间: 2010-07-27

本帖最后由 zhangsuozhu 于 2010-07-27 14:21 编辑
  1. #include <stdio.h>
  2. #define MAX_POOL_SIZE 1024

  3. char pool[MAX_POOL_SIZE];
  4. int  pos;

  5. char *new_str(char *str)
  6. {
  7.     char *head = &pool[pos];
  8.     if (pos >= MAX_POOL_SIZE) return NULL;
  9.     while((pool[pos++] = *str ++) != '\0' && pos < MAX_POOL_SIZE)
  10.         ;
  11.     return head;
  12. }

  13. int main(int argc,  char* argv[])
  14. {
  15.     printf("%s,%s,%s\n", new_str("aaa")?:"NULL",new_str("bbb")?:"NULL",new_str("ccc")?:"NULL");
  16.     return 0;
  17. }
复制代码

作者: zhangsuozhu   发布时间: 2010-07-27

你要的 strcpy(3),我实现给你了。

char *strcpy(char *dest, const char *src)
{
    char *orig = dest;

    while (*dest++ = *src++)
        ;

    return orig;
}

作者: langue   发布时间: 2010-07-27