您的位置:首页 > 编程语言 > C语言/C++

C语言中字符串的复制与memcpy函数

2016-02-27 20:40 357 查看
今天在线做一道360实习生笔试题, 发现大多数题还是比较基础的, 但都需要仔细斟酌. 不过我已被虐得面目全非, 操作系统和计算机网络相关的很多知识都不会, 还得努力学习. 不过说重点, 面试题有两个编程题, 第一个是实现hashmap, 第二题是一个字符串的处理, 我主要说说第二题, 题目描述如下:

实现域名的字段顺序翻转函数,比如输入www.so.com, 输出为com.so.www, 要求实现的效率尽可能的优化


在做这个题的时候还剩下不到10分钟, 慌忙中将题目看复杂了,我想成会有www.abc.efg.com这样的情况了, 于是惯性思维促使我使用c++将域名按”.”分段, 然后逆序输出, 写的也烂, 也不是效率最高的, 提交后再看题目发现域名是只有www和域名本体和com三个部分, 当然后面的的com可能是其他的后缀,比如io或者info之类的, 发现直接是memcpy()复制内存片段效率应该会更高, 即首先复制后缀, 然后复制域名本体, 然后再复制www到字符串缓冲区,然后输出就是结果了,于是用c实现了这个方法:

#include <stdio.h>
#include <string.h>
void trans(char *res, char *a)
{
strcat(a, "."); //在域名默认加上".", 因为"com", 移动到最前面后后面需要一个"."
const char *src = a; //复制一个常量副本, 因为memcpy()函数的参数中要求常量
int len = strlen(src) - 1;
int i = len;
while(src[--i] != '.'); //找到后开始的下标

memcpy(res, src + i + 1, (len - i) * sizeof(char)); //复制后缀到res字符串缓冲区的起点
memcpy(res + (len - i), src + 4, (i - 3) * sizeof(char)); //将域名内容复制到res缓冲区的末尾
memcpy(res + (len + 1 - 4), src, 3 * sizeof(char)); //继续将"www"复制到res末尾
res[len] = '\0'; //设置字符串结束标志
}

int main()
{
char a[100], res[100];
scanf("%s", a);
trans(res, a);
puts(res);
return 0;
}


输出结果如下:

www.baidu.com
com.baidu.www


关于c语言中字符串的复制, 通常可以使用strcpy()来实现, 当然也可手动写个循环, 但是复制效率是最低的, 无论是从人的角度还是计算机的角度来说, 第三个就是直接使用memcpy(), 直接将复制目标内存片段到指定位置, 并且复制速度是最快的, 但是strcpy()与memcpy()在用来复制字符串的时候有一个小小的区别就是无论如何strcpy()从字符串的开始只复制到第一个”\0”的位置, 但是由于memcpy()是整个内存片段,所以”\0”也不会被忽略, 虽然最后复制内容输入到屏幕显示的结果是一样的, 我们用个小程序演示一下这个区别:

#include <stdio.h>
#include <string.h>

int main()
{
char a[20] = "asdf\0uiop";
char b[20];
char c[20];

strcpy(b, a);
puts(b);
printf("%d\n", strlen(a));
for (int i = 5; i < 9; i++)
printf("%c", b[i]);
printf("\n");

puts("-----------------------");
memcpy(c, a, 9 * sizeof(char));
puts(c);
printf("%d\n", strlen(c));
for (int i = 5; i < 9; i++)
printf("%c", c[i]);
printf("\n");
return 0;
}


输出结果如下:

asdf
4
S

-----------------------
asdf
4
uiop
请按任意键继续. . .


从结果可以看出,使用strcpy()仅仅复制到了”\0”, 因为输出b的后半部分结果是未定义的,说明并没有复制过来, 但是输出c的后半部分是, 输出了事先定义的结果

同样, 利用memcpy()函数的特性, 我们可以做一个泛型的交换函数:

#include <stdio.h>
#include <string.h>

//因为交换的数据类型是未知的, 所以添加一个额外的参数告诉函数复制多长内存片段
void swap(void *a, void *b, int size)
{
char buffer[size];
memcpy(buffer, a, size);
memcpy(a, b, size);
memcpy(b, buffer, size);
}

int main()
{
char a = 'a', b = 'b';
swap(&a, &b, sizeof(char));
printf("a = %c b = %c\n", a , b);

int x = 11, y = 99;
swap(&x, &y, sizeof(int));
printf("x = %d y = %d\n", x , y);
return 0;
}


输出:

a = b b = a
x = 99 y = 11
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: