求字符串长度
strlen
长度不受限制的字符串函数
strcpy
strcat
strcmp
长度受限制的字符串函数
strncpy
strncat
strncmp
字符串查找
strstr
strtok
错误信息报告
strerror
内存操作函数
memcpy
memmove
memset
memcmp
1 strlen
字符串以 '\0' 作为结束标志, strlen 函数返回的是在字符串中 '\0' 前面出现的字符个数(不包
含 '\0' )。 参数指向的字符串必须要以 '\0' 结束。 注意函数的返回值为size_t,是无符号的
模拟实现:
size_t my_strlen(const char* str) { assert(str); size_t count = 0; while (*str != '\0') { str++; count++; } return count; } int main() { char arr[] = "abcdefg"; size_t len = my_strlen(arr); printf("%u", len); return 0; }
2 strcpy
源字符串必须以 '\0' 结束。会将源字符串中的 '\0' 拷贝到目标空间。目标空间必须足够大,以确保能存放源字符串。目标空间必须可变。
模拟实现:
//char* my_strcpy(const char* str1, char* str2) //{ // char* ret = str2; // assert(str1 && str2); // while (*str1 != '\0') // { // *str2++ = *str1++; // // } // str2 = str1; // return ret; // //} //int main() //{ // char arr1[] = "abcdefgh"; // char arr2[10] = ""; // my_strcpy(arr1, arr2); // printf("%s",arr2); // return 0; //}
3 strcat(字符串追加)
源字符串必须以 '\0' 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
模拟实现:
char* my_strcat(char* str1, const char* str2) { assert(str1 && str2); char* ret = str1; while (*str1 != '\0') { str1++; } while (*str1++ = *str2++); return ret; } int main() { char arr1[10] = "hello"; char arr2[] = "word"; my_strcat(arr1, arr2); printf("%s", arr1); return 0; }
4 strcmp
第一个字符串大于第二个字符串,则返回大于 0 的数字
第一个字符串等于第二个字符串,则返回 0
第一个字符串小于第二个字符串,则返回小于 0 的数字
模拟实现:
int my_strcmp(char* str1, const char* str2) { assert(str1 && str2); while (*str1 == *str2) { str1++; str2++; } return (*str1 - *str2); } int main() { char arr1[] = "zhangsan"; char arr2[] = "zhangsanfeng"; int ret = my_strcmp(arr1, arr2); if (ret < 0) { printf("<\n"); } else if (ret == 0) { printf("==/n"); } else { printf(">\n"); } return 0; }
5 strncpy
拷贝 num 个字符从源字符串到目标空间。
如果源字符串的长度小于 num ,则拷贝完源字符串之后,在目标的后边追加 0 ,直到 num 个。
char* my_strncpy(char* destination, const char* source, size_t n) { char* cp = destination; int i = 0; while (*source && i < n) { *cp++ = *source++; i++; } for (int j = i; j < n; j++) { *cp++ = 0; } return destination; } int main() { char a[20] = "abcdefghi"; char b[] = "xyz"; my_strncpy(a, b, 6); printf("%s\n", a); return 0; }
6 strncat
将源文件的前num字符添加到目的地,再加上一个结束的空字符。
如果源字符串的长度小于num,则只复制到结束的空字符的内容。
char* my_strncat(char* dest, const char* scr, int n) { char* p = dest; assert(dest && scr); while (*p) { p++; } while (n--) { *p++ = *scr++; } *p = '\0'; return dest; } int main() { char arr[32] = "hello "; const char arr1[] = "word!"; char* str = my_strncat(arr, arr1, 20); printf("%s\n", str); return 0; }
7 strncmp
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
8 strstr
返回str1中第一次出现的str2的指针,如果str2不是str1的一部分,则返回一个空指针。
模拟实现:
char* my_strstr(const char* str1, const char* str2) { assert(str1 && str2); const char* s1 = str1; const char* p = str1; const char* s2 = str2; while (*p) { s1 = p; s2 = str2; while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2) { s1++; s2++; } if (*s2 == '\0') { return (char*)p; } p++; } return NULL; } int main() { char arr1[] = "abbbcde"; char arr2[] = "bcd"; char* ret = my_strstr(arr1, arr2); if (ret == NULL) { printf("子串不存在\n"); } else { printf("%s\n", ret); } return 0; }
9 strtok
sep参数是个字符串,定义了用作分隔符的字符集合。
第一个参数指定一个字符串,它包含了 0 个或者多个由 sep 字符串中一个或者多个分隔符分割的标
记。
strtok 函数找到 str 中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok 函数会改变被操作的字符串,所以在使用 strtok 函数切分的字符串一般都是临时拷贝的内容
并且可修改。)
strtok 函数的第一个参数不为 NULL ,函数将找到 str 中第一个标记, strtok 函数将保存它在字符串
中的位置。
strtok 函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。
如果字符串中不存在更多的标记,则返回 NULL 指针。
int main() //{ // const char* sep = "@."; // char email[] = "csdnboke@csdnboke.com.net"; // char cp[40] = { 0 }; // strcpy(cp, email); // // char* ret = NULL; // for (ret = strtok(cp, sep); // ret != NULL; // ret=strtok(NULL, sep)) // { // printf("%s\n", ret); // } // return 0; //}
10 memcpy
(其实在VS中,memcpy遇到重叠的时候也实现了memmove的功能,连函数现在都卷起来了!!!)
函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到 destination 的内存位置。
这个函数在遇到 '\0' 的时候并不会停下来。
如果 source 和 destination 有任何的重叠,复制的结果都是未定义的。
模拟实现:
void* my_memcpy(void* dest, const void* src, size_t sum) { assert(dest && src); void* ret = dest; while (sum--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } return ret; } int main() { int arr1[] = { 0,1,2,3,4,5,6,7,8,9 }; int arr2[10] = { 0 }; my_memcpy(arr2, arr1, 16); return 0; }
11 memmove
和 memcpy 的差别就是 memmove 函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用 memmove 函数处理。
模拟实现:
void* my_memmove(void* dst, const void* src, size_t count) { void* ret = dst; if (dst <= src || (char*)dst >= ((char*)src + count)) { while (count--) { *(char*)dst = *(char*)src; dst = (char*)dst + 1; src = (char*)src + 1; } } else { dst = (char*)dst + count - 1; src = (char*)src + count - 1; while (count--) { *(char*)dst = *(char*)src; dst = (char*)dst - 1; src = (char*)src - 1; } } return(ret); } int main() { int arr1[] = { 0,1,2,3,4,5,6,7,8,9 }; my_memmove(arr1 + 2, arr1, 16); return 0; }