zoukankan      html  css  js  c++  java
  • C语言常用库函数实现

    myself test:

    strcpy() {} strcmp() {} strlen() {} memcpy() {} memmove() {} memset() {} atoi() {} itoa() {}

    <--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->

    1.strcpy

    char * strcpy(char *dst,const char *src)   
    {
        if((dst==NULL)||(src==NULL))
             
               return NULL; 
     
        char *ret = dst; //[1]
     
        while ((*dst++=*src++)!=''); //[2]
     
        return ret;//[3]
    }

    细节是:

    (1)判断地址是否为空;

    (2)参数只有两个地址,没有拷贝的长度。拷贝到'‘时就会终止,要保证最终dst末尾是'';

    (3)要保证目标字串的长度足够,能够容纳原串的长度;

    (4)因为拷贝是dst会移动,而最终要返回的是拷贝后字符串的起始地址,因此要先保存dst的地址,便于最终返回。

     

    Tips: while(*src != '') *dst++ = *src++;

    is wrong !!!     没有考虑给dst复制结束符!!!

     

     

    2.strcmp

    int strcmp(const char *str1, const char *str2)
    {
       int ret=0;
       while( !(ret = *(unsigned char*)str1 - *(unsigned char*)str2 ) && *str1 )    //红色为了当str1==str2的时候,已经判断到了字符串末尾,跳出循环
       {
          str1++;
          str2++;
       }
       if(ret < 0)
           return -1;
       else if(ret > 0) 
           return 1;
       return 0;    

    3.strlen

    size_t __cdecl strlen (            //源自标准库
            const char * str
            )
    {
    //个人觉得应该要对str == NULL 处理, 但并不可以返回0, 应该设置一个全局变量, 当为NULL将其置位
    const char *eos = str; while( *eos++ ) ; return( eos - str - 1 ); //为什么要-1? 因为当eos为''后仍又++ }

    4.memcpy

    void * __cdecl memcpy ( void * dst,const void * src,size_t count)
    {
             void * ret = dst;
             while (count--)
             { // 注意, memcpy函数没有处理dst和src区域是否重叠的问题
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
             }
             return(ret);
    }

    细节:

    1)src和dst所指内存区域不能重叠,函数返回指向dst的指针。如果src和dst以任何形式出现了重叠,它的结果是未定义的

    2)与strcpy相比,memcpy遇到’’不结束,而且一定会复制完n个字节。只要保证src开始有n字节的有效数据,dest开始有n字节内存空间就行。

    3)如果目标数组本身已有数据,执行memcpy之后,将覆盖原有数据(最多覆盖n个)。

         如果要追加数据,则每次执行memcpy()后,要将目标地址增加到要追加数据的地址。

    4)source和destin都不一定是数组,任意的可读写的空间均可。

    5.memmov

    void * __cdecl memmove ( void * dst,const void * src,size_t count)
    {
             void * ret = dst;
             if (dst <= src || (char *)dst >= ((char *)src + count))
             {
                       // 若dst和src区域没有重叠,则从起始处开始逐一拷贝
                       while (count--)
                       {
                                *(char *)dst = *(char *)src;
                                dst = (char *)dst + 1;
                                src = (char *)src + 1;
                       }
             }
             else
             { // 若dst和src 区域交叉,则从尾部开始向起始位置拷贝,这样可以避免数据冲突
                       dst = (char *)dst + count - 1;
                       src = (char *)src + count - 1;
                       while (count--)
                       {
                                *(char *)dst = *(char *)src;
                                dst = (char *)dst - 1;
                                src = (char *)src - 1;
                       }
             }
             return(ret);
    }

    Q:memcpy与memmove的区别?

    A:当src和dst区域没有重叠时,两个函数是完全一样的。木有重叠的条件是: dst <= src || (char *)dst >= ((char *)src + count 。否则,memcpy是不能正常工作的,memmove是可以正常工作的。

    6.memset

    void* memset(void* dst,int val, size_t count)
    {
        void* ret = dst;
        while(count--)
        {
            *(char*)dst = (char)val;
            dst = (char*)dst + 1; //移动一个字节
        }
        return ret;
    }

    7.atoi && itoa

    isspace(int x)  
    {  
        if(x==' ' || x=='/t' || x=='/n' || x=='/f' || x=='/b' || x=='/r')  
            return 1;  
        else   
            return 0;  
    }  
      
    isdigit(int x)  
    {  
        if(x<='9' && x>='0')           
            return 1;   
        else   
            return 0;  
    }  
      
    int atoi(const char *nptr)  
    {  
            int c;              /* current char */  
            int total;         /* current total */  
            int sign;           /* if '-', then negative, otherwise positive */  
      
      
            /* skip whitespace */  
            while ( isspace((int)(unsigned char)*nptr) )  
                ++nptr;  
      
      
            c = (int)(unsigned char)*nptr++;  
            sign = c;           /* save sign indication */  
            if (c == '-' || c == '+')  
                c = (int)(unsigned char)*nptr++;    /* skip sign */  
      
      
            total = 0;  
            while (isdigit(c)) {  
                total = 10 * total + (c - '0');     /* accumulate digit */  
                c = (int)(unsigned char)*nptr++;    /* get next char */  
            }  
      
      
            if (sign == '-')  
                return -total;  
            else  
                return total;   /* return result, negated if necessary */  
    }  
    char* _itoa(int value, char* string, int radix)
    {
        char tmp[33];
        char* tp = tmp;
        int i;
        unsigned v;
        int sign;
        char* sp;
        if (radix > 36 || radix <= 1)
        {
            __set_errno(EDOM);
            return 0;
        }
        /*
        编程语言的基础类库一般最大到36,小于2的进制没有意义,如果给定的参数不满足这个范围,
        运行时会发出Debug Assertion Failed。对于最小的进制2,一个int,4个字节,32位,tmp
        开33的数组足够
        */
     
        sign = (radix == 10 && value < 0);
        if (sign)
            v = -value;
        else
            v = (unsigned)value;
        /*
        这里对radix进行分类,10进制与非10进制,如果是10进制,直根据负数还是正数进行转化就行,
        如果不是10进制,根据反码,补码的知识,把value转成unsigned类型
        */
     
        while (v || tp == tmp)
        {
            i = v % radix;
            v = v / radix;
            if (i < 10)
                *tp++ = i + '0';
            else
                *tp++ = i + 'a' - 10;
        }
        /*
        转化过程
        */
     
        if (string == 0)
            string = (char*)malloc((tp - tmp) + sign + 1);
        /*
        如果给定的指针不指向有效的内存区,根据所给参数申请足够的内存
        */
     
        sp = string;
        if (sign)
            *sp++ = '-';
        while (tp > tmp)
            *sp++ = *--tp;
        *sp = 0;
        return string;
    }
  • 相关阅读:
    替代PhotoShop:GIMP图形编辑器的使用
    Matlab: 主函数和子函数间接传递变量
    代码管理:SVN的使用
    Python: 科学计算
    Python: 代码调试
    Latex: article模板
    Matlab: 程序优化和调试
    LibreOffice的使用技巧
    mysql--多表联合查询
    mysql--数据查询
  • 原文地址:https://www.cnblogs.com/dzy521/p/9547681.html
Copyright © 2011-2022 走看看