- strlen 函數的實現
int my_strlen(char* dst) {
assert(dst);
char* ret = dst;
int count = 0;
while (*ret!='\0') {
++ret;
++count;
}
return count;
}
- strcat 函數的實現
har* my_strcat(char* dst, const char* src) {
assert(dst && src);
char* ret = dst; // 因爲後邊 dst需要++,所以用ret保存原來的位置
while (*dst != '\0') { //先找到 dst 上'\0' 的位置
++dst;
}
while (*dst++ = *src++); //當 dst 到 '\0'了,再將 src 傳給 dst
return ret;
}
和strcpy 不同的是 strcpy是拷貝,strcat是追加拷貝。
- strcmp 函數的實現
int my_strcmp(const char* str1,const char* str2) {
assert(str1 && str2);
unsigned char* s1 = (unsigned char*)str1;
unsigned char* s2 = (unsigned char*)str2;
while (*s1 && *s2) {
if (*s1 > *s2) {
return 1;
}
else if (*s1 < *s2) {
return -1;
}
else {
++s1;
++s2;
}
}
if (*s1 == '\0'&&*s2 == '\0') {
return 0;
}
else if (*s1 == '\0') {
return -1;
}
else {
return 1;
}
}
strcmp 函數居然是根據字符串中字符的 ASCII 碼大小來比較字符串大小的,我有一點不解,假如有兩個字符串 str1 = “abbb” 和 str1 = “baaa”,用 strcmp 函數的話,結果是 str2 大於 str1,僅僅是因爲 str2 的第一個字符 b 的 ASCII 碼大於 str1 的 a。我的想法是應該比較總的 ASCII 碼的大小。(僅僅是我自己的臆想,還是按照人家的來吧!)
- strstr 函數的實現
判斷一個字符串是不是另一個字符串的子串,如果是,則該函數返回 str2 在 str1 中首次出現的地址,否則,返回NULL。
char* my_strstr(const char* src, const char* sub) {
assert(src && sub);
const char* srci = src;
const char* subi = sub;
while (*srci != '\0') {
while (*srci == *subi && *subi != '\0') {
++srci;
++subi;
}
if (*subi == '\0') {
return src;
}
else {
subi = sub;
++src;
srci = src;
}
}
}
- memcpy 函數的實現
void* my_memcpy(void* dst, const void* src, size_t num) {
assert(dst && src);
char* str_dst = (char*)dst;
char* str_src = (char*)src;
for (size_t i = 0; i < num; ++i) {
str_dst[i] = str_src[i]; // 等價於 *(str_src + i)
}
return dst;
}
memcpy函數和strcpy函數的一個區別在於,memcpy可以拷貝任意類型的數據,而strcpy函數只能拷貝字符串
-
memmove 函數的實現
memmove 函數有兩種實現的方法。
如圖要將紅色部分的數據拷貝到黑色部分,第一種情況是內存的前重疊,和不重疊,直接從 src 的前往 src 的後拷貝給 dst,不會影響結果。但是如果是內存的後重疊,如下圖:
如果還是按照從前往後進行拷貝,把 src 的第一個數據拷給 dst 的第一個數據時,就已經改變了 src 後邊的數據,因爲 dst 第一個數據所在位置剛好重疊與 src 後邊的數據,這樣拷貝,已經改變了還沒有拷貝給 dst 的數據,後邊拷貝的數據並不是我們最初想要的。所以這種內存後重疊,我們就要從後往前進行拷貝,也就是說,先把 src 的最後一個數據拷貝給 dst 的最後一個數據,然後把 src 的倒數第二個數據拷貝給 dst 的倒數第二個數據,以此類推。這樣做就不會改變還沒有拷貝給 dst 的 src 數據。
以下有兩種拷貝方式,第一種是:給前重疊或者不重疊從前往後拷貝,給後重疊或者不重疊從後往前拷貝(從前往後或者從後往前拷貝都不會影響到內存不重疊的拷貝)。 第二種是:給內存前重疊或者不重疊的從前往後拷貝,給內存後重疊的從後往前拷貝。第一種
void* my_memmove(void* dst, const void* src, size_t num) {
assert(src && dst);
char* str_dst = (char*)dst;
char* str_src = (char*)src;
if (str_dst < str_src) { //前重疊或者不重疊,從前往後拷貝
for (size_t i = 0; i < num; ++i) {
str_dst[i] = str_src[i];
}
}
else {//後重疊或者是不重疊,從後往前拷貝
for (int i = num-1 ; i >= 0; --i) {
str_dst[i] = str_src[i];
}
}
return dst;
}
**第二種**
void* my_memmove(void* dst, const void* src, size_t num) {
assert(src && dst);
char* str_dst = (char*)dst;
char* str_src = (char*)src;
if (str_src < str_dst && str_dst<str_src +num) { //後重疊 從後往前拷貝
for (int i = num - 1; i >= 0; --i) {
str_dst[i] = str_src[i];
}
}
else { //前重疊或者不重疊,從前往後拷貝
for (size_t i = 0; i < num; ++i) {
str_dst[i] = str_src[i];
}
}
return dst;
}
值得一提的是,字符串數組可以用這種方式初始化(char str[] = “abcdefg”),但是不可以用這種方式賦值,這裏就可以用到字符串函數 strcpy memcpy memmove