目录
<string.h>库
一、strlen()
二、strcpy()
---strncpy()
三、strcat()
---strncat()
四、strcmp()
---strncmp()
五、strstr()
六、strtok()
七、字符分类函数
内 存 函 数
一、memcpy()
二、memmove()
三、memcmp()
四、memset()
<string.h>库 一、strlen()
size_t strlen(const char * str);
字符串会以‘’作为结束标志,strlen则会返回’’以前出现的字符个(不包含)若没有‘’,则会出现找不到返回随机值的情况。
strlen()的模拟实现:
unsigned int my_strlen(char* p) { int count = 0; while (*p++) { count++; } return count; }
易错点:
#include#include int main() { //if ((int)strlen("abc") - (int)strlen("abcdef") > 0) if (strlen("abc") - strlen("abcdef")>0 ) printf(">"); else printf("<="); return 0; }
这个会打印什么呢?
答案:
-3 > 0吗?!!
原来,size_t strlen(const char * str);中的size_t表示unsigned int(无符号整形)即:size_t strlen(const char * str);--->unsigned int strlen(const char * str);
#include#include int main() { if ((int)strlen("abc") - (int)strlen("abcdef") > 0) //if (strlen("abc") - strlen("abcdef")>0 ) printf(">"); else printf("<="); printf("n"); printf("%un", strlen("abc") - strlen("abcdef"));//很大的正数 printf("%dn", (int)strlen("abc") - (int)strlen("abcdef"));//-3 // 然而 printf("%dn", strlen("abc") - strlen("abcdef"));//-3 return 0; }
经过测试可知,两个无符号整形相减只能是正数,但是打印时不注意%u和%d容易误解;
所以判断比较strlen的长度时要用:
if ((int)strlen("abc") - (int)strlen("abcdef") > 0) if (strlen("abc") > strlen("abcdef") ) 不可 if (strlen("abc") - strlen("abcdef") > 0)
这是由strlen类型导致的易错点!
二、strcpy()char* strcpy(char * destination, const char * source);
strcpy()模拟实现:
char* my_strcpy(char* dest, const char* src) { char* ret = dest; while (*dest++ = *src++) { ; } return ret; }
源字符串即待拷贝字符串,必须以’‘结束会将源字符串中的’’拷贝到目标字符串目标空间需要足够大,来确保能够存放源字符串.目标空间必须可变
测试:
1.将’‘去除
2.编译器内存框观察是否会将源字符串中的’’拷贝到目标字符串
3.将N改为小于字符串abcdef长度的数,如5
4.在char* dest前也加const,使目标空间必须不可变
#include#include const int N = 20; char* my_strcpy(char* dest, const char* src) { char* ret = dest; while (*dest++ = *src++) { ; } return ret; } int main() { char arr1[] = {'a', 'b', 'c', 'd', 'e', 'f', ''}; char arr2[N] = "xxxxxxxxxxxx"; my_strcpy(arr2, arr1); //strcpy(arr2, arr1); printf("%sn", arr2); printf("%sn", my_strcpy(arr2, arr1)); //printf("%sn", strcpy(arr2, arr1)); return 0; }
测试结束后你将彻底掌握strcpy();
---strncpy()char * strncpy(char * dest, const char * sour, size_t num);
拷贝num个字符从源字符串到目标空间.如果源字符串的长度小于num,则拷贝完字符串之后,在目标后边加0,直到num个.
#include三、strcat()#include int main() { char arr1[] = "123456789"; char arr2[] = "abcdefg"; printf("%sn", arr1); strncpy(arr1a, arr2, 5); printf("%sn", arr1); return 0; } output 123456789 abcde6789
char * strcat ( char * dest, const char * sour);
strcat() 模拟实现:
char* my_strcat(char* arr, const char* arr1) { char* ret = arr; assert(arr && arr1); while (*arr) { arr++; } while ((*arr++ = *arr1++)) { ; } return ret; }
源字符串必须以’’为结束。目标空间足够大。目标空间可修改.注意不可字符串自己给自己追加,会出现目标空间不足的情况
可粗略理解为两个字符串拼接在一起
#include---strncat()#include char* my_strcat(char* dest, const char* src) { char* ret = dest; //1. 目标空间中的 while (*dest) { dest++; } //2. 追加内容到目标空间 while (*dest++ = *src++) { ; } return ret; } int main() { char arr1[30] = "hello"; char arr2[] = "world";// {'w', 'o', 'r', 'l', 'd', ''}; printf("%sn", my_strcat(arr1, arr2)); printf("%sn", arr1); //printf("%sn", strcat(arr1, arr2)); return 0; }
char * strncat( char * dest, const char * sour, size_t num);
同理,遇到停止
#include四、strcmp()#include const int N=10; int main() { char arr1[20] = "12345xxxxxxx"; char arr2[] = "abcdefgyyy"; printf("%sn", arr1); strncat(arr1, arr2, N); //strncpy(arr1, arr2, 5); printf("%sn", arr1); return 0; } output 12345 12345abcdefg 若N=2 output 12345 12345ab
int strcmp ( const char * str1, const char * str 2);
strcmp()模拟实现:
#include#include int my_strcmp(const char* str1, const char*str2) { while (*str1 == *str2) { if (*str1 == '') return 0; str1++; str2++; } return *str1 - *str2;
第一个字符串大于第二个字符串,则返回大于0的数字第一个字符串等于第二个字符串,则返回0第一个字符串小于第二个字符串,返回小于0的数字字符串比较时,对应位置一一比较
测试:
#include---strncmp()#include int my_strcmp(const char* str1, const char*str2) { while (*str1 == *str2) { if (*str1 == '') return 0; str1++; str2++; } return *str1 - *str2; } int main() { //strcmp - 字符串比较 //比较是对应位置上的字符大小 char arr1[] = "abd"; char arr2[] = "abce"; int ret = my_strcmp(arr1, arr2); if (ret<0) { printf("arr10) { printf("arr1>arr2"); } else { printf("arr1==arr2"); } return 0; }
int strncmp ( const char * str1, const char * str2, size_t num);
比较出现不一样的字符一个字符串结束num个字符全部比完
#include#include const int N = 3; int main() { char arr1[] = "abcwef"; char arr2[] = "abcqqqqqq"; int ret = strncmp(arr1, arr2, N); if (ret < 0) { printf("arr1 0) { printf("arr1>arr2"); } else { printf("arr1==arr2"); } return 0; } output arr1==arr2
五、strstr()
char * strstr ( const char *str1, const char * str2);
strstr()模拟实现:
char* my_strstr(const char* str, const char* substr) { const char* s1 = str; const char* s2 = substr; const char* cur = str; if (*substr == '') { return (char*)str; } while (*cur) { s1 = cur; s2 = substr; while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; } if (*s2 == '') return (char*)cur; cur++; } return NULL; }
寻找子集,看str1中是否存在str2.若存在,返回str1中出现str2的地址若不存在,返回NULL
测试:
#include#include char* my_strstr(const char* str, const char* substr) { const char* s1 = str; const char* s2 = substr; const char* cur = str; if (*substr == '') { return (char*)str; } while (*cur) { s1 = cur; s2 = substr; while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; } if (*s2 == '') return (char*)cur; cur++; } return NULL; } int main() { char arr1[] = "abbbcdef"; char arr2[] = "bbc"; char* ret = my_strstr(arr1, arr2); //char* ret = strstr(arr1, arr2); if (NULL == ret) printf("没找到n"); else printf("%sn", ret); return 0; }
output:
bbcdef六、strtok()
char * strstr ( const char *str1, const char * str2);
strtok()模拟实现:
char * strstr (const char * str1, const char * str2) { char *cp = (char *) str1; char *s1, *s2; if ( !*str2 ) return((char *)str1); while (*cp) { s1 = cp; s2 = (char *) str2; while ( *s1 && *s2 && !(*s1-*s2) ) s1++, s2++; if (!*s2) return(cp); cp++; } return(NULL);
sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用结尾,返回─个指向这个标记的指针。(注:strtok函数会改变被 *** 作的字符串,
所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回NULL指针。
1. strtok函数找第一个标记的时候,函数的第一个参数丕是NULD.
2. strtok函数找非第一个标记的时候,函数的第一个参数是NULL
例子:
#include#include int main() { const char* p = "@.#"; char arr[] = "zpengwei@yeah.net#hehe"; char buf[50] = { 0 };// "zpengwei@yeah.net" strcpy(buf, arr); char* str = strtok(buf, p);//zpengwei printf("%sn", str); str = strtok(NULL, p);//yeah printf("%sn", str); str = strtok(NULL, p);//net printf("%sn", str); //strtok - 开始返回NULL return 0; } output zpengwei yeah net
标准用法:
#include#include int main() { const char* p = "@.#"; char arr[] = "zpengwei@yeah.net@hehe#666"; char buf[50] = { 0 }; strcpy(buf, arr); char* str = NULL; for (str = strtok(buf, p); str != NULL; str=strtok(NULL, p)) { printf("%sn", str); } return 0; }
测试输出:
七、字符分类函数
使用前先引#include
实用例子:
#include#include int main() { int i=0; char str[]="Test string. n"; char c; while (str[i]) { c=str[i]; if (isupper(c)) c=tolower(c); putchar (c); i++; } return 0; } output test string.
内 存 函 数 一、memcpy()
void * memcpy( void * dest, const void * sour, size_t num)
memcpy() 模拟实现:
void* my_memcpy(void* dest, const void*src, size_t num) { void* ret = dest; while (num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } return ret; }
函数从sour的位置开始向后复制num个字节数据到dest的内存位置遇到’’并不会停下来不管有任何重叠,复制的结果是未定义的
测试:
#include二、memmove()#include int main() { int arr3[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr4[5] = { 0 }; memcpy(arr4, arr3+5, 5*sizeof(arr3[0])); int i = 0; for (i = 0; i < 5; i++) { printf("%d ", arr4[i]); } return 0; } output 6 7 8 9 10
void * memmove ( void * dest, const void * sour, size_t num);
memmove()模拟实现:
void* my_memmove(void* dest, const void* src, size_t num) { void* ret = dest; assert(dest && src); if (dest < src) { //前->后 while (num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } else { //后->前 while (num--) { *((char*)dest+num) = *((char*)src + num); } } return ret; }
和memcpy的区别是memmove函数处理的源内存块和目标内存块是可以重叠的如果出现重叠,就使用memmove
测试:
#include#include void* my_memmove(void* dest, const void* src, size_t num) { void* ret = dest; if (dest < src) { //前->后 while (num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } else { //后->前 while (num--) { *((char*)dest+num) = *((char*)src + num); } } return ret; } void test1() { int arr3[] = { 1,2,3,4,5,6,7,8,9,10 }; //1 2 1 2 3 4 5 8 9 10 //my_memcpy(arr3+2, arr3, 5 * sizeof(arr3[0])); //my_memmove(arr3, arr3+2, 20); memmove(arr3+2, arr3, 20); //memcpy(arr3+2, arr3, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr3[i]); } } int main() { test1(); return 0; }
总结:memmove (A,B,元素个数*元素字节)用法---->将从B数组地址表示的元素开始,向后包含(元素个数*元素字节)个字节表示的元素,覆盖从A数组地址表示的元素开始个元素。
三、memcmp()void * memmcp ( void * dest, const void * sour, size_t num);
#include#include int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 'a','b',1,2,3 }; int ret = memcmp(arr1, arr2+2, 9); printf("%dn", ret); return 0; } output 0
非常简单的比较
A=B return 0;
A>B return 1;
A
注意:是一个字节一个字节地比较!
四、memset()void *memset( void *dest. int c, size_t count):
例子1:
size_t count 依然表示字节数
#include#include int main() { char arr[20] = "abcdefghijklmn"; memset(arr, 'x', 6); printf("%s",arr); return 0; } output xxxxxxghijklmn
例子2:
#include#include int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; memset(arr, 0, 9); for (int i = 0; i < 10; i++) printf("%d ", arr[i]); return 0; } ouyput 0 0 0 4 5 6 7 8 9 10
原内存:01 00 00 00 02 00 00 00 00 03 00 00 00 04 00 00 00 00......
修改后:00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 00.......(将前面9个字节改为0)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)