- memmov
#include <iostream>
#include <cstring>
void* memmov(void* destination, const void* source, size_t num)
{
char* dest = static_cast<char*>(destination);
const char* src = static_cast<const char*>(source);
// Check for overlapping memory regions
if (dest < src)
{
// Copy forward starting from the beginning
for (size_t i = 0; i < num; ++i)
{
dest[i] = src[i];
}
}
else if (dest > src)
{
// Copy backward starting from the end
for (size_t i = num; i > 0; --i)
{
dest[i - 1] = src[i - 1];
}
}
return destination;
}
int main()
{
char source[] = "Hello, World!";
char destination[20];
memmov(destination, source, sizeof(source));
std::cout << "Destination: " << destination << std::endl;
return 0;
}
在上面的代码中,
memmov
函数接受三个参数:目标内存区域的指针destination
、源内存区域的指针source
和要复制的字节数num
。函数的返回类型是void*
,表示指向目标内存区域的指针。在函数内部,我们使用指针操作来逐字节复制内存内容。首先,我们将
destination
和source
强制转换为char*
类型的指针,以便进行字节级别的复制。然后,我们检查目标区域和源区域是否有重叠。如果目标区域的起始地址小于源区域的起始地址,则我们从头开始逐字节复制;如果目标区域的起始地址大于源区域的起始地址,则我们从尾部开始逐字节复制。最后,我们在
main
函数中测试memmov
函数,将一个字符串从源数组复制到目标数组,并打印目标数组的内容。请注意,虽然我们使用 C++ 编写了上述代码,但该函数的实现与 C 语言中的
memmove
函数是相同的。
- strcpy
#include <iostream>
#include <cstring>
char* strcpy(char* destination, const char* source)
{
char* dest = destination;
const char* src = source;
while (*src != '\0')
{
*dest = *src;
++dest;
++src;
}
*dest = '\0';
return destination;
}
int main()
{
char source[] = "Hello, World!";
char destination[20];
strcpy(destination, source);
std::cout << "Destination: " << destination << std::endl;
return 0;
}
在上述代码中,
strcpy
函数接受两个参数:目标字符串的指针destination
和源字符串的指针source
。函数的返回类型是char*
,表示指向目标字符串的指针。在函数内部,我们使用指针操作来逐字符复制字符串。首先,我们将
destination
和source
的地址分别赋给dest
和src
指针。然后,我们使用while
循环,将src
指针所指向的字符复制到dest
指针所指向的位置,并递增dest
和src
指针,直到遇到源字符串的结尾符'\0'
。最后,我们在目标字符串的末尾添加一个结尾符'\0'
,以确保复制后的字符串正确终止。最后,我们在
main
函数中测试strcpy
函数,将一个源字符串复制到目标字符串,并打印目标字符串的内容。请注意,虽然我们使用 C++ 编写了上述代码,但该函数的实现与 C 语言中的
strcpy
函数是相同的。
- atoi
#include <iostream>
#include <cstdlib>
int atoi(const char* str)
{
int result = 0;
int sign = 1;
int i = 0;
// Skip leading whitespaces
while (str[i] == ' ')
{
++i;
}
// Check for sign
if (str[i] == '+' || str[i] == '-')
{
sign = (str[i] == '-') ? -1 : 1;
++i;
}
// Convert digits to integer
while (str[i] >= '0' && str[i] <= '9')
{
result = result * 10 + (str[i] - '0');
++i;
}
return result * sign;
}
int main()
{
const char* str = "12345";
int number = atoi(str);
std::cout << "Number: " << number << std::endl;
return 0;
}
在上述代码中,
atoi
函数接受一个指向以 null 结尾的字符串的指针str
,并返回相应的整数值。函数内部首先初始化结果
result
为 0,符号sign
为 1,并定义一个索引变量i
来遍历字符串。然后,我们使用一个循环来跳过字符串中的前导空格。接着,我们检查字符串中是否有符号标记 '+' 或 '-',并根据符号标记更新
sign
的值,并将索引i
向后移动。最后,我们使用另一个循环将字符串中的数字字符转换为整数。我们将
result
乘以 10,并加上当前数字字符与字符 '0' 的差值,以得到相应的数字。然后,我们递增索引i
,继续处理下一个字符,直到遇到非数字字符为止。最后,我们将结果乘以符号
sign
,以考虑到正负号,并将最终的结果返回。在
main
函数中,我们测试了atoi
函数,将一个字符串转换为相应的整数,并打印结果。
- LRU
#include <iostream>
#include <unordered_map>
#include <list>
class LRUCache {
private:
std::unordered_map<int, std::pair<int, std::list<int>::iterator>> cache;
std::list<int> lruList;
int capacity;
public:
LRUCache(int capacity) {
this->capacity = capacity;
}
int get(int key) {
if (cache.find(key) == cache.end()) {
return -1; // Key not found
}
// Move accessed key to the front of the LRU list
lruList.erase(cache[key].second);
lruList.push_front(key);
cache[key].second = lruList.begin();
return cache[key].first;
}
void put(int key, int value) {
if (cache.find(key) != cache.end()) {
// Key already exists, update the value and move it to the front of the LRU list
lruList.erase(cache[key].second);
}
else if (cache.size() >= capacity) {
// Remove the least recently used key from the cache and the LRU list
int lastKey = lruList.back();
lruList.pop_back();
cache.erase(lastKey);
}
// Add the new key-value pair to the cache and the front of the LRU list
lruList.push_front(key);
cache[key] = { value, lruList.begin() };
}
};
int main() {
LRUCache cache(2);
cache.put(1, 1);
cache.put(2, 2);
std::cout << cache.get(1) << std::endl; // Output: 1
cache.put(3, 3);
std::cout << cache.get(2) << std::endl; // Output: -1
cache.put(4, 4);
std::cout << cache.get(1) << std::endl; // Output: -1
std::cout << cache.get(3) << std::endl; // Output: 3
std::cout << cache.get(4) << std::endl; // Output: 4
return 0;
}
在上述代码中,
LRUCache
类实现了一个简单的 LRU 缓存。它使用一个无序哈希映射cache
来存储键值对,其中键是缓存的键,值是包含缓存值和对应的 LRU 列表迭代器的pair
对象。LRU 列表lruList
是一个双向链表,存储了最近访问的键,最近访问的键位于链表的前端。在构造函数中,我们初始化了缓存的容量
capacity
。
get
方法用于获取给定键的值。如果键不存在于缓存中,返回 -1;否则,将访问的键移动到 LRU 列表的前端,并更新其对应的迭代器。然后,返回键对应的值。
put
方法用于将键值对放入缓存中。如果键已经存在于缓存中,更新对应的值,并将键移动到 LRU 列表的前端。如果缓存已满,需要移除最近最少使用的键(即 LRU 列表的末尾键),然后再将新键值对插入到缓存和 LRU 列表的前端。在
main
函数中,我们创建一个容量为 2 的缓存对象cache
,并演示了一些使用情况,包括插入键值对和获取键对应的值。
- vector
#include <iostream>
#include <stdexcept>
template <typename T>
class Vector {
private:
T* elements;
size_t size;
size_t capacity;
public:
Vector() : elements(nullptr), size(0), capacity(0) {}
~Vector() {
delete[] elements;
}
size_t Size() const {
return size;
}
bool Empty() const {
return size == 0;
}
T& operator[](size_t index) {
if (index >= size) {
throw std::out_of_range("Index out of range");
}
return elements[index];
}
const T& operator[](size_t index) const {
if (index >= size) {
throw std::out_of_range("Index out of range");
}
return elements[index];
}
void PushBack(const T& value) {
if (size >= capacity) {
size_t newCapacity = (capacity == 0) ? 1 : capacity * 2;
Reserve(newCapacity);
}
elements[size] = value;
++size;
}
void PopBack() {
if (size > 0) {
--size;
}
}
void Reserve(size_t newCapacity) {
if (newCapacity <= capacity) {
return;
}
T* newElements = new T[newCapacity];
for (size_t i = 0; i < size; ++i) {
newElements[i] = elements[i];
}
delete[] elements;
elements = newElements;
capacity = newCapacity;
}
};
int main() {
Vector<int> vec;
vec.PushBack(1);
vec.PushBack(2);
vec.PushBack(3);
std::cout << "Size: " << vec.Size() << std::endl;
for (size_t i = 0; i < vec.Size(); ++i) {
std::cout << vec[i] << " ";
}
std::cout << std::endl;
vec.PopBack();
std::cout << "Size after PopBack: " << vec.Size() << std::endl;
return 0;
}
在上述代码中,
Vector
类模板定义了一个动态数组。它使用指针elements
来存储数组元素,size
表示当前存储的元素个数,capacity
表示当前数组的容量。类中包含了一些常用的成员函数:
Size
返回当前数组的大小。Empty
判断数组是否为空。operator[]
重载了下标操作符,可以通过下标访问数组元素。PushBack
在数组尾部插入一个元素。PopBack
删除数组尾部的一个元素。Reserve
调整数组的容量,以便能够存储更多的元素。在
main
函数中,我们演示了如何使用Vector
类来创建一个动态数组,插入元素,访问元素,删除元素,并打印数组的大小。请注意,上述代码是一个简化的
Vector
类示例,没有实现所有可能的成员函数和功能。在实际应用中,
- string
#include <iostream>
#include <cstring>
class String {
private:
char* data;
size_t length;
public:
String() : data(nullptr), length(0) {}
String(const char* str) {
length = std::strlen(str);
data = new char[length + 1];
std::strcpy(data, str);
}
String(const String& other) {
length = other.length;
data = new char[length + 1];
std::strcpy(data, other.data);
}
~String() {
delete[] data;
}
size_t Length() const {
return length;
}
const char* CStr() const {
return data;
}
String& operator=(const String& other) {
if (this != &other) {
delete[] data;
length = other.length;
data = new char[length + 1];
std::strcpy(data, other.data);
}
return *this;
}
String operator+(const String& other) const {
String result;
result.length = length + other.length;
result.data = new char[result.length + 1];
std::strcpy(result.data, data);
std::strcat(result.data, other.data);
return result;
}
char& operator[](size_t index) {
if (index >= length) {
throw std::out_of_range("Index out of range");
}
return data[index];
}
const char& operator[](size_t index) const {
if (index >= length) {
throw std::out_of_range("Index out of range");
}
return data[index];
}
};
int main() {
String s1 = "Hello";
String s2 = " World";
String s3 = s1 + s2;
std::cout << "Concatenated String: " << s3.CStr() << std::endl;
std::cout << "Length of s1: " << s1.Length() << std::endl;
s1[0] = 'h';
std::cout << "Updated s1: " << s1.CStr() << std::endl;
return 0;
}
在上述代码中,
String
类实现了一个简单的字符串类。它使用指针data
来存储字符串的字符数组,length
表示字符串的长度。类中包含了一些常用的成员函数:
Length
返回字符串的长度。CStr
返回字符串的 C 风格字符数组。operator=
重载了赋值运算符,用于将一个String
对象赋值给另一个对象。operator+
重载了加号运算符,用于连接两个字符串。operator[]
重载了下标操作符,用于访问字符串的字符。在
main
函数中,我们演示了如何使用String
类来创建字符串对象,连接字符串,获取字符串长度,并修改字符串中的字符。请注意,上述代码是一个简化的
String
类示例,没有实现所有可能的成员函数和功能。在实际应用中,可能需要考虑更多的字符串操作,如插入、删除、查找等。此外,为了确保安全性和效率,可能需要实现更多的成员函数和优化。