一.字符串函数(使用需包含头文件 #include <string.h>)
1.长度不受限制的字符串函数
1>strlen
1.原型:size_t strlen ( const char * str );
strlen - C++ Reference (cplusplus.com)
2.注意事项:1>strlen函数只计算字符串中第一个\0前字符的个数
2>函数返回类型是无符号整形
3>参数指向的字符串必须以\0结尾
3.模拟实现
1.计数器法
int my_strlen(const char * str)
{
int count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
2.递归法
int my_strlen(const char * str)
{
if(*str == '\0')
return 0;
else
return 1+my_strlen(str+1);
}
3.指针法
int my_strlen(const char *s)
{
char *p = s;
while(*p != ‘\0’ )
p++;
return p-s;
}
4.sizeof与strlen的区别
sizeof | strlen |
1.是操作符 | 1.是库函数 |
2.计算的是操作数在内存中所占字节的大小 | 2.计算的是\0之前字符的个数 |
3.不关心内存中存的是什么 | 3.关心内存中是否存在\0 |
2>strcmp
1.原型:int strcmp ( const char * str1, const char * str2 );
strcmp - C++ Reference (cplusplus.com)
2.模拟实现:
int my_strcmp (const char * str1, const char * str2)
{
int ret =0;
assert(str1 != NULL);
assert(str2 != NULL);
while(*str1==*str2)
{
if(*str1=='\0')
return 0;
str1++;
str2++;
}
return str1-str2;
}
3>strcpy
1.原型:char * strcpy ( char * destination, const char * source );
strcpy - C++ Reference (cplusplus.com)
2.注意事项:1>原字符串必须以\0结尾,且\0会被拷贝进目标字符串中
2>目标字符串必须可修改,不能是字符串常量
3.模拟实现:
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}
4>strcat
1.原型:char * strcat ( char * destination, const char * source );
strcat - C++ Reference (cplusplus.com)
2.注意事项:1>原字符串必须以\0结尾,目标字符串也必须以\0结尾以开始保证追加的位置
2>目标字符串必须可修改,不能是常量字符串
3>字符串不能自己给自己追加,这时会因找不到\0而陷入死循环,导致程序崩溃
3.模拟实现:
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;
}
*5>strstr
1.原型:char * strstr ( const char * str1, const char * str2 );
strstr - C++ Reference (cplusplus.com)
2.用途:在目标字符串中找原字符串是否出现,若出现返回第一次出现的地址,否则返回NULL
3.思路:
4.模拟实现:
char* my_strstr(const char* dest, const char* src)
{
assert(dest);
char* str1 = dest;
char* str2 = src;
char* tmp = dest;
if (*str2 == '\0')
return (char*)dest;
while (*tmp)
{
str1 = tmp;
str2 = src;
if (*str1 == *str2)
{
while (*str1 && *str2 && *str1 == *str2)
{
str1++;
str2++;
}
if (*str2 == '\0')
return tmp;
}
tmp++;
}
return NULL;
}
*6>strtok
1.原型:char * strtok ( char * str, const char * delimiters );
strtok - C++ Reference (cplusplus.com)
2.用途:将由间隔符组成的字符串分割开来
3.注意事项:1>delimiters是代表分隔符的集合数组的地址
2>在字符串中分割开一处后,会在其后自动补\0,并且下一次从该位置向后继续 查找
*7>strerror
1.原型:char * strerror ( int errnum );
strerror - C++ Reference (cplusplus.com)
2.用途:把参数部分错误码对应的错误信息的字符串地址返回来
2.长度受限制的字符串函数(使用需包含头文件 #include <string.h>)
1>strncmp
1.原型:int strncmp ( const char * str1, const char * str2, size_t num );
strncmp - C++ Reference (cplusplus.com)
2.模拟实现:
int my_strncmp(const char* str1, const char* str2,int num)
{
assert(str1 && str2);
while (*str1 == *str2 && num && *str1 && *str2)
{
str1++;
str2++;
num--;
}
if (num == 0)
return 0;
else
return str1-str2;
}
2>strncpy
1.原型:char * strncpy ( char * destination, const char * source, size_t num );
strncpy - C++ Reference (cplusplus.com)
2.注意事项:若原字符串的长度小于num,在拷贝完原字符串后,在目标字符串后追加0直至 num个
3.模拟实现:
char* my_strncpy(char* dest, const char* src, int num)
{
assert(dest && src);
char* ret = dest;
while (num--)
{
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return ret;
}
3>strncat
1.原型:char * strncat ( char * destination, const char * source, size_t num );
strncat - C++ Reference (cplusplus.com)
2.注意事项:1>在目标字符串后连接num个原字符串中内容后,会在结尾补\0
2>若原字符串的长度小于num,在追加完原字符串后不再补0直至num个
3.模拟实现:
char* my_strncat(char* dest, const char* src, int num)
{
assert(dest && src);
char* ret = dest;
while (*dest)
{
dest++;
}
while (num--)
{
*dest = *src;
dest++;
src++;
}
*dest='\0';
return ret;
}
二.字符函数
注:此部分内容若能应用在以后的编程,可以在某些程度上简化代码
1.字符分类函数:使用需包含头文件 #include <ctype.h>
函数 | 如果参数符合条件返回真 |
iscntrl | 任何控制字符 |
isspace | 空白字符:“ ”,换页"\f",换行:"\n",回车:"\r",制表符:"\t",垂直制表符:"\v" |
isdigit | 十进制数:0-9 |
isxdigit | 十六进制数:0-9,a-f,A-F |
islower | 小写字母:a-z |
isupper | 大写字母:A-Z |
isalpha | 字母:A-Z或a-z |
isalnum | 字母或数字:a-z,A-Z,0-9 |
ispunct | 标点符号 |
isgraph | 任何图形字符 |
isprint | 任何可打印的字符,包括图形字符和空白字符 |
2.字符转换函数
例:
#include <stdio.h>
#include <ctype.h>
int main()
{
char str[] = "I am a student";
int i = 0;
char c;
//将字符串中小写字母改成大写字母
while (str[i])
{
c = str[i];
if (islower(c))
c = toupper(c);
putchar(c);
i++;
}
return 0;
}
三.内存函数
注:字符串函数只能用于字符串,而内存函数适用于所有类型的数组。
这里可以参考为什么要引入qsort来进行排序的原因
1.memcpy
1>原型:void * memcpy ( void * destination, const void * source, size_t num );
memcpy - C++ Reference (cplusplus.com)
2>用途:将一个数组中的内容拷贝到另一个数组
3>局限性:对于两个有重叠部分的数组,用此函数可能会出错,这时往往采用memmove函数
4>模拟实现:
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
2.memmove
1>原型:void * memmove ( void * destination, const void * source, size_t num );
memmove - C++ Reference (cplusplus.com)
2>用途:在两数组用重叠情况下,实现将一个数组内容拷贝到另一个数组中
3>思路:
4>模拟实现:
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
//当目的地的地址在高地址处,源头地址在低地址处时,采用从后向前拷贝的方法
//将dest强转为char*,一个字节一个字节的拷贝
if (dest>src)
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
//当目的地地址在低地址处,源头地址在高地址处时,采用从前向后拷贝的方法
else
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
}
*3.memset
1>原型:void * memset ( void * ptr, int value, size_t num );
memset - C++ Reference (cplusplus.com)
2>用途:将内存中的值以字节为单位设置成自己想要的内容
*4.memcmp
1>原型:int memcmp ( const void * ptr1, const void * ptr2, size_t num );
memcmp - C++ Reference (cplusplus.com)
2>用途:从p1,p2指向的位置开始,比较其后num个字节