不受限制的字符串函数,比如说strcpy、strcmp等等,我们最常用的字符串函数都是不受限制的,只是通过寻找字符串参数结尾的NULL字节来判断它的长度。那么什么是受限制的字符串函数呢?通过下面的例子我们来一起详细了解一下
strcpy:
原型:char *strcpy( char *strDestination, const char *strSource );
这个函数把参数src字符串复制到dest参数中,在使用这个函数时需要注意,首先,必须保证目标字符数组的空间足以容纳需要复制的字符串,为什么呢?如果字符串比数组长,多余的字符仍然会被复制,这就导致它们会覆盖原先存储在数组后面的内存空间的值。其次,目标参数应该是可被修改的,所以它必须是个字符数组或者是一个指向动态分配内存的数组的指针。
1.strcpy模拟实现:
char *my_strcpy(char *dest, const char *src) { char *ret = dest; assert(src != NULL); assert(dest != NULL); while (*dest++ = *src++) { ; } return ret; }
strncpy: 把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。
上面是不受限制的字符串函数,那么为什么会有strncpy这样一类受限制的字符串函数呢?
就拿这两个函数来说,strcpy只是复制字符串,但不限制复制的数量,很容易造成缓冲溢出。strncpy要安全一些。strncpy能够选择一段字符输出,strcpy则不能。
下面是strncpy模拟实现:
char *my_strncpy(char *dest, const char *src, int n) { char *ret = dest; assert(dest); assert(src); while (n--) { *dest++ = *src++; } *dest = ‘\0‘; return ret; }
2.将两个字符串连接,我们可以使用strcat函数
函数原型:
char *strcat( char *strDestination, const char *strSource );
功能:
把src所指字符串添加到dest结尾处(覆盖dest结尾处的‘\0‘)。
说明:
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
char *my_strcat(char *dest, const char *src) { char *ret = dest; assert(src != NULL); assert(dest != NULL); while (*dest) { dest++; } while (*dest++ = *src++) { ; } return ret; }
strncat:
功能
把src所指字符串的前n个字符添加到dest所指字符串的结尾处,并覆盖dest所指字符串结尾的‘\0‘,从而实现字符串的连接。
说明
src和dest所指内存区域不可以重叠,并且dest必须有足够的空间来容纳src的字符串。
返回值
返回指向dest的指针。
char *my_strncat(char *dest, const char *src, int len) { char *ret = dest; assert(dest); assert(src); while (*dest) { dest++; } while (len--) { *dest = *src; dest++; src++; } *dest = ‘\0‘; return ret; }
3.strcmp函数:比较两个字符串。
有一个需要注意的地方是
当s1<s2时,返回为负数;
当s1=s2时,返回值= 0;
当s1>s2时,返回正数。
即:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇‘\0‘为止。
有的人以为返回值是1和-1,分别代表大于和小于,如果你也这样想,那就错了。ANSI标准规定,返回值为正数,负数,0 。而确切数值是依赖不同的C实现的。
int my_strcmp(const char *str1, const char *str2) { assert(str1); assert(str2); while (*str1 == *str2) { if (*str1 == ‘\0‘) return 0; str1++; str2++; } if (*str1 - *str2 > 0) return -1; else return 1; }
strncmp函数原型:
int strncmp ( const char * str1, const char * str2, size_t n );
参数str1, str2 为需要比较的两个字符串,n为要比较的字符的数目。
字符串大小的比较是以ASCII 码表上的顺序来决定,此顺序亦为字符的值。strncmp()首先将s1 第一个字符值减去s2 第一个字符值,若差值为0 则再继续比较下个字符,直到字符结束标志‘\0‘,若差值不为0,则将差值返回。例如字符串"Ac"和"ba"比较则会返回字符"A"(65)和‘b‘(98)的差值(-33)。注意:要比较的字符包括字符串结束标志‘\0‘,而且一旦遇到‘\0‘就结束比较,无论n是多少,不再继续比较后边的字符。
strncmp函数模拟实现:
int my_strncmp(const char *dest, const char*src, int count) { assert(dest); assert(src); while (count>0 && (*dest == *src)) { if (*dest == ‘\0‘) return 0; dest++; src++; count--; } return *dest - *src; }
4.为了在字符串中查找一个子串,我们可以使用strstr函数
函数原型:
char *strstr( const char *string, const char *strCharSet );
这个函数在s1中查找整个s2第一次出现的起始位置,并返回一个指向该位置的指针。如果s2没有完整地出现在s1的任何地方,函数将返回一个NULL指针。如果第二个参数是一个空字符串,函数就返回s1。
char *my_strstr(const char *str, const char *substr) { assert(str != NULL); assert(substr != NULL); char *s1 = (char *)str; char *s2 = (char *)substr; char *start = (char *)str; while (*start) { s1 = start; while ((*s1 != ‘\0‘) && (*s2 != ‘\0‘) && (*s1 == *s2)) { s1++; s2++; } if (*s2 == ‘\0‘) return start; s2 = (char *)substr; start++; } return NULL; }
strrstr:
标准库中并不存在这样的函数,当然,如果需要,也可以很容易实现
strrstr函数在字符串s1中查找s2最后出现的位置
char* my_strrstr(char const *s1, char const *s2) { char *last = NULL; //将指针初始化为已经找到的前一次匹配位置 char *current = NULL; assert(s1); assert(s2); if (*s2 ) //只有在第二个字符串不为空时才进行查找 { current = (char *)strstr(s1, s2);//s2在s1中第一次出现的位置 while (current != NULL) { //每次找到字符串时,让指针指向它的起始位置,然后查找该字符串下一个匹配位置 last = current; current = (char*)strstr(last + 1, s2); } } return last; }
5.在一个字符串中查找一个特定字符最容易的方法是使用strchr函数
这个函数比较简单,下面是模拟实现:
#include<stdio.h> #include<stdlib.h> char *my_strchr(const char*str, int ch) { while (*str) { if (*str == ch) return (char*)str; str++; } return NULL; } int main() { char *str = "happy"; char *ret = my_strchr(str, ‘a‘); if (ret != NULL) { printf("%c\n", *ret); } system("pause"); return 0; }
strrchr:
strrchr() 函数查找字符在指定字符串中从后面开始的第一次出现的位置,如果成功,则返回从该位置到字符串结尾的所有字符,如果失败,则返回 false。与之相对应的是strstr()函数,它查找字符串中首次出现指定字符的位置。
函数原型:
char *strrchr( const char *string, int c );
char *my_strrchr(char *str, char ch) { char *ptr = NULL; assert(str); while (*str) { if (*str == ch) ptr = str; str++; } if (ptr != 0) return ptr; return 0; } int main() { char ch = 0; char *ret = NULL; char *arr = "feabadc"; printf("请输入一个你要查找的字符:"); scanf_s("%c", &ch); ret = my_strrchr(arr, ch); printf("%s\n", *ret); system("pause"); return 0; }
当然,关于str这样的函数还有很多,这里模拟实现了一些经常用的函数,希望互相借鉴帮助。