memcpy
#include <iostream>
#include <cassert>
// #include <cstring>
#include "test.h"
using namespace std;
// 返回值的目的是满足链式表达
// ====================================================================
// // 考虑不周全
// // 当 dest 在 src 的内部时,dest的起始将覆盖掉 src 的数据,导致 src 后面数据丢失
// // src---------------
// // dest---------------
// void* memcpy(void* dest, const void* src, size_t n)
// {
// assert(dest != NULL && src != NULL);
// char* d = (char*)dest;
// char* s = (char*)src;
// while (n--) {
// *d++ = *s++;
// }
// return dest;
// }
void* memcpy(void* dest, const void* src, size_t n)
{
assert(dest != NULL && src != NULL);
char* d = (char*)dest;
char* s = (char*)src;
if (d > s && d < s + n) { // 从后往前复制
d += n - 1;
s += n - 1;
while (n--) {
*d-- = *s--;
}
}
else { // 从前往后复制
while (n--) {
*d++ = *s++;
}
}
return dest;
}
// ====================================================================
int main()
{
// 没有重叠部分
int src1[5] = {1,2,3,4,5};
int dst1[10];
memcpy(&dst1[0], src1, sizeof(int) * 5);
cout << "src1: "; print(src1, 5);
cout << "dst1: "; print(dst1, 10);
// 重叠 dest---src-------
int* dst2 = (int*)malloc(sizeof(*dst2) * 10);
int* src2 = dst2 + 3;
// 对src2赋值
for (int i=0; i<5; ++i) src2[i] = i;
cout << "\naddress:\n" << dst2 << "\n" << src2 << endl;
cout << "src2: "; print(src2, 5);
// 从src2 往 dst2 memcpy 5 个数
memcpy(dst2, src2, 5 * sizeof(int));
cout << "src2: "; print(src2, 5); // src src2已经被改变
cout << "dst2: "; print(dst2, 5);
// 重叠 src---dest-------
int* src3 = (int*)malloc(sizeof(*src3) * 10);
int* dst3 = src3 + 3;
// 对src3赋值
for (int i=0; i<5; ++i) src3[i] = i;
cout << "\naddress:\n" << src3 << "\n" << dst3 << endl;
cout << "src3: "; print(src3, 5);
// 从src3 往 dst3 memcpy 5 个数
memcpy(dst3, src3, 5 * sizeof(int));
cout << "src3: "; print(src3, 5);
cout << "dst3: "; print(dst3, 5);
// src1: 1 2 3 4 5
// dst1: 1 2 3 4 5 21992 689871264 21992 317540080 32766
// address:
// 0x55e829dd7280
// 0x55e829dd728c
// src2: 0 1 2 3 4
// src2: 3 4 2 3 4
// dst2: 0 1 2 3 4
// address:
// 0x55e829dd72b0
// 0x55e829dd72bc
// src3: 0 1 2 3 4
// src3: 0 1 2 0 1
// dst3: 0 1 2 3 4
return 0;
}
memset
按字节赋值,每个字节赋值范围为char
的范围,其他类型会拆成字节来赋值,所以只可以初始化为0或者-1(0xFF)。
#include <iostream>
#include <cassert>
// #include <cstring>
#include "test.h"
// 返回值的目的是满足链式表达
// ====================================================================
// 按字节赋值,可以完成字符赋值 或 为 0 -1,其他不行 (0, 0xFF)
void* memset(void* src, int c, size_t n)
{
assert(src != NULL);
char* psrc = (char*)src;
while (n--) {
*psrc++ = (char)c;
}
return src;
}
// ====================================================================
int main()
{
int nums[10];
memset(nums, -1, 10*sizeof(int));
print(nums, 10);
// -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
return 0;
}
strcpy
与memcpy类似,只是最后多个\0
需要添加。
#include <iostream>
#include <cassert>
#include <cstring>
#include "test.h"
// ==============================================================
// // 未考虑重叠情况
// char* strcpy(char* dest, const char* src)
// {
// assert(dest != NULL && src != NULL);
// char* ret = dest;
// while ((*dest++ = *src++) != '\0');
// return ret;
// }
char* strcpy(char* dest, const char* src)
{
assert(dest != NULL && src != NULL);
char* pdst = dest;
size_t n = strlen(src);
if (dest > src && dest < src + n) {
src += n - 1;
pdst += n;
*pdst-- = '\0';
while (n--) {
*pdst-- = *src--;
}
}
else {
while ((*pdst++ = *src++) != '\0');
}
return dest;
}
// ==============================================================
int main()
{
char s1[10] = "hello!";
char s2[10];
strcpy(s2, s1);
printf("s1: %s\n", s1);
printf("s2: %s\n\n", s2);
char* src1 = (char*)malloc(10*sizeof(char));
char* dest1 = src1 + 3;
strcpy(src1, "hello!");
printf("src1: %s\n", src1);
strcpy(dest1, src1);
printf("src1: %s\n", src1);
printf("dest1: %s\n", dest1);
// s1: hello!
// s2: hello!
// src1: hello!
// src1: helhello!
// dest1: hello!
return 0;
}
strcat
#include <iostream>
#include <cassert>
#include "test.h"
// =================================================
// 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾
char* strcat(char* dest, const char* src)
{
assert(dest != NULL && src != NULL);
char* ret = dest;
while (*dest != '\0') {
dest++;
}
while ((*dest++ = *src++) != '\0');
return ret;
}
// =================================================
int main()
{
char src[10] = "world!";
char dest[20] = "hello ";
strcat(dest, src);
printf("%s\n", dest);
// hello world!
return 0;
}
strcmp
#include <iostream>
#include <cassert>
#include "test.h"
// =================================================
// 字符串比较 '\0'(0)
int strcmp(const char* s1, const char* s2)
{
assert(s1 != NULL && s2 != NULL);
while (*s1 && *s2 && *s1 == *s2) {
s1++;
s2++;
}
return *s1 - *s2;
}
// =================================================
int main()
{
const char* s1 = "hello!";
const char* s2 = "hello! ";
std::cout << strcmp(s1, s2) << std::endl;
// -32
return 0;
}
strlen
#include <iostream>
#include <cassert>
#include "test.h"
// ==============================================================
size_t strlen(const char* str)
{
assert(str != NULL);
size_t n = 0;
while (*str != '\0') {
str++;
n++;
}
return n;
}
// ==============================================================
int main()
{
const char* str = "hello!";
std::cout << strlen(str) << std::endl;
// 6
return 0;
}
strncpy
#include <iostream>
#include <cassert>
#include "test.h"
// ===========================================================
// 复制指定长度的字符串,末尾\0
char* strncpy(char* dest, const char* src, size_t n)
{
assert(dest != NULL && src != NULL);
char* ret = dest;
const char* psrc = src;
size_t lensrc = 0;
while (*psrc++ != '\0') lensrc++;
n = lensrc > n ? n : lensrc;
if (dest > src && dest < src + n) {
dest += n;
*dest-- = '\0';
src += n - 1;
while (n--) {
*dest-- = *src--;
}
} else {
while (n--) {
*dest++ = *src++;
}
if (*(dest - 1) != '\0') *dest = '\0';
}
return ret;
}
// =============================================================
int main()
{
char src[20] = "hello world!";
char* dest = &src[0] + 3;
printf("src : %s\n", src);
strncpy(dest, src, 7);
printf("src : %s\n", src);
printf("dest: %s\n", dest);
// src : hello world!
// src : helhello w
// dest: hello w
return 0;
}