这里是面试常见的字符串相关题目。
该文章主要将strcpy、memcpy、memmove三个。
1. strcpy
strcpy的返回值是目的字符串的地址,可以实现链式语法。
#include <stdio.h>
#include <string.h>
char *mystrcpy(char *dst, char *src)
{
char *res = dst;
if (!src || !dst) return dst;
while ((*(dst++) = *(src++)) != '\0');
return res;
}
int main()
{
char *a1 = (char*)malloc(5);
char a[] = "12345678";
char b[] = "1234111111111";
mystrcpy(a, b);
printf("%s\n", a); // 输出 1234111111111
mystrcpy(a1, b);
printf("%s\n", a1); // 输出 1234111111111
free(a1);
return 0;
}
另外,这里是因为字符串都是显式所以编译器能够特殊处理吗?居然没有出现内存溢出的问题。
2. memcpy
注意memcpy是直接赋值内存的内容的,所以返回值及输入都是void指针类型,需要制定赋值的数量。
#include <stdio.h>
#include <string.h>
#include <assert.h>
void *mymemcpy(void *dst, void *src, int count)
{
assert(dst != NULL && src != NULL);
char *tmp_src = (char *)src;
char *tmp_dst = (char *)dst;
while (count--) {
*(tmp_dst++) = *(tmp_src++);
}
return dst;
}
int main()
{
char a[] = "12345678";
char b[] = "qweer";
mymemcpy(b, a, 2);
printf("%s\n", b); //输出 12eer
return 0;
}
3. memmove
memmove与memcpy不一样的地方就是memmove会考虑目标区域与来源区域存在重叠的情况。那么如果目标区域在来源区域的前面,则从头一个一个赋值。如果目标区域在来源区域的后面,则从尾开始一个一个赋值。这样子就可以防止赋值过去的值将还未复制的值覆盖的情况了。
#include <stdio.h>
#include <string.h>
void *mymemmove(void *dst, void *src, int count)
{
if (dst == NULL || src == NULL) {
return dst;
}
char *tmp_dst = (char *)dst, *tmp_src = (char *)src;
if (dst < src) {
while (count--) {
*(tmp_dst++) = *(tmp_src++);
}
}
else if (src < dst) {
// 注意这里是要 - 1
tmp_src += count - 1;
tmp_dst += count - 1;
while (count--) {
*(tmp_dst--) = *(tmp_src--);
}
}
return dst;
}
int main()
{
char a[] = "123456789qwerty";
mymemmove(a+5, a, 5);
printf("%s\n", a); // 输出 1234512345werty
mymemmove(a, a+9, 5);
printf("%s\n", a); // 输出 5wert12345werty
return 1;
}