zoukankan      html  css  js  c++  java
  • strcpy函数的C/C++实现

    2013-07-05 14:07:49

    本函数给出了几种strcpy与strncpy的实现,有ugly implementation,也有good implementation。并参考标准库中的implementation,最后给出了比较好的implementation。

    字符串复制,一个一个字符进行判断,直到最后一个结束符。

    问题:

    *与++的优先级问题:

    根据《C缺陷与C陷阱》上的说法,两者是同一个优先级,结合性是从右向左。但*p++的含义却是先得到*p的值,之后再对指针p加1,具体实例见文章:http://www.cnblogs.com/youngforever/p/3171283.html

    因此,

    while ( (*dst = *src) != '')

    dst++;  

    *src++;

    可简写为:

    while ( (*dst = *src) != '') ;

    又因为''的ASCII值就是0,因此while ( (*dst++ = *src++) != '') ;  可简写为while ( *dst++ = *src++ ) ;

     并注意到结束时字符串结束符''已经复制,因为是先复制再判断的。

    小结:

    标准库函数并没有输入合法性检查,这将输入合法性检查的任务推给了函数的调用者。
    对于strcpy函数,好的implementation要考虑一下几点:

      1. 函数src参数应为const,dst参数为非const;
      2. 函数要返回dst的地址,以方便嵌套使用该函数;
      3. 函数返回的dst的地址不要为const类型;
      4. 确定dst要有字符串结束符;
      5. 注意输入合法性检查注意输入合法性检查。

    对于strncpy函数,除了以上几点外,好的implementation还要考虑一下几点:

    当source的长度小于count时,应该怎么办?标准库函数的做法是,对dst大于source长度、小于count的部分赋值为;但在当source的长度大于count时。赋值到dst中的字符串是没有结束符的,在下面的运行结果中_strncpy_2的测试部分可以看到;这是因为代码中只这样写的:

    1 while (count && (*dest++ = *source++))    /* copy string */
    2         count--;
    3 
    4     if (count)                              /* pad out with zeroes */
    5         while (--count)
    6             *dest++ = '';  

    这样在当source的长度大于或等于count时,就不会执行下面的if语句,而上面的while条件判断由于是先判断count的值,后复制的,因此,在count减为0时,刚好复制完最后一个有效字符,即 的前一个字符,而没有复制.

    如果要想使得source的长度大于count时,复制到dst中的字符串也有结束符,_strncpy_3函数可以做到这一点;

    注意若while中的换为(*dest++ = *source++) && count,结果就会不同,即:

    1 while ( (*dest++ = *source++) && count )
    2         count--;   

    这样写,就会在source长度大于count时,多复制一个字符,因为count为0时,*source不是,仍会惊醒复制曹组,之后才会判断count的值。


    代码:

      1 #include <iostream>
      2 
      3 using namespace std;
      4 #define SIZE 100
      5 
      6 
      7 /***
      8 *char *strcpy(dst, src) - copy one string over another
      9 *
     10 *Purpose:
     11 *       Copies the string src into the spot specified by
     12 *       dest; assumes enough room.
     13 *
     14 *Entry:
     15 *       char * dst - string over which "src" is to be copied
     16 *       const char * src - string to be copied over "dst"
     17 *
     18 *Exit:
     19 *       The address of "dst"
     20 *
     21 *Exceptions:
     22 *******************************************************************************/
     23 
     24 const char * _strcpy_1(char *dst,const char *src)
     25 {
     26     if (NULL == src || NULL == dst)
     27     {
     28         return NULL;
     29     }
     30     char *dst_ret = dst;
     31     //const char *dst_ret = dst;   
     32     while ( (*dst++ = *src++) != '') ;   //*的优先级高于++,结束时''已经复制
     33     return dst_ret;
     34 }
     35 
     36 char * _strcpy_2(char *dst,const char *src)
     37 {
     38     if (NULL == src || NULL == dst)
     39     {
     40         return NULL;
     41     }
     42     char *dst_ret = dst;
     43     //const char *dst_ret = dst;      //返回值不需要是const类型的
     44     while ( (*dst++ = *src++) != '') ;   //*的优先级高于++
     45     return dst_ret;
     46 }
     47 
     48 //标准库函数给出的implementation,没有输入合法性检查
     49 char * _strcpy_3(char *dst,const char *src)
     50 {
     51     char *cp = dst;
     52 
     53     while ( *cp++ = *src++ )
     54         ;        /* Copy src over dst */
     55 
     56     return ( dst );
     57 }
     58 
     59 //标准库函数给出的implementation,加上输入合法性检查
     60 //好的implementation要考虑一下几点:
     61 //1)函数src参数应为const,dst参数为非const
     62 //2)注意输入合法性检查
     63 char * _strcpy_4(char *dst,const char *src)
     64 {
     65     if (NULL == src || NULL == dst)
     66     {
     67         return NULL;
     68     }
     69 
     70     char *cp = dst;
     71 
     72     while ( *cp++ = *src++ )
     73         ;        /* Copy src over dst */
     74 
     75     return ( dst );
     76 }
     77 
     78 /***
     79 *char *strncpy(dest, source, count) - copy at most n characters
     80 *
     81 *Purpose:
     82 *       Copies count characters from the source string to the
     83 *       destination.  If count is less than the length of source,
     84 *       NO NULL CHARACTER is put onto the end of the copied string.
     85 *       If count is greater than the length of sources, dest is padded
     86 *       with null characters to length count.
     87 *
     88 *
     89 *Entry:
     90 *       char *dest - pointer to destination
     91 *       char *source - source string for copy
     92 *       unsigned count - max number of characters to copy
     93 *
     94 *Exit:
     95 *       returns dest
     96 *
     97 *Exceptions:
     98 *
     99 *******************************************************************************/
    100 
    101 //不好的implementation
    102 //因为参数count为int,且在src的长度小于count时,dst后面的没有处理
    103 char * _strncpy_1(char *dst,const char *src,int count)
    104 {
    105     if (NULL == src || NULL == dst)
    106     {
    107         return NULL;
    108     }
    109     char *cp = dst;
    110     int current_count = 0;
    111     //while ( (*cp++ = *src++) != '' && current_count != count) 
    112     //    ++current_count;
    113 
    114     //*(cp - 1) = ''; //结束符
    115 
    116     while ( current_count != count && (*cp++ = *src++) != '') 
    117         ++current_count;
    118 
    119     *cp = ''; //结束符
    120 
    121     return ( dst );
    122 }
    123 
    124 //标准库函数的implementation
    125 char *  _strncpy_2 (
    126     char * dest,
    127     const char * source,
    128     size_t count
    129     )
    130 {
    131     char *start = dest;
    132 
    133     while (count && (*dest++ = *source++))    /* copy string */
    134         count--;
    135 
    136     if (count)                              /* pad out with zeroes */
    137         while (--count)
    138             *dest++ = '';   //在sorce的长度小于count时,后面不补'',只是将source的前面count个字符覆盖,后面的不变
    139 
    140     return(start);
    141 }
    142 
    143 //标准库函数的implementation,加上输入合法性检查
    144 //好的implementation要考虑一下几点:
    145 //1)输入source为const,dest为非const,count为size_t类型
    146 //2)在sorce的长度小于count时,后面补''
    147 //3)在sorce的长度大于count时,同样有结束符''
    148 char *  _strncpy_3 (
    149     char * dest,
    150     const char * source,
    151     size_t count
    152     )
    153 {
    154     if (NULL == source || NULL == dest)
    155     {
    156         return NULL;
    157     }
    158 
    159     char *start = dest;
    160 
    161     while (count && (*dest++ = *source++))    /* copy string */
    162         count--;     //若while中的换为(*dest++ = *source++) && count,结果就会不同
    163 
    164     //*(dest - 1) = '';  //结束符
    165     *dest = '';  //在sorce的长度小于count时,后面补''
    166 
    167     if (count)                              /* pad out with zeroes */
    168         while (--count)
    169             *dest++ = '';
    170 
    171     return(start);
    172 }
    173 
    174 
    175 //测试程序
    176 int main()
    177 {
    178     //_strcpy
    179     char src_1[SIZE] = "hello world!";
    180     char dst[SIZE] = "";
    181 
    182     cout<<"test _strcpy_1..."<<endl;
    183     cout<<"the src string is : "<<src_1<<endl;
    184     _strcpy_1(dst,src_1);
    185     cout<<"the dst string is : "<<dst<<endl;
    186 
    187     char src_2[SIZE] = "hello!";
    188     cout<<"test _strcpy_2..."<<endl;
    189     cout<<"the src string is : "<<src_2<<endl;
    190     _strcpy_2(dst,src_2);
    191     cout<<"the dst string is : "<<dst<<endl;
    192 
    193     char src_3[SIZE] = "happy birthday!";
    194     cout<<"test _strcpy_3..."<<endl;
    195     cout<<"the src string is : "<<src_3<<endl;
    196     _strcpy_3(dst,src_3);
    197     cout<<"the dst string is : "<<dst<<endl;
    198 
    199     char *src_null = NULL;  //不能这样赋值,报错:cannot convert from 'int' to 'char [100]'
    200     //cout<<"test _strcpy_3(src == NULL )..."<<endl;
    201     ////cout<<"the src string is : "<<src_3<<endl;
    202     //_strcpy_3(dst,src_null);
    203     //cout<<"the dst string is : "<<dst<<endl;
    204 
    205     char src_4[SIZE] = "happy!";
    206     cout<<"test _strcpy_4..."<<endl;
    207     cout<<"the src string is : "<<src_4<<endl;
    208     _strcpy_4(dst,src_4);
    209     cout<<"the dst string is : "<<dst<<endl;
    210 
    211     cout<<"test _strcpy_4(src == NULL )..."<<endl;
    212     _strcpy_4(dst,src_null);
    213     cout<<"the dst string is : "<<dst<<endl;
    214 
    215     //_strncpy
    216     char dst_2[SIZE] = "";
    217     size_t count = 4;
    218     cout<<"test _strncpy_1..."<<endl;
    219     cout<<"the src string is : "<<src_1<<endl;
    220     cout<<"the number to copy is : "<<count<<endl;
    221     _strncpy_1(dst_2,src_1,count);
    222     cout<<"the dst_2 string is : "<<dst_2<<endl;
    223 
    224     count = 20;
    225     cout<<"test _strncpy_1..."<<endl;
    226     cout<<"the src string is : "<<src_1<<endl;
    227     cout<<"the number to copy is : "<<count<<endl;
    228     _strncpy_1(dst_2,src_1,count);
    229     cout<<"the dst_2 string is : "<<dst_2<<endl;
    230 
    231     count = 4;
    232     cout<<"test _strncpy_2..."<<endl;
    233     cout<<"the src string is : "<<src_1<<endl;
    234     cout<<"the number to copy is : "<<count<<endl;
    235     _strncpy_2(dst_2,src_1,count);
    236     cout<<"the dst_2 string is : "<<dst_2<<endl;
    237 
    238     count = 20;
    239     cout<<"test _strncpy_2..."<<endl;
    240     cout<<"the src string is : "<<src_1<<endl;
    241     cout<<"the number to copy is : "<<count<<endl;
    242     _strncpy_2(dst_2,src_1,count);
    243     cout<<"the dst_2 string is : "<<dst_2<<endl;
    244 
    245     count = 4;
    246     cout<<"test _strncpy_3..."<<endl;
    247     cout<<"the src string is : "<<src_1<<endl;
    248     cout<<"the number to copy is : "<<count<<endl;
    249     _strncpy_3(dst_2,src_1,count);
    250     cout<<"the dst_2 string is : "<<dst_2<<endl;
    251 
    252     count = 20;
    253     cout<<"test _strncpy_3..."<<endl;
    254     cout<<"the src string is : "<<src_1<<endl;
    255     cout<<"the number to copy is : "<<count<<endl;
    256     _strncpy_3(dst_2,src_1,count);
    257     cout<<"the dst_2 string is : "<<dst_2<<endl;
    258 
    259     return 0;
    260 }

    运行结果(分别测试count大于、以及小于source长度的情形):

     1 test _strcpy_1...
     2 the src string is : hello world!
     3 the dst string is : hello world!
     4 test _strcpy_2...
     5 the src string is : hello!
     6 the dst string is : hello!
     7 test _strcpy_3...
     8 the src string is : happy birthday!
     9 the dst string is : happy birthday!
    10 test _strcpy_4...
    11 the src string is : happy!
    12 the dst string is : happy!
    13 test _strcpy_4(src == NULL )...
    14 the dst string is : happy!
    15 test _strncpy_1...
    16 the src string is : hello world!
    17 the number to copy is : 4
    18 the dst_2 string is : hell
    19 test _strncpy_1...
    20 the src string is : hello world!
    21 the number to copy is : 20
    22 the dst_2 string is : hello world!
    23 test _strncpy_2...
    24 the src string is : hello world!
    25 the number to copy is : 4
    26 the dst_2 string is : hello world!
    27 test _strncpy_2...
    28 the src string is : hello world!
    29 the number to copy is : 20
    30 the dst_2 string is : hello world!
    31 test _strncpy_3...
    32 the src string is : hello world!
    33 the number to copy is : 4
    34 the dst_2 string is : hell
    35 test _strncpy_3...
    36 the src string is : hello world!
    37 the number to copy is : 20
    38 the dst_2 string is : hello world!
    39 请按任意键继续. . .

    从运行结果可以看出,

  • 相关阅读:
    尚硅谷前端2020Web前端学习记录
    阿里网盘阿里云网盘内测资格获取,阿里网盘开通
    冰眼冷链物流监控平台-2020微服务项目实战
    探花交友智能推荐社交项目-2020Java大数据实战
    互联网Java工程师面试突击三季
    恋上数据结构与算法(一、二、三季)
    布客&#183;ApacheCN 编程/后端/大数据/人工智能学习资源 2020.9
    NumPy 基础知识·翻译完成
    NumPy 初学者指南中文第三版·翻译完成
    NumPy 秘籍中文第二版·翻译完成
  • 原文地址:https://www.cnblogs.com/youngforever/p/3173677.html
Copyright © 2011-2022 走看看