All things are difficult before they are easy. 没有软件的裸机是一具僵尸,没有硬件的软件是一个幽灵。2012,专注于Linux和C语言,关注自动化、性能测试,关注开源社区和开源测试工具、方法,尝试测试团队管理!

C语言实现strlen函数的几种方法

上一篇 / 下一篇  2010-10-10 20:29:33 / 个人分类:C/C++

今天偶然看到了一个实现strlen函数的方法,也实际练习了一下,挺有意义的,其实现的一些思想值得学习,记录一下吧。我这里除了写两个比较巧妙的递归实现之外,也写了另外一种常规的方式。
传说常见的一个笔试题:不使用中间变量求const字符串长度,即实现求字符串长度库函数strlen函数。函数接口声明如下:int strlen(const char *p);
思路分析:
在字符串中通常可以利用最后一个结束符’\0’,但此处参数为const,只读,那么我们不能打他的主意。
函数运行过程中不占用内存基本不可能,除非都使用了寄存器。“不使用中间变量”只是说程序员不能显示的申请内存而已,即不能有局部变量或者动态内存申请。
如果函数自动申请栈内存或者使用寄存器存储变量,或者使用立即数寻址即常量,那么就相当于“不使用中间变量”。
从函数原型看,返回值为int,那么在函数内部必定需要一个地方存储这个值,要么是常数要么是寄存器。长度不为1时不能一次就求出来,说明必须有递归调用,这样递归时函数会自动申请栈内存,这样就相当于程序员“不使用中间变量”了。中间返回的值通过寄存器自动保存,最后一次返回时拷贝到int中去。C/C++中也有临时对象的概念,都是程序在运行过程中由编译器在栈中自动申请的对象,对程序员不可见,也相当于“不使用中间变量”
另外一个不申请任何变量的典型题目是:反转字符串(http://blog.csdn.net/sailor_8318/archive/2008/10/11/3058240.aspx
这种问题都是利用常量,或者将变量的申请交给编译器在递归过程中自动在栈中申请,也就是借刀杀人了。
无代码,无真相;简单的源码如下:
#include <stdio.h>
#include <string.h>
#include <assert.h>

int myStrlen(const char *str);
int myStrlen1(const char *str);
int myStrlen2(const char *str);

int main()
{
    char *str=NULL;
    str = "Hello Jay!";
    printf("original strlen():%d\n",strlen(str));
    printf("myStrlen():%d\n",myStrlen(str));
    printf("myStrlen1():%d\n",myStrlen1(str));
    printf("myStrlen2():%d\n",myStrlen2(str));
}

int myStrlen(const char *str)   /* 不用中间变量,用递归实现,很容易看懂 */
{
    if ( (str == NULL) || (*str == '\0') ) {
        return 0;
    }
    else {
        return myStrlen(str+1)+1;
    }
}

int myStrlen1(const char *str)  /* 不用中间变量,也是用递归实现,写得更简洁而已 */
{
    assert(str != NULL);
    return *str ? (myStrlen1(++str) + 1) : 0;
}

int myStrlen2(const char *str)  /* 使用了一个int型变量 */
{
    if(str==NULL) return 0;
    int len = 0;
    for(; *str++ != '\0'; )
    {
        len++;
    }
    return len;
}
注:我的三个strlen都对str等于NULL做了兼容的,而貌似strlen(NULL)会“Segmentation fault”。
另外,这里再把网上找的strcpystrcat、strlen、strcmp的C语言简单实现贴在这里吧,也是很基础的东西,自己也好好学习一下。

char * strcpy (char * dst, char * src)
{
      char * cp = dst;

      while( *cp++ = *src++ )
      ;               /* Copy src over dst */
      return( dst );
}

char * strcat (char * dst, char * src)
{
      char * cp = dst;

      while( *cp )
           ++cp;           /* Find end of dst */
      while( *cp++ = *src++ )
      ;               /* Copy src to end of dst */
      return( dst );

}

int strlen (const char * str)
{
     int length = 0;

     while( *str++ )
          ++length;

     return( length );
}

int strcmp (unsigned char *src, unsigned char *dst)
{
        int ret = 0 ;

        while( ! (ret = *src - *dst) && *dst)
             ++src, ++dst;

        if ( ret < 0 )
              ret = -1 ;
        else if ( ret > 0 )
              ret = 1 ;

        return( ret );
}

参考资料:http://blog.csdn.net/Vonger/archive/2009/12/10/4980322.aspx

TAG: strcat strcmp strcpy strlen

 

评分:0

我来说两句

smile665

smile665

Stay hungry, stay foolish. 得意之时谨记,一半命运还掌握在上帝手里;失意之时须知,一半命运还掌握在自己手里。

日历

« 2024-04-15  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 954609
  • 日志数: 220
  • 建立时间: 2008-11-06
  • 更新时间: 2012-10-06

RSS订阅

Open Toolbar