关于字符串函数的介绍
求字符串长度
strlen函数
用于计算字符串的长度的函数,需要使用的库函数是string.h
函数声明
size_t strlen(const char *str)
函数模拟实现
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* arr)
{
assert(arr);
int len = 0;
while (*arr)
{
len++;
arr++;
}
return len;
}
int main()
{
char* arr = "asdf";
printf("%d",my_strlen(arr));
return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
char* arr = "asdf";
printf("%d", strlen(arr));
return 0;
}
需要注意的是:计算的位置并不是随意的,他会计算到’\0’停止并且’\0’不计入字符总长度
请看这个代码,为什么会出现这中结果呢?你不是说计算到‘\0’结束吗,现在没有’\0’,可是为什么会出现相同的结果呢???
我们能看到内存中除了已经存好的字符之外全是’\0’,这就是为什么会是4,但是为什么会全是’\0’,因为这是c语言的规则,如果数组进行了初始化但是是未完全的初始化,那么其余的空间都将会被初始化为0
长度不受限制的字符串
strcpy()
使用的时候需要引用string.h头文件
字符串拷贝,以’\0’字符为结束标志,拷贝长度不受限制,使用时需要引用库函数—string.h
函数定义
char *strcpy(char *dest, const char *src)
函数模拟实现
char* my_strcpy(char* des, const char* src)
{
assert(des && src);
char* res = des;
while (*des++ = *src++);
return res;
}
在实现的时候一定要注意将源字符串中的’\0’拷贝进去,不然会出错
strcat
使用的时候需要引用string.h头文件
字符串连接函数
函数声明
char *strcat(char *dest, const char *src)
将后一个字符串放到前一个字符串的末尾,所以需要保证前一个字符串有’\0’结尾,并且写入的时候需要预留足够的空间
函数模拟实现
char* my_strcat(char* des, const char* arr)
{
assert(des && arr);
char* res = des;
while (*des)des++;
while (*des++ = *arr++);
return res;
}
特别需要强调的就是预留足够的空间
如果将代码写成指针的形式,那就错了!!!
因为指针没有足够的空间
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcat(char* des, const char* arr)
{
assert(des && arr);
char* res = des;
while (*des)des++;
while (*des++ = *arr++);
return res;
}
int main()
{
char* arr = "hello ";
char* arr2 = "world!";
my_strcat(arr, arr2);
puts(arr);
return 0;
}
strcmp
使用的时候需要引用string.h的头文件
字符串比较函数,比较到有结果或者结尾停止
函数声明
int strcmp ( const char * str1, const char * str2 );
此函数是使用字典序来进行比较大小的,如果a和b比较大小就是那a的ASCII码-b的ASCII码,然后进行返回(需要特殊说明的是,一般情况下返回的是不能于0的数)
函数模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strcmp(const char* arr1, const char* arr2)
{
assert(arr1 && arr2);
while (*arr1 || *arr2)
{
if (*arr1 != *arr2) return *arr1 - *arr2;
arr1++;
arr2++;
}
return 0;
}
字符长度受限
strncpy,strncat,strncmp
使用的时候需要引用string.h头文件
这些函数与上面的使用方法相似,这里我们之介绍一个—strncpy
函数声明
char * strncpy ( char * destination, const char * source, size_t num );
当num小于source的长度–>拷贝都最后
当num大于source的长度–>在结尾的时候加上’\0’
字符查找
strstr
函数声明
char *strstr(const char *haystack, const char *needle)
使用的时候需要引用string.h头文件
用于查找字符串中needle字符串第一次出现的位置,如果有—>返回位置
如果没有—>返回NULL指针
strtok
函数声明
char *strtok(char *str, const char *delim)
分割字符串函数,delim是分隔符的数组
int main()
{
char str[] = "asdf-asdfw.asdf-svs";
char delim[5]="-.";
//使用源字符串会改变源字符串,所以不能使用源字符串
char arr[100];
strcpy(arr,str);
//char* ch = strtok(str, delim);
for (char* ch = strtok(arr, delim);ch!=NULL;ch=strtok(NULL,delim))
{
puts(ch);
}
return 0;
}
第一个参数为NULL的时候,计算机中会有一个记录上一次到达的位置,会从这个位置开始向后搜索
strerror
使用的时候需要引用errno.h头文件
当调用库函数的时候发生错误时,错误信息会记录到errno的全局变量中
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
//当调用库函数发生错误,noerror会记录发生错误的原因
FILE* pf = fopen("en.txt", "r");
if (pf == NULL)
{
printf("%s\n", strerror(errno));
}
return 0;
}
内存操作函数
memcpy
使用需要引用string.h头文件
在字节的层面进行复制
函数声明
void *memcpy(void *str1, const void *str2, size_t n)
函数模拟实现
void* my_memcpy(void* des, const void* src, int n)
{
assert(des && src);
void* res = des;
for (int i = 0; i < n; i++)
{
*((char*)des + i) = *((char*)src + i);
}
return res;
}
当我们想将1,2,3,4,5复制成1,2,1,2,3
但是结果却和我们想的不一样
为了解决上面的覆盖的问题,就有了下面的函数
memmove
C 库函数 void memmove(void str1, const void str2, size_t n) 从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠***的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。
函数声明
void *memmove(void *str1, const void *str2, size_t n)
函数模拟实现
void* my_memmove(void* des, const void* src, int n)
{
assert(des && src);
void* res = des;
if (des < src)
{
for (int i = 0; i < n; i++)
{
*((char*)des + i) = *((char*)src + i);
}
}
else
{
while (n--)
{
*((char*)des + n) = *((char*)src + n);
}
}
return res;
}
这样子的话是不是就是对了了呢
多多练习