目录
strlen
size_t strlen ( const char * str );
字符串是以‘\0’作为结束标志,strlen函数范围的是‘\0’之前的字符个数
参数指向的字符串必须要以‘\0’结尾
strlen函数返回值为size_t(无符号的)
strlen函数的模拟实现
计数器:
size_t SimulationStrlen(const char* pa)
{
int count = 0;
assert(pa != NULL);
while (*pa != '\0')
{
count++;
pa++;
}
return count;
}
递归:
size_t SimulationStrlen(const char* pa)
{
assert(pa != NULL);
if (*pa == '\0')
{
return 0;
}
return SimulationStrlen(pa + 1) + 1;
}
指针-指针:
size_t SimulationStrlen(const char* pa)
{
assert(pa != NULL);
char* pb = pa;
while (*pb != '\0')
{
pb++;
}
return pb - pa;
}
strcpy
参数:指向要复制内容的目标数组的指针、源字符串
返回:destination空间的起始地址
char* strcpy(char *destination, const char *source);
源字符串必须以‘\0’结束
strcpy会把源字符串中的‘\0’拷贝过去
目标空间必须足够大(足以放下源字符串)
目标空间必须可变
strcpy的返回值类型的设置是为了实现链式访问
printf("%s", SimulationStrcpy(destination,source));
strcpy函数的模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>
char *SimulationStrcpy(char* dst, const char* src)
{
assert(dst != NULL);
assert(src != NULL);
//assert(dst && src)
char* cp = dst;
while (*cp++ = *src++);
return dst;
}
strcat
将源字符串的副本追加到目标字符串。目标中终止的空字符将被源的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符。
返回:destination空间的起始地址
char* strcat(char *destination, const char *source);
源字符串必须以‘\0’结尾
目标空间必须足够大
目标空间必须可修改
strcat函数的模拟实现
char* SimulationStrcat(char* dst, const char* src)
{
assert(dst && src);
char* cp = dst;
while (*cp)
{
cp++;
}
while (*cp++ = *src++);
return dst;
}
strcmp
将 C 字符串 str1 与 C 字符串 str2 进行比较。(比较字符的ASCII码值)
返回值 | 表明 |
---|---|
<0 | 第一个不匹配的字符在 ptr1 中的值低于 ptr2 中的值 |
0 | 两个字符串内容相等 |
>0 | 第一个不匹配的字符在 ptr1 中的值大于 ptr2 中的值 |
int strcmp ( const char * str1, const char * str2 );
strcmp函数的模拟实现
int SimulationStrcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
{
return 0;
}
str1++;
str2++;
}
if (*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
}
长度不受限与长度受限的字符串函数
长度不受限的字符串函数=
{
s
t
r
c
m
p
s
t
r
c
p
y
s
t
r
c
a
t
\left\{\begin{matrix} strcmp & & \\ strcpy & & \\ strcat & & \end{matrix}\right.
⎩⎨⎧strcmpstrcpystrcat
长度受限的字符串函数=
{
s
t
r
n
c
m
p
s
t
r
n
c
p
y
s
t
r
n
c
a
t
\left\{\begin{matrix} strncmp & & \\ strncpy & & \\ strncat & & \end{matrix}\right.
⎩⎨⎧strncmpstrncpystrncat
strncpy
char * strncpy ( char * destination, const char * source, size_t num );
拷贝nun个字符从源字符串到目标空间
如果源字符串的长度小于num,则拷贝完后,追加0(直到目标空间中字符长度等于num)
strncpy函数的模拟实现
#include<assert.h>
char* SimulationStrncpy(char* destination, const char* source, size_t num)
{
assert(destination && source);
char* ret = destination;
while (num)
{
*destination = *source;
destination++;
source++;
num--;
}
return ret;
}
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
比较到出现字符不一样或者一个字符串结束或者num个字符比较完
strncmp的模拟实现
#include<assert.h>
int SimulationStrcmp(const char* pa, const char* pb, size_t num)
{
assert(pa && pb);
for (int i = 0; i < num; i++)
{
if (*pa == *pb)
{
pa++;
pb++;
continue;
}
else
{
return *pa - *pb;
}
}
}
strncat
char* SimulationStrncat(char* destination, const char* source, int num)
{
assert(destination && source);
char *ret = destination;
while (*ret)
{
ret++;
}
while (num)
{
*ret = *source;
num--;
ret++;
source++;
}
return destination;
}
strstr
char * strstr ( const char *str1, const char * str2);
判断str2是否为str1的子串
如果是,返回指向 str1 中第一次出现的 str2 的指针;如果 str2 不是 str1 的一部分,则返回空指针。
strstr函数的模拟实现
char* SimulationStrstr(const char* p1, const char* p2)
{
assert(p1 && p2);//断言这俩指针不是空指针
const char* s1 = p1;
const char* s2 = p2;
const char* cur = p1;
while (*cur)
{
s1 = cur;
s2 = p2;
while ((*s1 != 0) && (*s2 != 0) && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cur;
}
if (*s1 == '\0')
{
return NULL;
}
cur++;
}
return NULL;
}
strtok
使用需引用头文件<string.h>
char * strtok ( char * str, const char * sep );
sep参数是个字符串,定义用作分隔符的字符集合
第一个参数指定了一个字符串,包含了0个或多个由sep字符串中一个或者多个分隔符分割的标记
strtok函数会找到str中的下一个,并将其用’\0’结尾,返回一个指向这个标记的指针(strtok函数会改变被操作的字符串,所以在使用strtok函数切分字符串一般都是用临时拷贝的内容并且可修改)
strtok函数的第一个参数不为NULL,函数将找到str中的第一个标记,strtok函数将保存它在字符串中的位置
strtok函数的第一个参数为NULL时,函数将在同一个字符串中被保存的位置开始,查找下一个标记
如果字符串中不存在更多的标记,则返回空指针
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "you@are#so$graceful%elegant^and&charming*tonight";
const char *sep = "@#$%^&*";
char buf[100] = { 0 };
strcpy(buf, arr);
char* str = NULL;
for (str = strtok(buf, sep); str != NULL; str = strtok(NULL, sep))
{
printf("%s ", str);
}
return 0;
}
strerror
char * strerror ( int errnum );
返回错误码所对应的错误信息
#include<stdio.h>
#include<string.h>
#include<limits.h>
#include<errno.h>
#include<stdlib.h>//使用perror所需引用
int main()
{
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
printf("\n");
int* p = (int*)malloc(INT_MAX);//向堆区申请内存,申请成功返回元素地址;不成功返回空指针
if (p == NULL)//申请不成功
{
printf("%s\n", strerror(errno));//全局变量error:错误码
perror("malloc");
return 1;
}
return 0;
}
字符分类函数
表格 | 如果参数符合下列条件就返回真 |
---|---|
iscntrl | 任何控制字符 |
isspace | 空白字符:“空格”、“换页\f”、换行“\n”、回车“\r”、制表符“\t”、垂直制表符“\v” |
isdigit | 十进制0~9 |
isxdighit | 十六进制数字,包括所有十进制数字,小写字母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 | 任何可打印字符,包括图形字符和空白字符 |
字符转换:tolower(int c)、toupper(int c) |
memcpy
void *memcpy(void *destination,const void *source, size_t num)
memcoy函数从source的位置开始向后复制num个字节的数据到destination的内存位置
遇到‘\0’并不会停下来
如果source和destination有任何的重叠,复制的结果都是未定义的
memcpy函数的模拟实现
void* SimulationMemcpy(void* destination, const void* source, size_t num)
{
assert(destination && source);
void* ret = destination;
while (num--)
{
*(char*)destination = *(char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
return ret;
}
int main()
{
int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr2[5] = { 0 };
SimulationMemcpy(arr2, arr1, 20);
for (int i = 0; i < 5; i++)
{
printf("%d", arr2[i]);
}
return 0;
}
memmove
void *memmove(void *destination, const void *source, size_t num);
memmove函数处理的源内存块和目标内存块是可以重叠的
如果destination在source之前,则从前向后拷
如果destination在source + num之前、在source之后,则从后向前拷
如果没有重叠,从后向前拷还是从前向后拷就无所谓啦
memmove函数的模拟实现
void* SimulationMemmove(void* destination, void* source, size_t num)
{
void* ret = destination;
if (destination > source && destination < (char*)source + num)
{
while (num--)
{
*(char*)destination = *(char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
}
else
{
while (num--)
{
*((char*)destination + num) = *((char*)source + num);
}
}
return ret;
}
memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
比较从prt1、prt2指针开始的num个字节
memset–内存设置
memset是以字节为单位来初始化单元的
void *memset(void *dest, int c, size_t count);