strlen
實現的方法:
使用 指針-指針 算出之間的差值,也就是這個字符串的真實長度
(指針-指針的要求就是:兩個指針是同一個類型)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int My_Strlen(char *p)
{
char *p1 = p;
while( *p1 != '\0' )
{
*p1++;
}
return p1-p;
}
void testMy_strlen()
{
char *p = "1234";
printf("%d\n",My_Strlen(p));
}
strcpy
功能:字符串拷貝,把源字符串src,拷貝到目標空間dest中
實現過程:
1. 目標空間( dest )足夠大,足夠容得下src字符串(包括\0)
2. 目標字符串可修改,源字符串不能修改(類型前加const)
3. 模擬實現strcpy返回值類型是char*,有返回值爲了實現鏈式訪問
4. 把src中內容拷貝到dest中,直到src的'\0'拷貝過去結束
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
char* my_strcpy( char *dest,const char *src )
{
char *ret = dest;
assert(dest!=NULL);
assert(src!=NULL);
while( *ret++ = *src++ )
{
;
}
return dest;
}
void testMy_strcpy()
{
char p1[20] = "abcd";
char *p2 = "efghi";
my_strcpy(p1,p2);
printf("%s\n",p1);
printf("%d\n",strlen(my_strcpy(p1,p2)));
}
運行結果:
strcat
功能:字符串追加,把源字符串src,追加到目標空間dest中
實現過程:
1. 目標空間( dest )足夠大,足夠容得下追加的src字符串(包括\0)
2. 目標字符串可修改,源字符串不能修改(類型前加const)
3.模擬實現strcat返回值類型是char*,有返回值爲了實現鏈式訪問
4. 過程:
首先要找目標空間dest中'\0',並且讓源字符串src覆蓋dest中'\0',
然後開始追加,直到追加到src的'\0'結束
顯然:
strcat不能實現自己給自己追加,因爲剛開始追加的時候,已經
把'\0'覆蓋,後面再去追加時(結束條件是:遇到'\0'),所以是無法實現的
char* My_Strcat(char *dest,const char *src)
{
char *ret = dest;
assert(dest && src);
while( *dest != '\0' )
{
*dest++;
}
while( *dest++ = *src++ )
{
;
}
return ret;
}
void testMy_strcat()
{
char p1[20] = "abcd ";
char *p2 = "efgh";
My_Strcat(p1,p2);
printf("%s\n",p1);
}
運行結果:
strcmp
功能:字符串比較函數
實現過程:
1. 首先s1和s2是固定字符串,要實現的是比較,所以都不能被修改
因此必須加上const 修飾
2. 先判斷兩個字符串長度是否相等,如果不相等,就沒有必要再去遍歷,直接返回-1
3. 如果相等:一起遍歷字符串,首先比較第一個字符:
1. 兩個字符的ASCII碼值如果不相等,直接返回-1
2. 兩個字符的ASCII碼值相等,繼續遍歷
3. 直到遍歷遇到'\0',結束遍歷
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int My_Strcmp(const char *dest,const char *src)
{
int len1 = strlen(dest);
int len2 = strlen(src);
if( len1 != len2 )
return -1;
else
{
while( *dest && *src )
{
if( *dest == *src )
{
*dest++ ;
*src++ ;
}
else
return -1;
}
return 0;
}
}
void testMy_strcmp()
{
char *p1 = "hell0";
char *p2 = "hello";
int flag = My_Strcmp(p1,p2);
if( flag == 0 )
{
printf("兩個字符串相等\n");
}
else
{
printf("兩個字符串不相等\n");
}
}
運行結果:
strstr
功能:在字符串中查找子串,如果找到,輸出第一次找到子串的開始位置
實現過程:
1. 首先str和substr是固定字符串,要實現的是查找,所以都不能被修改
因此必須加上const 修飾
2. 要考慮到多種情況如下
1."abcdef"中找"bcd" 返回b的地址,輸出bcdef
2."abcdef"中找""(空字符串) 沒有必要找,直接把abcdef輸出
3.“abcbcd”中找"bcd"
開始找str中b和substr中b相同,繼續向後發現b和c不同,這時
substr應當退回去,從str中剛纔開始匹配的下一個元素開始重新匹
配,也就是str第三個元素開始繼續匹配,如此重複,直到匹配成功。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
char* My_Strstr( const char *str, const char *substr )
{
char *cp = (char *)str;
char *cur1 = (char *)str;
char *cur2 = (char *)substr;
assert(str);
if( *substr == '\0' )
return cp;
while( *cp )
{
cur1 = cp;
cur2 = (char *)substr;
while( *cur1 && *cur2 && (*cur1 == *cur2) )
{
*cur1++;
*cur2++;
}
if( *cur2 == '\0' )
return cp;
*cp++;
}
return NULL;
}
void testMy_strstr()
{
char *p1 = "abcdbcd";
char *p2 = "";
printf("%s\n",My_Strstr(p1,p2));
}
運行結果:
char *p1 = "abcdbcd";
char *p2 = "bcd";
memcpy
功能:
由src指向地址爲起始地址的連續n個字節的數據複製到以dest指向地址爲起始地址的空間內。
(src和dest內存不重疊)
memcpy 和 strcpy 的區別:
原型:
void *memcpy(void *memTo,const void *memFrom,size_t size)
char *strcpy(char *dst,const char *src);
相同點:
strcpy與memcpy都可以實現拷貝的功能
不同點:
1、複製的內容不同。strcpy只能複製字符串,而memcpy可以複製任意內容,
例如字符數組、整型、結構體、類等。
2、複製的方法不同。strcpy不需要指定長度,它遇到被複制字符的串結束符"\0"才結束,
所以容易溢出。memcpy則是根據其第3個參數決定複製的長度。
3、用途不同。通常在複製字符串時用strcpy,而需要複製其他類型數據時則一般用memcpy
4、實現功能不同,strcpy主要實現字符串變量間的拷貝,memcpy主要是內存塊間的拷貝。
5、操作對象不同,strcpy的操作對象是字符串,memcpy 的操作對象是內存地址,並不限於何種數據類型。
6、執行效率不同,memcpy最高,strcpy次之。
#include<stdlib.h>
#include<string.h>
#include<assert.h>
void *my_memcpy(void*dest, void*src, size_t n)
{
char *p = (char *)dest;
const char *p1 = (const char *)src;
assert(dest && src);
while(n--)
{
*p++ = *p1++;
}
return dest;
}
void testMy_Memcpy()
{
char p1[20] = "abc";
char *p2 = "abcdefg";
my_memcpy(p1,p2,5);
printf("%s\n",p1);
}
memmove
功能:
由src指向地址爲起始地址的連續n個字節的數據複製到以dest指向地址爲起始地址的空間內。
(src和dest內存重疊)
注意:
不重疊部分:從前向後拷貝
重疊部分:從後向前拷貝
#include<stdlib.h>
#include<string.h>
#include<assert.h>
void * my_memmove( void *dest, const void * src, size_t count )
{
void * ret = dest;
if( dest <= src || (char *)dest >= (char *)src+count )
{
while( count-- )
{
*(char *)dest = *(char *)src;
dest = (char *)dest + 1;
src = (char *)src + 1;
}
}
else
{
dest = (char *)dest + count-1;
src = (char *)src + count -1;
while(count--)
{
*(char *)dest = *(char *)src;
dest = (char *)dest -1;
src = (char *)src -1;
}
}
return ret;
}
void testMy_Memmove()
{
char p[] = "abcdefgh";
my_memmove(p,p+3,5);
printf("%s\n",p);
}
memset
功能:
將s所指向的某一塊內存中的前n個字節的內容全部設置爲ch指定的ASCII值
1. 第一個參數爲指定內存地址
2. 塊的大小由第三個參數指定
3. 這個函數通常爲新申請的內存做初始化工作,其返回值爲指向s的指針
void * my_memset(void*s, int ch, size_t n)
{
assert(s);
char *ret = (char *)s;
while (n--)
{
*ret++ =(char) ch;
}
return s;
}
int main()
{
char arr[10];
int i;
my_memset(arr, 0, 10*sizeof(char));
for (i = 0; i < 10; i++)
{
printf("%d\n", arr[i]);
}
system("pause");
return 0;
}