函数简介
字符函数是处理单个字符的函数集合,它们常用于分析字符的属性、转换字符格式或进行字符编码操作。例如,charCodeAt
可以返回字符串中特定位置的字符编码,而 fromCharCode
则执行相反的操作,将编码转换为字符。此外,toUpperCase
和 toLowerCase
分别将字符转换为大写或小写形式。这些函数为文本处理提供了基础工具,使得对字符级别的操作成为可能。本文章将会较为系统性介绍子字符串函数。
求字符串长度
strlen
长度不受限制的字符串函数
strcpy
strcat
strcmp
长度受限制的字符串函数介绍
strncpy
strncat
strncmp
字符串查找
strstr
strtok
错误信息报告
strerror
字符操作
内存操作函数
memcpy
memmove
memset
memcmp
函数介绍
strlen
函数介绍
strlen函数,其作用是获取字符串的长度,需要注意的是:
strlen是初始化的长度,并非存放字符串的空间长度。
函数定义方式:
size_t strlen ( const char * str );
字符串的长度取决于strlen是否识别到null字符(也就是\0),stlren会返回在字符串中出现'\0'前面的字符个数,在使用这个函数时要注意这一点。
那我们来验证一下
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = { "abcdef" };
char arr2[] = { 'a','b','c','d' };
int ret1 = 0, ret2 = 0;
ret1 = strlen(arr1);
ret2 = strlen(arr2);
printf("%d\n%d", ret1, ret2);
return 0;
}
执行的结果如下:
我们可以看到,在地址中arr2字符数组的存储情况,可以知道,当strlen函数访问到 00 时,才停止访问,最后得到了33这个字符串长度。
其实,上面的代码存在一个小错误,不知道你们发现了没有呢?看看下面的代码会不会给你启发!
#include <stdio.h>
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
请问这个代码最后会输出什么结果?是不是最终会出来负数?
结果如下:
返回的结果str2>str1,为什么会出现这样的结果
size_a是strlen函数的返回值,size_a是无符号整形,所返回的整形是没有符号的,所以也无关乎是否存在小于0的情况了。
这也是为什么上面int类型的ret接受strlen的返回值会在编译器出现警告的原因、
模拟实现strlen
既然我们已经知道strlen的使用方式与功能,为了加深了解,我们自己来编写函数模拟实现strlen的功能:
模拟函数命名为my_strlen,首先我们应该对其进入函数的字符串进行判断,判断其是否合法,是否可以进入函数。
因为函数返回无符号整形,我们可以利用一个计数器count,当指针遍历整个字符串时,count自增,直到指针遇到'\0'时,count停止计数并返回其值,那么代码如下:
size_t my_strlen(const char* str)
{
size_t count = 0;
assert(str != NULL);
while (*str)
{
count++;
str++;
}
return count;
}
assert函数调用判断需要使用<assert.h>这个库函数,const修饰变量,表示其变量只读,不会被修改,代码更具有健硕性
那么,如果不使用临时变量,是否也能实现strlen的功能呢?我们可以用递归来描述:
size_t my_strlen( const char* str)
{
if (*str == '\0')
return 0;
else
return 1 + my_strlen(1 + str);
}
strcpy
函数介绍
在这里,我同样将cplusplus网站对于函数的解释奉上:
strcopy函数是将某字符串复制到指定的空间中(包括\0),其中返回类型为char*,两个参数类型为char* 的函数类型。
同样的,函数定义及使用方法:
char * strcat ( char * destination, const char * source );
其中strcopy函数需要指定的目标空间足够大,且空间必须可变以确保可以放置源字符串。
为什么需要空间可变呢?我们来看一下的代码用例:
#define _CRT_SECURE_NO_WARNINGS 1
# include<stdio.h>
# include<string.h>
int main()
{
char* p = "asdfghjkl";//此代码在C++格式下,是错误的
char arr[] = {" hello world "};
strcpy(p, arr);
printf("%s", p);
return 0;
}
最后编译出现的情况是:
指针p内指向的指向的是常量字符串,这是不允许修改的,所以此空间内无法复制数据进入!
模拟实现strcpy
如果我们要想实现此函数的功能,我们应该如何实现呢?
对于函数strcpy的功能我们已有所了解,那么通过对两者指向的地址空间进行操作,来完成''复制''这一操作
char* my_strcpy(char* dest, char* scre)
{
while (*scre != '\0')
{
*dest = *scre;
dest++;
scre++;
}
*dest = *scre;
}
当然,这个设计还可以改进:
char* my_strcpy(char* dest, char* scre)
{
char* ret=0;
ret = dest;
assert(dest != '\0');
assert(scre != '\0');
while (*dest++ = *scre++)
{
;
}
return ret;
}
NULL | #define NULL 本质为0,指针的初始化 |
\0 | /ddd的转移字符 本质也是0 |
0 | 数字0 |
NUL/nul | \0 |
'0' | 字符0 本质48 |
strcat
函数介绍
在此,我同样贴上这个函数的介绍:
此函数使用时:
模拟实现strcat
为了实现库函数strcat作用,我们使用两个指针,一个寻找源空间中存放的'\0',另一指针在此基础上,将数据拷贝过来。代码示例如下:
char* my_strcat(char* dest, const char* scre)
{
char* ret = 0;
ret = dest;
assert(dest && scre);
//查询目标空间'\0'
while (*dest)
{
dest++;
}
//拷贝数据
while (*dest++ = *scre++)
{
;
}
return ret;
}
strcmp
函数介绍
strcmp是对于两个字符串中的字符进行对比,比较其大小,而不是比较字符串的长度。
模拟实现strcmp
若要模拟实现其功能,通过传入的两个地址,对两个字符串进行比较,最后两个指针指向的字符,将其强制类型转换为整形,传回两个参数相减的值。
int my_strcmp(const char* s1, const char* s2)
{
while (*s1 == *s2)
{
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return *s1 - *s2;
strncpy strncat strncpy
上面介绍的函数,在使用时是长度不受限制的,寻找到NULL才停止,而strncpy strncat strncpy三个函数是长度受限制的字符串函数。
strncmp介绍
strncpy介绍
strncat介绍
C语言推出的三个函数,在传入参数是多规定一个无符号整形,意在限制函数操作的字符串长度。
当需要操作的数大于被操作数,会以'\0'来作填补。
strstr
函数介绍
strstr函数的作用是,两个字符串进行操作,返回字符串中在另外一个字符串首次出现的地址。
函数的使用方式如下:
char * strstr ( const char *str1, const char * str2);
函数模拟实现
想要模拟实现strstr的功能,需要考虑情况较多{"asdfg","aaasdfggg"},{"abbbcedf","bbc"}类似于这种字符串,只依靠两个指针无法完成此复杂功能,所以需要多个指针,代码如下:
char* my_strstr(const char* str1, const char*str2)
{
const char* cur = str1;
const char* s1 = NULL;
const char* s2 = NULL;
assert(str1 && str2);
if (*str2 == '\0')
{
return (char*)str1;
}
while (*cur)
{
s1 = cur;
s2 = str2;
while (*s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cur;
}
cur++;
}
return NULL;
}
在函数体内部在设置三个指针,一个指向被查找空间位置,另外两个分别指向两个传入的地址,与传入的指针一同进行操作。