C语言中字符串的复制与memcpy函数
2016-02-27 20:40
357 查看
今天在线做一道360实习生笔试题, 发现大多数题还是比较基础的, 但都需要仔细斟酌. 不过我已被虐得面目全非, 操作系统和计算机网络相关的很多知识都不会, 还得努力学习. 不过说重点, 面试题有两个编程题, 第一个是实现hashmap, 第二题是一个字符串的处理, 我主要说说第二题, 题目描述如下:
在做这个题的时候还剩下不到10分钟, 慌忙中将题目看复杂了,我想成会有www.abc.efg.com这样的情况了, 于是惯性思维促使我使用c++将域名按”.”分段, 然后逆序输出, 写的也烂, 也不是效率最高的, 提交后再看题目发现域名是只有www和域名本体和com三个部分, 当然后面的的com可能是其他的后缀,比如io或者info之类的, 发现直接是memcpy()复制内存片段效率应该会更高, 即首先复制后缀, 然后复制域名本体, 然后再复制www到字符串缓冲区,然后输出就是结果了,于是用c实现了这个方法:
输出结果如下:
关于c语言中字符串的复制, 通常可以使用strcpy()来实现, 当然也可手动写个循环, 但是复制效率是最低的, 无论是从人的角度还是计算机的角度来说, 第三个就是直接使用memcpy(), 直接将复制目标内存片段到指定位置, 并且复制速度是最快的, 但是strcpy()与memcpy()在用来复制字符串的时候有一个小小的区别就是无论如何strcpy()从字符串的开始只复制到第一个”\0”的位置, 但是由于memcpy()是整个内存片段,所以”\0”也不会被忽略, 虽然最后复制内容输入到屏幕显示的结果是一样的, 我们用个小程序演示一下这个区别:
输出结果如下:
从结果可以看出,使用strcpy()仅仅复制到了”\0”, 因为输出b的后半部分结果是未定义的,说明并没有复制过来, 但是输出c的后半部分是, 输出了事先定义的结果
同样, 利用memcpy()函数的特性, 我们可以做一个泛型的交换函数:
输出:
实现域名的字段顺序翻转函数,比如输入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
相关文章推荐
- 算法代码实现之冒泡排序,C/C++ 实现
- 逆波兰法求解数学表达示(C++)
- C++计算器项目的初始部分
- C++计算器项目的初始部分
- ACJoy A Presents
- c++模板类中的友元函数
- usaco 第一章博客指引
- 【NOI 2014】【BZOJ 3670】动物园 题解&代码(C++)
- C语言实现双向非循环链表
- C语言创建并使用dll
- 初学C++的宏观问题——对象的演化
- C++学习笔记:纯虚函数和抽象类
- C语言学习笔记8-函数
- C++变量命名规则
- C++ 继承、友元、权限
- C语言中的类型转换
- C语言创建并使用lib
- c语言编写通讯录
- C++学习笔记49——继承中的复制构造函数与赋值操作符
- 图的深度优先搜索/Depth-first search/C++