字符函数
strlen()
求字符串长度
- 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
- 参数指向的字符串必须要以 '\0' 结束。
- 注意函数的返回值为size_t,是无符号的( 易错 )
- 学会strlen函数的模拟实现
//strlen() 模拟
// 求字符串长度,必须以'\0'结尾
//size_t strlen( const char* str);
size_t my_strlen(const char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
strcpy()
拷贝字符串
- 源字符串必须以 '\0' 结束。
- 会将源字符串中的 '\0' 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
- 学会模拟实现
//strcpy() 模拟
// 字符串拷贝
//char* strcpy(char *destination,const char *source);
char* my_strcpy(char *destination, const char* source)
{
assert(destination != NULL && source != NULL);
char* strdes = destination;
const char* strsou = source;
while (*strsou != '\0')
{
*strdes = *strsou;
strdes++;
strsou++;
}
*strdes = '\0';
return destination;
}
strcat()
连接字符串
- 源字符串必须以 '\0' 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
- 字符串自己给自己追加,如何?
//strcat() 模拟
// 连接两个字符串,destination必须要有足够的空间
//char* strcat(char *destination,const char *source);
char* my_strcat(char* destination, const char* source)
{
assert(destination != NULL && source != NULL && destination!=source);
char* strdes = destination;
const char* strsou = source;
while (*strdes != '\0')
{
strdes++;
}
while (*strsou != '\0')
{
*strdes = *strsou;
strdes++;
strsou++;
}
*strdes = '\0';
return destination;
}
strcmp()
比较字符串
- 标准规定:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
//strcmp() 模拟
// 两个字符串比较
//int strcmp(const char*str1,const char*str2);
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 != NULL && str2 != NULL);
while (*str1!='\0')
{
if (*str1 == *str2)
{
str1++;
str2++;
}
else
break;
}
return *str1 - *str2;
}
strstr()
查找字符串1中,第一个出现字符串2的位置,返回其指针
//strstr() 模拟
// 查找str1中第一个出现str2字符串的位置
//char * strstr ( const char *, const char * );
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 != NULL && str2 != NULL);
const char* s1 = str1;
const char* s2 = str2;
while (*s1 != '\0'&& *s2 != '\0')
{
if (*s1 == *s2)
{
s2++;
s1++;
}
else
{
s2 = str2;
s1++;
}
}
if (*s2 == '\0')
return (s1 - strlen(str2));
else
return NULL;
}
strncpy()
- 拷贝num个字符从源字符串到目标空间。
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
char* my_strncpy( char *strDest, const char *strSource, size_t count )
{
assert(strDest!=NULL && strSource!=NULL);
char *pDest = strDest;
int str_len = strlen(strSource);
for(int i=0; i<count; ++i)
{
if(i < str_len)
*pDest++ = *strSource++;
else
*pDest++ = '\0';
}
return strDest;
}
strncat()
char* my_strncat( char *strDest, const char *strSource, size_t count )
{
assert(strDest!=NULL && strSource!=NULL);
char *pDest = strDest;
while(*pDest != '\0')
pDest++;
int str_len = strlen(strSource);
for(int i=0; i<str_len&&i<count; ++i)
{
*pDest++ = *strSource++;
}
*pDest = '\0';
return strDest;
}
strncmp()
int my_strncmp( const char *string1, const char *string2, size_t count )
{
assert(string1!=NULL && string2!=NULL);
int res = 0;
while(count-- != 0)
{
res = *string1 - *string2;
if(res != 0)
break;
string1++;
string2++;
}
if(res > 0)
res = 1;
else if(res < 0)
res = -1;
return res;
}
strtok()
- sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改
- 变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
//char *strtok( char *strToken, const char *strDelimit );
int main()
{
//char *p = "zhangsan\0qq.com";
char p[] = "zhangsan@163.com";
const char* sep = "@.";
strtok(p, sep);
char *res = strtok(NULL, sep);
printf("%s\n", res);
}
strerror()
返回错误码,所对应的错误信息。
#include<stdio.h>
#incldue<errno.h>
//errno
void main()
{
FILE *fp = fopen("Test1.txt", "r");
if(fp == NULL)
{
printf("errno = %d\n", errno);
printf("err msg = %s\n", strerror(errno));
printf("打开文件失败.\n");
return;
}
printf("打开文件成功.\n");
fclose(fp);
}
内存函数
memcpy()
拷贝source中的n个字节到destination()
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 '\0' 的时候并不会停下来。
- 如果source和destination有任何的重叠,复制的结果都是未定义的。
//memcpy() 模拟
// 复制source中n个字节的内容到destination
// 如果source和destination有任何的重叠,复制的结果都是未定义的。
//void * memcpy ( void * destination, const void * source, size_t num );
void* my_memcpy(void* destination, const void* source, size_t num)
{
assert(destination != NULL && source != NULL);
char* strdes = (char*)destination;
char* strsou = (char*)source;
while (num--)
{
*strdes = *strsou;
strdes++;
strsou++;
}
return destination;
}
memmove()
拷贝source中的n个字节到destination()
- 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
- 这个函数在遇到 '\0' 的时候并不会停下来。
- source和destination可以存在重叠。
//memmove() 模拟
//复制source中n个字节的内容到destination
//如果source和destination有任何的重叠,复制的结果不会出错。
//void * memmove ( void * destination, const void * source, size_t num );
void* my_memmove(void* destination, const void* source, size_t num)
{
assert(destination != NULL && source != NULL);
char* strdes = (char*)destination;
char* strsou = (char*)source;
//destination在后,source在前,发生空间重叠,倒着复制
if (strdes > strsou)
{
strdes = strdes + num - 1;
strsou = strsou + num - 1;
while (num--)
{
*strdes = *strsou;
strdes--;
strsou--;
}
}
else
{
while (num--)
{
*strdes = *strsou;
strdes++;
strsou++;
}
}
return destination;
}
memcpy()
比较从ptr1和ptr2指针开始的num个字节
int my_memcmp( const void *buf1, const void *buf2, size_t count )
{
assert(buf1!=NULL && buf2!=NULL);
const char *pf1 = (const char*)buf1;
const char *pf2 = (const char *)buf2;
int res = 0;
while(count-- != 0)
{
res = *pf1 - *pf2;
if(res != 0)
break;
pf1++;
pf2++;
}
return res;
}
memset()
初始化dest指向的地址及其后n个字节;
void* my_memset( void *dest, int c, size_t count )
{
assert(dest != NULL);
char *pDest = (char *)dest;
while(count-- != 0)
{
*pDest++ = c;
}
return dest;
}