目录
1、*strlen
2、*strcpy
3、*strcat
4、*strcmp
5、strncpy
6、strncat
7、*strstr
8、strtok
9、*memcpy
10、*memmove
11、memcmp
*表示我们会进行模拟实现
我们借助MSDN来辅助学习
1、*strlen
清晰、简单明了。
作用是:获得一个字符串的长度。
函数模型:
size_t strlen( const char *string );
返回类型:size_t,参数类型:const char*
需要注意以下这么几点:
1、字符串已经'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')。
2、参数指向的字符串必须要以'\0'结束。
3、注意函数的返回值为size_t,是无符号的。(unsigned int)
对于strlen的模拟实现,方法有很多。
我们介绍三种:
第一种:
//计数器方式 size_t my_strlen(const char * str) { size_t count = 0; while(*str) { count++; str++; } return count; }
第二种:
//不能创建临时变量计数器 size_t my_strlen(const char * str) { if(*str == '\0') return 0; else return 1 + my_strlen(str+1); }
第三种:
//指针-指针的方式size_t my_strlen(char *s) { char *p = s; while(*p != ‘\0’ ) p++; return p-s; }
其实这三种方法都易于接收。还是比较简单的。
2、*strcpy
我想笔者已经不需要再去重复了,应该都能看懂。
注意以下几点:
源字符串必须以'\0'结束。
会将源字符串中的'\0'拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。
举个例子,比如:
char* strcpy(char* s1, const char*s2);
意思就是把s2拷贝到s1里去。然后返回s1。
以下是一个例子:
模拟实现:
char *my_strcpy(char *dest, const char*src) { char *ret = dest; assert(dest != NULL); assert(src != NULL); while((*dest++ = *src++)) { ; } return ret; }
3、*strcat
使用时注意以下几点:
源字符串必须以'\0'结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
模拟实现:
char* my_strcat(char* dest, const char* src) { char* ret = dest; assert(dest != NULL); assert(src != NULL); while (*dest) { dest++; } while ((*dest++ = *src++)) { ; } return ret; }
4、*strcmp
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
int my_strcmp(const char* src, const char* dst) { int ret = 0; assert(src != NULL); assert(dst != NULL); while (!(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst) { ++src; ++dst; } if (ret < 0) ret = -1; else if (ret > 0) ret = 1; return ret; }
很简单,很好理解。
5、strncpy
我们很容易发现,strcpy和strncpy就有一点不一样。那就是strncpy多了一个参数count。也可以就理解为就是n。也就是说n就是其要拷贝的个数。
其他的,和strcpy一样。如下图:
使用时注意:
拷贝count个字符从源字符串到目标空间。
如果源字符串的长度小于count,则拷贝完源字符串之后,在目标的后边追加0,直到count个。
6、strncat
和strcat也是差不多的。
需要注意的是,当strlen(strSource)+1
7、*strstr
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); } }
还是很简单的。
8、strtok
这个函数它没有那么单纯。
它 的目的主要是用来切割字符串的。
而切割的标准就是依照参数 strDelimit
几点描述:
strDelimit定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由strDelimit字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回NULL指针。
什么意思具体来说?
我们通过一个例子来 说明
在字符串 “,.- This, a sample string.”里,它会找到下一个 strDelimit中的字符。
第一个是“, 。- ”,第二个是“,”,那么其会标记上一个strDelimit中的后一个字符,即T,然后将","换成"\0",所以,运行完 pch = strtok (str," ,.-"); pch指向的是T,字符串为“,.- This\0 a sample string.”(后面的空格并不会去修改)
然后,进入while循环。strtok的第一个参数是NULL,那么其会从上一个标记处(就是上一次的分隔符号的位置)开始寻找,然后去找strDelimit里的分隔符号。直到找到,将其变为\0。
如果第一个参数为NULL并且找不到分隔符号的时候,就会返回空指针。
9、*memcpy
一般情况下,src都是0,如果不是0,用的如果 不恰当会引起“麻烦”,我们以后再说。
先来说这个函数的用法:
用法其实很简单:
需要注意的是:
函数memcpy从src的位置开始向后复制num个字节的数据到dest的内存位置。
这个函数在遇到'\0'的时候并不会停下来。
如果src和dest有任何的重叠,复制的结果都是未定义的。
如图,将myname复制到person.name里面
将person结构体复制到person_copy里面
后面第三个元素表示的是复制的字节数。
模拟实现:
注意,如果是结构体类型这种方法应该是不可以的。在这里我们只做简单的模拟实现。到了C++中我们会用类来去实现。
10、*memmove
它和memcpy的区别就是, memcpy的src和dest不可以有空间上的重叠。
但是memmove是可以有的。
我们在模拟实现的时候只需要加上一个条件就可以了。
void* 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); }
11、memcmp
这个很简单,类比于strcmp,主要是在后面有一个参数,它会从第count的位置开始比较。
strerror等略(不属于string.h里,本节不讲)