目录:
求字符串长度 strlen
长度不受限制的字符串函数 strcpy strcat strcmp
长度受限制的字符串函数 strncpy strncat strncmp
字符串查找 strstr strtok
错误信息报告 strerror
字符操作
前言:大家也可以通过cplusplus这个网站搜索C语言中的字符函数
一.strlen
统计字符串中\0之前字符个数

参数为char *,返回类型为无符号整型
#include <assert.h>
//模拟实现strlen
size_t my_strlen(const char* str)
{
assert(str);//断言,确保str不是空
const char* start = str;
const char* end = str;
while (*end != '\0')
{
end++;
}
return end - start;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);//测试
printf("%d\n", len);
return 0;
}
二.长度不受限制的字符串函数 strcpy strcat strcmp
长度不受限制指该类函数只考虑\0,不考虑长度
strcpy

注意:拷贝时源字符串必须包含\0,以\0结尾,会将\0拷贝到目标字符串,目标字符串足够大,且可变
char* my_strcpy(char* dest, const char* src)//模拟实现strcpy
{
assert(dest);
assert(src);
char* ret = dest;
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "abc";
char arr2[] = "hello bit";
printf("%s\n", my_strcpy(arr1, arr2));
return 0;
}
strcat

字符追加函数,不能在字符串后追加其本身。
char* my_strcat(char* dest, const char*src)
{
//1.找目标空间中的\0
char* cur = dest;
while (*cur)
{
cur++;
}
//2.拷贝源头数据到\0之后的空间
while (*cur++ = *src++)
{
;
}
return dest;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world";
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
strcmp
比较字符串函数,比较的是对应位置上字符的ascii码大小,不是长度。

int ret = my_strcmp(arr1, arr2);//strcmp用法
if (ret < 0)
printf("arr1<arr2\n");
else if(ret>0)
printf("arr1>arr2\n");
else
printf("arr1==arr2\n");//ret=0表示arr1=arr2
模拟实现strcmp
int my_strcmp(const char* s1, const char* s2)
{
assert(s1 && s2);
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0;
}
s1++;
s2++;
}
return *s1 - *s2;
}

三.长度受限制的字符串函数 strncpy strncat strncmp
strncpy

num指要拷贝的字符个数。
使用示范:
int main()
{
char arr1[20] = "abcdefghi";
char arr2[] = "xxxx";
strncpy(arr1, arr2, 3);
printf("%s\n", arr1);
return 0;
}
//结果是:xxxdefghi
大家也可下载Everything,在该软件中找到c语言实现字符串函数的代码


char * __cdecl strncpy (
char * dest,
const char * source,
size_t count
)
{
char *start = dest;
while (count && (*dest++ = *source++) != '\0') /* copy string */
count--;
if (count) /* pad out with zeroes */
while (--count)
*dest++ = '\0';
return(start);
}
strncat

在destination后追加num个source的字符,如果自己给自己追加字符串本身,应该用此函数
使用示范:
int main()
{
char arr1[20] = "abc";
char arr2[] = "xxxx";
strncat(arr1, arr1,3 );
printf("%s\n", arr1);
return 0;
}//结果为abcabc
模拟实现:
char * __cdecl strncat (
char * front,
const char * back,
size_t count
)
{
char *start = front;
while (*front++)
;
front--;
while (count--)
if ((*front++ = *back++) == 0)
return(start);
*front = '\0';
return(start);
}
strncmp

如果str1中包括str2则返回大于0的数,否则返回小于0的数
使用示范:
int main()
{
int ret = strncmp("abcdef", "abc", 4);
printf("%d\n", ret);
return 0;
}
模拟实现:
int __cdecl strncmp
(
const char *first,
const char *last,
size_t count
)
{
size_t x = 0;
if (!count)
{
return 0;
}
if( count >= 4 )
{
/* unroll by four */
for (; x < count-4; x+=4)
{
first+=4;
last +=4;
if (*(first-4) == 0 || *(first-4) != *(last-4))
{
return(*(unsigned char *)(first-4) - *(unsigned char *)(last-4));
}
if (*(first-3) == 0 || *(first-3) != *(last-3))
{
return(*(unsigned char *)(first-3) - *(unsigned char *)(last-3));
}
if (*(first-2) == 0 || *(first-2) != *(last-2))
{
return(*(unsigned char *)(first-2) - *(unsigned char *)(last-2));
}
if (*(first-1) == 0 || *(first-1) != *(last-1))
{
return(*(unsigned char *)(first-1) - *(unsigned char *)(last-1));
}
}
}
/* residual loop */
for (; x < count; x++)
{
if (*first == 0 || *first != *last)
{
return(*(unsigned char *)first - *(unsigned char *)last);
}
first+=1;
last+=1;
}
return 0;
}
四.字符串查找 strstr strtok
strstr

意思是返回一个指向str1中首次出现str2的指针,如果str2不是str1的一部分则返回一个空指针
使用示范:
int main()
{
char arr1[] = "abcdefabcdef";
char arr2[] = "cde";
char* p = strstr(arr1, arr2);
if (p == NULL)
{
printf("不存在\n");
}
else
{
printf("%s\n", p);
}
return 0;
}//结果是cdefabcdef
模拟实现
//暴力求解
char* my_strstr(const char* str1, const char* str2)
{
const char* s1 = str1;
const char* s2 = str2;
const char* p = str1;
if (*str2 == '\0')
{
return str1;
}
while (*p)
{
s1 = p;
s2 = str2;
while (*s1!='\0' && *s2!='\0' && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)p;//找到了
}
p++;
}
return NULL;//找不到子串
}
strtok

第一个参数是被某些字符分割的字符串,第二个参数delimiters是分割字符串的字符集合。
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
使用示范:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "https://blog.youkuaiyun.com/qq_62888595/";
const char* p = "/.";
char* str = NULL;
for (str=strtok(arr, p); str!=NULL; str=strtok(NULL, p))
{
printf("%s\n", str);
}
return 0;
}

五.错误信息报告 strerror

errnum是c语言错误信息对应的错误码

使用示范:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
//strerror
//把错误码转换成错误信息
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("");//打印的依然是errno变量中错误码对应的错误信息,perror=printf+strerror
//printf("%s\n", strerror(errno));
return 1;
}
//读文件
fclose(pf);
pf = NULL;
return 0;
}

六.字符操作
下列is函数头文件
#include <ctype.h>
函数 如果他的参数符合下列条件就返回真(也就是非0的数)
iscntrl 任何控制字符
isspace 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'
isdigit 十进制数字 0~9
isxdigit 十六进制数字,包括所有十进制数字,小写字母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 任何可打印字符,包括图形字符和空白字符
以下两个函数头文件:
#include <string.h>
int tolower(int c)大写转小写
int toupper(int c)小写转大写
使用示范:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
/* tolower example */
#include <stdio.h>
#include <ctype.h>
int main()
{
int i = 0;
char str[] = "Test String.\n";
char c;
while (str[i])
{
c = str[i];
putchar(tolower(c));
i++;
}
return 0;
}

如有错误欢迎斧正,如有疑惑可私信或评论,我会尽力回答,一起加油吧!