目录
1. strlen
size_t strlen( const char *string );
作用:获取字符串的长度
解释:字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含'\0')
注意:
- 参数指向的字符串必须要以 '\0' 为结尾,否则会返回随机数
- 注意函数的返回值为size_t,是无符号的
模拟实现:
//计数方式
int my_strlen(const char* str)
{
assert(str);
int count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
//递归方式
int my_strlen(const char* str)
{
assert(str);
if(*str)
{
return 0;
}
else
{
return 1 + my_strlen(str + 1);
}
}
//指针-指针方式
int my_strlen(const char* str)
{
assert(str);
char* p = str;
while(*p)
{
p++;
}
return p - str
}
2. strcpy
char *strcpy( char *strDestination, const char *strSource );
作用:复制字符串
解释:源字符串必须以 '\0' 结束,也会将 '\0' 拷贝到目标空间
注意:
- 目标空间必须足够大,确保能够存放源字符串
- 目标空间必须可变
模拟实现:
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}
3. strcat
char * strcat ( char * destination, const char * source );
作用:追加字符串
解释:在源字符串后追加目标字符串
注意:
- 源字符串必须以 '\0' 结束
- 目标空间必须足够大
- 目标空间必须可以修改
模拟实现:
char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while(*dest)
{
dest++; //先找到源字符串的 '\0'
}
while((*dest++ = *src++))
{
; //进行追加
}
return ret;
}
4. strcmp
int strcmp ( const char * str1, const char * str2 );
作用:比较两个字符串
解释:strcmp()函数首先将str1字符串的第一个字符的ACSII值减去str2第一个字符的ACSII值(自左向右逐个字符相比,直到出现不同的字符或遇'\0'为止)若差值为零则继续比较下去;若差值不为零,则返回差值
注意:
- strcmp可用于比较两个字符串常量或比较数组和字符串常量,不能比较数字等其他形式的参数。
模拟实现:
//第一个字符串大于第二个字符串,则返回大于0的数字
//第一个字符串等于第二个字符串,则返回0
//第一个字符串小于第二个字符串,则返回小于0的数字
int my_strcmp (const char * src, const char * dst)
{
int ret = 0 ;
assert(src != NULL);
assert(dest != 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
char * strncpy ( char * destination, const char * source, size_t num );
作用:拷贝num个字符从源字符串到目标空间
解释:和strcpy类似
注意:
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
6. strncat
char * strncat ( char * destination, const char * source, size_t num );
作用:追加num个字符从源字符串到目标空间后
解释:和strcat类似
注意:
- 如果源中 C 字符串的长度小于 num,则只有终止之前的内容复制空字符
7. strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
作用:比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完
解释:和strcmp类似
注意:
8. strstr
char * strstr ( const char *str1, const char * str2);
作用:查找子字符串
解释:查找 str1 中是否有 str2
注意:
模拟实现:
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);
}
9. strerror
char * strerror ( int errnum );
作用:获取系统错误消息 (strerror) 或打印用户提供的错误消息 (_strerror)。
解释:返回错误码,所对应的错误信息。
注意:
字符分类函数:
函数 如果它的参数符合下列条件就返回真
- iscntrl 任何控制字符
- isspace 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车'\r',制表符'\t',或垂直制表符'\v'
- isdigit 十进制数字0~9
- isxdigit 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
- islower 小写字母a~z
- isupper 大写字母A~Z
- isalpha 字母a~z或A~Z
- isalnum 字母或数字a~z,A~Z或0~9
- ispunct 标点符号,任何不属于数字或字母的图像字符(可打印符号)
- isgraph 任何图像字符
字符转换:
- int tolower ( int c ); //大写字符转小写字符
- int toupper ( int c ); //小写字符转大写字符
##案例##:
#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main ()
{
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL)
{
printf ("Error opening file unexist.ent: %s\n",strerror(errno));
}
//errno: Last error number
return 0;
}
10. memcpy
void * memcpy ( void * destination, const void * source, size_t num );
作用:拷贝任何数据类型的对象,并指定拷贝的数据长度
解释:由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内
注意:
- source和destination所指内存区域不能重叠,函数返回指向destin的指针。
- 与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。
-
如果目标数组destination本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。
-
如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。
-
source和destination都不一定是数组,任意的可读写的空间均可。
模拟实现:
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
/*
* copy from lower addresses to higher addresses
*/
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
11. memmove
void *memmove( void *dest, const void *src, size_t count );
作用:将src移动到dest。
解释:和memcpy比较,他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候, memmove 保证拷贝的结果是正确的, memcpy 不保证拷贝的结果的正确。
注意:
- 如果要去实现memmove函数的话,需要考虑 src 在 dest 前面和后面两种情况是否一样,并如何实现。
模拟实现:
void* my_memmove(void *det, const void *src, int num)
{
assert(det && src);
char* p1 = (char*)det;
char* p2 = (char*)src;
if(det < src)
{
while(num--)
{
*p1 = *p2;
p1++;
p2++;
}
}
else
{
p1 += num;
p2 += num;
while(num--)
{
*p1 = *p2;
p1--;
p2--;
}
}
return p1;
}
12. memcmp
int memcmp( const void *buf1, const void *buf2, size_t count );
作用:比较两个指针后count个字节
解释:比较从buf1和buf2指针开始的count个字节 ( 和strncmp类似 )
注意:
- 对于memcmp(),如果两个字符串相同而且count大于字符串长度的话,memcmp不会在\0处停下来,会继续比较\0后面的内存单元,直到_res不为零或者达到count次数。
##案例##:
//当buf1<buf2时,返回值<0
//当buf1=buf2时,返回值=0
//当buf1>buf2时,返回值>0
#include <stdio.h>
#include <string.h>
int main ()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
if (n>0)
{
printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
}
else if (n<0)
{
printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
}
else
{
printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
}
return 0;
}