首页 百科知识 关于字符串的拷贝_C语言入门

关于字符串的拷贝_C语言入门

时间:2021-09-15 百科知识 联系我们

关于字符串的拷贝_C语言入门

下面我就把我们还没修改过的代码再贴出来吧,也顺便加深大家的印象:

---------------------------

char* copy(char* dest, const char* src)
{
       if((dest = NULL) && (src = NULL))
       {
             printf("无效参数。");
             return NULL;
       }
       char* get = dest;
       memcopy(dest,src,strlen(src)+1);
       return get;

}

 

char* memcopy(char* dest,const char* src,unsigned int len)
{
        if((dest =NULL) &&(src = NULL))
        {
             printf("无效参数。");
             return NULL;
         }
         char* get = dest;
         if((get+len) <= src || get > (src+len))
         {
               while(len--)
               {
                    *get = *src;
                     get++;
                     src++; 
                 }
         }
         else
         {
                 get = get + len -1;
                 src = src + len - 1;
                 while(len--)
                 {
                        *get = *src;
                         get--;
                         src--;
                  }
        }
       return dest;
}

------------------------------------------------

        这是我们昨天的程序,因为昨天没时间验证,今天验证下来运行时崩溃,大家现在应该看出问题出现在那里了吧,就是用黑体表示的那两句里面,说到这里,不得不说,编程真的不要细心啊,这个错误我已经连犯两次,有一次是在做一个上传下载文件的客户端和服务器上,在connect套接字的时候就是这样错将“=”当“==”使,所以导致一直无法连接服务器。那么为什么我们上面的这个会报错呢?因为我们重新初始化了指针,所以导致运行时出现无效内存。

       还有,这里的逻辑判断也不对,我们的原意是要检查参数的有效性,如果有一个为空就直接返回退出,这样的话用&&就极不适合了,为什么会出现这个判断符呢?因为当时没考虑,就直接从下面把他复制上去的。虽然我们一般不会传无效数组指针进去,不会碰到无效退出的情况,但是什么时候自己传了个无效的指针进去不是糟糕了吗?所以上面的黑体语句应该修改为如下:

      if((dest == NULL) || (src == NULL))

       再调试的话发现完全没问题了,就算有重叠内存的拷贝也不会崩溃了。下面我们来看看内存拷贝是怎么实现的。

       首先,我们先要判断有没有重叠内存的可能,这个该怎么判断呢?还记得我吗上一讲的那个恒等式吗?

     array[i] == *(ptr+i);

     &array[i] == ptr + i;

     通过这两个恒等式,我们可以轻易的判断出是否有内存重叠的情况:

     dest是要的目标地址dest就是我们所需要用到的一块内存的首地址,知道首地址,我们还知道那个len(这块内存的长度),所以我们可以轻松的得到这块内存的范围:[dest,dest+len],只要我们这块内存的最小值小于等于在我们源地址的首地址,或者在源地址的最大范围外就可以肯定他们没有重叠部分,就算有重叠部分,这样也不会印象到我们一般的从低到高的拷贝,如下:

      if(get<= src || get > (src+len))

     当满足该条件,我们就不用担心内存重叠的问题,直接从低字节向高字节依次拷贝即可,直到将源地址里面的信息拷贝给目标内存。

-------------------------------

      while(len--)

      { 

             *get =  *src;(www.guayunfan.com)

             get++;

             src++;

       }

----------------------------------

      这就是整个拷贝过程,当然,如果大家喜欢用数组操作的话,可以如下循环来完成复制过来:

--------------------------------

     for(int i=0;i<len;i++)

     {

              get[i] = src[i];

      }

-------------------------------

     注意一点,如果使用数组模式,不可以使用++或--,如果使用指针的话,可以这样操作。

      如果不满足上面的if条件,那么就说有内存重叠的地方,这时我们就要考虑另一种拷贝方法了,我们不能从低位向高位顺序拷贝,我们要从高位向低位进行拷贝,为什么呢?就用昨天我们举的例子吧:

        copy(array1+1,array1);

        从上面的原型我们可以看出,这是要把array1里面的信息拷贝到array1+1里面去,因为他们共用了一块内存:

     ——————

         ——————

      像上面的这两条线一样,array1的内存块是上面那一段,array1+1是下面这一段,第一个自己可以顺利复制进array1+1里面来,就简单点说,array1这块内存里面储存的是abc,那么a顺利复制到array1+1的首地址里,那么array1+1的首地址却是array1的第二个值储存地址,也就是b的地址,这一来,b便变成了a,于是array1的最终结果是aaaarray1+1的结果也是aaa,现在明白为什么要从高位到低位的拷贝了吧。

       关于这个字符串的拷贝函数就说到这里了,他到底算不算是系统string库里面的strcpy()的伪码我不知道,有空的同学可以多加验证,尤其是在效率方面,因为现在我们就差效率没有验证了,其他方面和strcpy()没有两样,甚至内存重叠拷贝的情况竟然比strcpy()的要好,我不知道这是好事还是坏事,我想微软不会没有考虑我所考虑的这些,至于效率,我也懒得去验证,留给大家去探索吧。

     

 

====================