看到很多面试都会要求你写一些简单的字符串操作函数,这些函数看起来挺简单的,但是自己写的时候就会发现不少的问题。所以我自己把大部分的字符串操作函数都写了一遍,然后用了个测试程序来测试自己写的函数与库函数是否相同。包括字符串长度函数、不受限制的字符串函数、受限制的字符串函数、字符串查找基础函数。下面直接上代码:
my_string.h 字符串操作函数头文件
#include <stddef.h> #define NUL '\0' #ifndef _MY_STRING_H_H #define _MY_STRING_H_H //字符串长度 size_t my_strlen(char const *dst); //不受限制的字符串函数 char *my_strcpy(char *dst, char const *src); char *my_strcat(char *dst, char const *src); int my_strcmp(char const *dst, char const *src); //受限制的字符串函数 char *my_strncpy(char *dst, char const *src, size_t len); char *my_strncat(char *dst, char const *src, size_t len); int my_strncmp(char const *dst, char const *src, size_t len); //字符串查找基础 char *my_strchr(char const *str, int ch); char *my_strpbrk(char const *str, char const *group); char *my_strstr(char const *s1, char const *s2); char *my_strrchr(char const *str, int ch); char *my_strrpbrk(char const *str, char const *group); char *my_strrstr(char const *s1, char const *s2); #endifmy_string.cpp 字符串操作函数源文件
#include "my_string.h" //字符串长度 size_t my_strlen(char const *dst) { size_t length = 0; while (*dst++ != NUL) length++; return length; } //不受限制的字符串函数 char *my_strcpy(char *dst, char const *src) { char *p = dst; while (*src != NUL) *dst++ = *src++; *dst = NUL; return p; } char *my_strcat(char *dst, char const *src) { char *p = dst; while (*dst++ != NUL); dst--; while (*src != NUL) *dst++ = *src++; *dst = NUL; return p; } int my_strcmp(char const *dst, char const *src) { while (*dst != NUL && *src != NUL) { if (*dst != *src) { if (*dst > *src) return 1; else return -1; } dst++; src++; } if (*dst == NUL && *src == NUL) return 0; else if (*dst == NUL && *src != NULL) return -1; else return 1; } //受限制的字符串函数 char *my_strncpy(char *dst, char const *src, size_t len) { char *p = dst; while (len != 0) { if (*src != NUL) *dst++ = *src++; else *dst++ = NUL; len--; } return p; } char *my_strncat(char *dst, char const *src, size_t len) { char *p = dst; while (*dst++ != NUL); dst--; while (len != 0) { if (*src == NUL) break; *dst++ = *src++; len--; } *dst = NUL; return p; } int my_strncmp(char const *dst, char const *src, size_t len) { while (len != 0) { if (*dst == NUL || *src == NUL) break; if (*dst != *src) { if (*dst > *src) return 1; else return -1; } dst++; src++; len--; } if (len == 0 || *dst == *src) return 0; else if (*dst == NUL && *src != NUL) return -1; else return 1; } //字符串查找基础 char *my_strchr(char const *str, int ch) { while (*str != NUL) { if (ch == *str) break; str++; } if (*str == NUL) return NULL; return (char *)str; } char *my_strpbrk(char const *str, char const *group) { char *p = NULL; while (*group++ != NUL) { p = my_strchr(str, *group); if (p != NULL) break; } return p; } char *my_strstr(char const *s1, char const *s2) { char *p; if (*s2 != NUL) { while (*s1 != NUL) { if (*s2 == *s1) { p = (char *)s1; while (*s2 != NUL) { if (*s1 != *s2) break; s1++; s2++; } if (*s2 == NUL) return p; s1 = p; } s1++; } return NULL; } return (char *)s1; } char *my_strrchr(char const *str, int ch) { char *last = NULL, *current = NULL; current = my_strchr(str, ch); while (current != NULL) { last = current; current = my_strchr(last + 1, ch); } return last; } char *my_strrstr(char const *s1, char const *s2) { char *last = NULL, *current = NULL; if (*s2 != NUL) { current = my_strstr(s1, s2); while (current != NULL) { last = current; current = my_strstr(last + 1, s2); } } return last; } char *my_strrpbrk(char const *str, char const *group) { char *last = NULL, *current = NULL; if (*group != NUL) { current = my_strpbrk(str, group); while (current != NULL) { last = current; current = my_strpbrk(last + 1, group); } } return last; }main.cpp 测试程序,主要是为了测试自己的函数与库函数结果是否一致
#include <stdio.h> #include <string.h> #include "my_string.h" //主函数 int main(void) { int len; char str_cpy1[13] = "abcdefghijkl", str_cpy2[13] = "abcdefghijkl"; char str_ncpy1[13] = "abcdefghijkl", str_ncpy2[13] = "abcdefghijkl"; char str_cat1[13] = "hello", str_cat2[13] = "hello"; char str_ncat1[13] = "hello", str_ncat2[13] = "hello"; char *pstr; char const *pcstr; printf("********字符串长度********\n"); len = my_strlen("test"); printf("my_strlen = %d\n", len); len = strlen("test"); printf("strlen = %d\n", len); printf("\n********不受限制的字符串函数********\n"); pstr = my_strcpy(str_cpy1, "hello world!"); printf("my_strcpy = %s\n", pstr); pstr = strcpy(str_cpy2, "hello world!"); printf("strcpy = %s\n", pstr); pstr = my_strcat(str_cat1, " world!"); printf("my_strcat = %s\n", pstr); pstr = strcat(str_cat2, " world!"); printf("strcat = %s\n", pstr); len = my_strcmp("test", "testa"); printf("my_strcmp = %d\n", len); len = strcmp("test", "testa"); printf("strcmp = %d\n", len); printf("\n********长度受限制的字符串函数********\n"); pstr = my_strncpy(str_ncpy1, "hello wor", 9); printf("my_strncpy = %s\n", pstr); pstr = strncpy(str_ncpy2, "hello wor", 9); printf("strncpy = %s\n", pstr); pstr = my_strncat(str_ncat1, " world!", 10); printf("my_strncat = %s\n", pstr); pstr = strncat(str_ncat2, " world", 10); printf("strncat = %s\n", pstr); len = my_strncmp("test", "testa", 5); printf("my_strncmp = %d\n", len); len = strncmp("test", "testa", 5); printf("strncmp = %d\n", len); printf("\n********字符串查找基础********\n"); pstr = my_strchr("hello world!", ' '); printf("my_strchr = %s\n", pstr); pcstr = strchr("hello world!", 'h'); printf("strchr = %s\n", pcstr); pstr = my_strpbrk("hello world!", "abcd"); printf("my_strpbrk = %s\n", pstr); pcstr = strpbrk("hello world!", "abcd"); printf("strpbrk = %s\n", pcstr); pstr = my_strstr("hello world!", "!"); printf("my_strstr = %s\n", pstr); pcstr = strstr("hello world!", "!"); printf("strstr = %s\n", pcstr); pstr = my_strrchr("hello world!", 'a'); printf("my_strrchr = %s\n", pstr); pcstr = strrchr("hello world!", 'a'); printf("strrchr = %s\n", pcstr); pstr = my_strrstr("hello world!", "!"); printf("my_strrstr = %s\n", pstr); pstr = my_strrpbrk("hello world!", "abcd"); printf("my_strrpbrk = %s\n", pstr); return 0; }自己现在写的函数只是为了实现和库函数相同的功能,不是要改进库函数的一些缺点,更多的是为了锻炼一下自己的基础功底。下面说明一下我在实现函数功能时注意的问题:
(1)strlen函数处理的是一个真正的字符串(以NUL结尾的字符串),找到NUL时结束,所以如果一个字符串没有以NUL结束的话,函数就会一直到内存中找到结束标志为止。
(2)strcpy和strcat函数在使用时,要考虑目标字符数组要能容纳所要承载的字符串。strcmp函数的返回值要注意,标准没有规定用于提示不相等的具体值。如果第1个字符串大于第2个字符串就返回一个大于0的值,如果第1个字符串小于第2个字符串就返回一个小于0的值,两个字符串相等时就返回0(这里我只用1、-1和0代替了一下)。
(3)strncpy函数,如果源字符串的长度小于len(待复制字符数),不够的用NUL补齐,如果源字符串的长度大于等于len,只复制len个。strncat与strncpy有几点不同,1.最多复制len个字符到目标字符数组后面。而且在结果字符串后面添加一个NUL字符; 2.不会像strlen一样对目标数组用NUL进行填充。
下面是我的测试结果图: