Day1笔面中的算法和编程准备【21天挑战C++笔面试】

135 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

总览C++算法开发的一些注意事项,常见的算法题。

一、C语言陷阱

1. 一道入门题:Memmov,把内存中的一块内容从 src 处拷贝到 des 处,拷贝的长度是 n

void *memmove(void *dest, const void *src, size_t n) {
    // implementation here 
}

其中

  • dest -- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
  • src -- 指向要复制的数据源,类型强制转换为 void* 指针。
  • n -- 要被复制的字节数。

(1)错误事例

void *memmove(void *dest, const void *src, size_t n)
{
    char *p1 = dest; 
    char *p2 = src;

    while (*p2 != \0) 
        *p1++ = *p2++;

    return p1; 
}

(2)C语⾔的陷阱

  • 内存重叠的处理

【情况1】内存重叠,造成拷贝后原数据丢失,最终dest值为 1212

image.png

【情况2】非内存重叠,破坏原始数据

image.png

  • 临时变量太多或者没安全释放
  • 没有测试内存越界
  • 指针操作不熟悉

(3)正确解法

void* my_memmove(void *dest, const void *src, int n)
{
	assert(dest != NULL);
	assert(src != NULL);

	char *p_dest = (char*)dest;
	const char *p_src = (char*)src;

	if (p_src < p_dest)
	{
		//dest: x x o o o o o o 
		//src:  o o o o o o
		//内存重叠,从后往前拷贝
		p_src += n;
		p_dest += n;
		while (n-- != 0)
		{
			*(--p_dest) = *(--p_src);
		}
	}
	else
	{
		//【情况1:起始位置相同,无需拷贝】
		//dest: o o o o o o 
		//src:  o o o o o o
		//【情况2:源在后,正向拷贝】
		//dest: o o o o o o 
		//src:  x x o o o o o o
		//正向赋值
		while (n-- != 0)
		{
			*(char*)p_dest++ = *(char*)p_src++;
		}
	}
	return dest;
}

测试

int main()
{
	char dest[] = "00123456789"; 
	std::cout << "After memmove dest:" << (char*)my_memmove(dest, dest+2, 4);
        //std::cout << "After memmove dest:" << (char*)my_memmove(dest+2, dest, 4);
	return 0;
}

上述代码给出了防止数组越界的测试 测试数据: dest:00123456789 src: xx123456789 二者地址的关系是: dest < src (如下图所示)

image.png

根据注释的内容可以尝试,dest > src 的情况的测试。

可以思考一下代码是不是还有其他问题呢?