strcpy和strncpy

在c语言中,对于简单变量,如int型、double型,直接使用赋值符号“=”,即可完成赋值,如

int a=10;

int b;

b=a;

即可完成用a给b赋值。

但是对于字符串,这样赋值是不准确的。

比如:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char src[10];
    
    printf("enter:\n");
    if( fgets(src,10,stdin))
    {
        //如果输入的有效字符少于9个,则说明src中存在'\n',这时去掉'\n'
        //如果输入的有效字符大于9个,则缓冲区中会残余字符,这时用getchar()函数吸收掉
        int i=0;
        while(src[i] !='\0'  && src[i] !='\n')
            i++;
        if(src[i]=='\n')
            src[i]='\0';
        else
            while(getchar() != '\n')
                continue;

    }
    char* dst;
    dst=src;
    printf("-----------------------------------\n");
    puts(dst);

    src[0]='z';
    printf("-----------------------------------\n");
    puts(dst);
    return 0;
}

我们发现当用赋值语句dst=src给dst赋值后,如果改变字符串src的值,dst的值也会随之改变,而对于简单变量则不会出现这种情况。

这时因为 dst=src,仅仅是地址之间的赋值。

要想对字符串进行赋值需要使用strcpy()函数,这个函数就相当于简单变量的赋值符号"=";

 

 

strcpy的函数原型:

char *strcpy(char* dest, const char *src);

作用:把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间。

这里需要注意的是:第一个参数应该指向一个数据对象(如数组),且该对象有足够的存储空间用于存储源字符串,第二个参数可以是指向数组的指针、数组名或者字符串常量

首先:dest应该是一片内存的首地址,不能是没有分配内存的指针

比如:

char* dst;
strcpy(dst,src);

这里dst没有分配内存空间,运行时会出错

 

再者:dest 所指向的内存空间一定要足够存储源字符串

比如:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char* src="中国人们解放军,中华人民共和国,中央人民政府,中共中央,***,呵呵哒";
    

    char dst[2];
    strcpy(dst,src);
    printf("-----------------------------------\n");
    puts(dst);
    return 0;
}

结果为:

 

 可以看到:虽然能够完整输出,但是程序会异常中断。其实有可能也会正常输出,但这种正常是不可靠的,因为很显然dst的大小为2,而源字符串的长度要大于2,这必然造成程序访问未知的内存空间,给程序带来不确定性

 

strncpy 相对于strcpy函数多了一个表示可拷贝的最大字符数的参数。这样在很大程度上就能避免strcpy函数的不足(程序员在用strncpy时,需要填写拷贝个数,这时程序员就很肯能会检查一下dest是否有足够的内存)。

原型:char *strncpy(char *dest, const char *src, int n);

要注意:n表示可拷贝的最大字符数,如果提前遇到'\0',拷贝的长度会小于n.

另外,如果仅拷贝源字符串的一部分,可能会造成目标串没有字符串结束标志'\0';

比如:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char* src="abcdefghijklmnopq";
    

    char dst[4];
    strncpy(dst,src,4);
    printf("-----------------------------------\n");
    puts(dst);
    return 0;
}

 

 

输出结果为:

可以看到有乱码输出,这就是因为拷贝的只是源字符串的一部分,abcd ,这其中并没有字符串结束标志'\0';因此dst中也就没有字符串结束标志'\0',所以会输出乱码,。

为解决这一问题可以做如下修改:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char* src="abcdefghijklmnopq";
    

    char dst[4];
    strncpy(dst,src,4-1);
    dst[4-1]='\0';
    printf("-----------------------------------\n");
    puts(dst);
    return 0;
}

拷贝n-1个字符,最后在字符串结尾手动添加'\0'结束标志,这样做比较安全。

 

posted @ 2016-10-17 14:11  青儿哥哥  阅读(3702)  评论(0编辑  收藏  举报