数据拷贝整理

背景:

数据拷贝和转换上的整理。

char数组之间拷贝

strcpy

原型:char *strcpy(char *dest, char *src);
功能:把src所指由‘\0’结束的字符串复制到dest所指的数组中。
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
注意:当src串长度>dest串长度时,程序仍会将整个src串复制到dest区域,可是dest数组已发生溢出。
因此会导致dest栈空间溢出以致产生崩溃异常。如果不考虑src串的完整性,可以把dest数组最后一元素置为NULL,从dest串长度处插入NULL截取字串。
strcpy函数是不进行越界处理的. 又因为strcpy连null一起复制,例如下述代码,是可以正常输出结果的:

char p[5]; 
char* s="12345"; 
strcpy(p,s);
cout << p << endl;

曾经认为:作为字符串字面值的”12345”会在结尾处自动加上空字符null,从而长度是6,上面的strcpy是会越界的,从而是个越界错误。而现实却是可以正常运行。。。

strncpy:字串复制

原型:char * strncpy(char*dest, char *src, size_t n);
功能:将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到NULL才停止复制,而是等凑够n个字符才开始复制),返回指向dest的指针。
说明:
  如果n > dest串长度,dest栈空间溢出产生崩溃异常。
  否则:
  1)src串长度<=dest串长度,(这里的串长度包含串尾NULL字符)
网上有资料显示,如果n=(0, src串长度),src的前n个字符复制到dest中。但是由于没有NULL字符,所以直接访问dest串会发生栈溢出的异常情况。但是在测试过程中,并未发现。测试代码(都是使用char型)如下:

char s3[10]={"ABCDEFG"};//dest串
std::cout<<"size:"<<sizeof(s3)<<",strlen测量结果:"<<strlen(s3)<<std::endl;
char s33[5]={'a','b','3','4'};//src串
strncpy(s3,s33,3);
std::cout<<"size:"<<sizeof(s3)<<",strlen测量结果:"<<strlen(s3)<<std::endl;
printf("src和dest都是char的时候,n为dest,且长度dest>src,copy之后的src:%s\n",s3);

运行结果如下:

size:10,strlen测量结果:7
size:10,strlen测量结果:7
src和dest都是char的时候,n为dest,且长度dest>src,copy之后的src:ab3DEFG

所以,不清楚上述case产生的情景,string类型同样无错误,难道是指针或者指针数组?欢迎大家指出,并补充。

  如果n = src串长度,与strcpy一致。
  如果n = dest串长度,[0,src串长度]处存放src字串,(src串长度, dest串长度]处存放NULL。
  2)src串长度>dest串长度
  如果n =dest串长度,则dest串没有NULL字符,会导致输出会有乱码。如果不考虑src串复制完整性,可以将dest最后一字符置为NULL。
  综上,一般情况下,使用strncpy时,建议将n置为dest串长度(除非你将多个src串都复制到dest数组,并且从dest尾部反向操作),复制完毕后,为保险起见,将dest串最后一字符置NULL,避免发生在第2)种情况下的输出乱码问题。
例子代码:

    char s3[5]={'A','B','C','D','E'};
    char s33[12]={'a','b','3','4','5','6','7','8','9','A'};
    strncpy(s3,s33,strlen(s33));
    printf("src和dest都是char的时候,n为dest,且长度dest>src,copy之后的src:%s\n",s3);//会根据dest的长度,对src数组进行自动扩充

运行结果如下:

src和dest都是char的时候,n为dest,且长度dest>src,copy之后的src:ab3456789A@

从上述结果可以看出,出现一个乱码@。
对比下述代码:

    char s3[5]={'A','B','C','D','E'};
    char s33[12]={'a','b','3','4','5','6','7','8','9','A'};
    strncpy(s3,s33,strlen(s33)+1);//注意这里的区别
    printf("src和dest都是char的时候,n为dest,且长度dest>src,copy之后的src:%s\n",s3);//会根据dest的长度,对src数组进行自动扩充

运行结果如下:

src和dest都是char的时候,n为dest,且长度dest>src,copy之后的src:ab3456789A

由于拷贝的时候,比之前多了一个字符,也就是说在拷贝过程中将src中的结束符一起拷贝。
  当然喽,无论是strcpy还是strncpy,保证src串长度

#include<iostream>
#include<string>
#include<stdio.h>
#include<string.h>
int main()
{
    char s[6] = "hello";
    char s1[] = {'a','b','c','0','d','e'};
    char s2[] = {'A','B','\0','C','D','D'};
    //strncpy(s, "DABCDE!",4);
    strncpy(s1, s2, 4);//遇到\0,拷贝中断
    //printf("%c\n",s1);//整理成unsigned char打印出来
    printf("%s\n",s);
    printf("%s\n",s1);
    std::cout<<"输出s2:"<<s2<<std::endl;
    std::string tt="ABCDEFGHILMN";
    //strncpy(s,tt.c_str(),strlen(s));
    //printf("%s\n",s);
    std::cout<<"dest的尺寸:"<<strlen(s)<<",src的尺寸:"<<tt.size()<<std::endl;
    strncpy(s,tt.c_str(),tt.size());
    printf("拷贝之后%s\n",s);
    char s3[10]={'A','B','C','D','E','F'};
    char s33[12]={'1','2','3','4','5','6','7','8','9','A'};
    char *s3_3="1234567890ABCDEF";
    strncpy(s3,s33,strlen(s33));
    printf("s3:%s\n",s3);
    //strncpy(s3,s3_3,strlen(s3_3));
    //printf("s3_3:%s\n",s3);
    return 0;
}

上述两个函数也可以实现从cha* 拷贝到char数组。从char数组拷贝到char 和char 之间拷贝其实是相同的,都是可以直接赋值,因为char数组的操作其实也是通过首地址。通过直接改变指针的指向实现。如

char *p="acbcdefghlmn";
char *stt="12345678";
p = stt;//这里是不能够用上述的srtncpy的,会直接core dump的,因为const是不允许修改的。
std::cout<<p<<std::endl;

string 转为char 数组,以及互转

string转为char数组

需要用到strncpy,而string转char *需要先建立一个char数组,对其进行指向,再采用strcncpy的方式转为char指针型。

char数组转为string

初始化方式的拷贝,只能在定义string对象之后,立即初始化的时候用。在不是初始化的地方是不能够这样拷贝的,需要用assign().

char szResp[33];
memset(szResp,'0', sizeof(szResp));
szResp[32]='\0';
std::string StandardHash(szResp);//如果写成std::string StandardHashStandardHash(szResp);是不行的,编译时就报错。
std::cout<<StandardHash.size()<<std::endl;
std::cout<<StandardHash<<std::endl;

assign方式:

char p1[]="12345678";
std::string p;
p.assign(p1,strlen(p1));
std::cout<<p<<std::endl;

string 转为char *,以及互转

string转char*上述已经阐述,此处直接给个例子。

string s = "abc";
char* c;
const int len = s.length();
c = new char[len+1];
strcpy(c,s.c_str());

char*转string和char数组转string其实是一样的,直接采用初始化的方式即可。

string转int,int转string

方法1:
int sprintf( char *buffer, const char *format [, argument] … );
例如:

      int ss;
      char temp[64];
      string str;
      ss = 1000;
      sprintf(temp, "%d", ss);
      string s(temp);
       //调用string的方法
      cout<<s.c_str()<<endl;//1000
      cout<<s.size()<<endl;  //长度为4

方法2:
char *_itoa( int value, char *string, int radix );
需要的头文件

      char buffer[20];
      int  i = 3445;   
      _itoa( i, buffer, 10 );//注意linux中没有该函数
      string s(buffer);

方法3:
stringstream( )
需要头文件

     int hello=4;
     std::stringstream ss;
     ss<<hello;
     std::string   s=ss.str();
     //调用string的方法
     cout<<s.c_str()<<endl;

其他部分,待续!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值