目录
求字符串长度
strlen
示例
模拟实现strlen
长度不受限制的字符串函数
strcpy
示例
模拟实现strcpy
strcat
模拟实现strcat
strcmp
示例
模拟实现strcmp
长度受限制的字符串函数介绍
strncpy
示例
模拟实现strncpy
strncat
示例
模拟实现strncat
strncmp
示例
模拟实现strncmp
字符串查找
strstr
示例
模拟实现strstr
strtok
示例
模拟实现strtok
错误信息报告
strerror
示例
字符分类函数
size_t strlen ( const char * str );
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
#include
size_t my_strlen(const char* str) {
size_t count = 0;
while (str[count] != '\0') {
count++;
}
return count;
}
int main() {
const char* str = "Hello, World!";
size_t length = my_strlen(str);
printf("字符串的长度为: %zu\n", length);
return 0;
}
copy字符串到目标字符串,应该使用strcpy
char* strcpy(char * destination, const char * source)
char name[20] = {0};
strcpy(name, "zhang\0hai");
printf("%s\n", name); // zhang
char *my_strcpy(char *dest, const char *str)
{
assert(dest && str);
char *res = dest;
while (*dest++ = *str++)
{
}
return res;
}
char arr1[] = "abc\0def";
char arr2[] = {0};
my_strcpy(arr2, arr1);
printf("%s\n", arr2); // abc
拼接字符串到目标字符串,应该使用strcat
char * strcat ( char * destination , const char * source );
/* 同样 strcpy同strcpy大概一致,需保持足够大的空间,遇\0停止 */
char arr1[] = "demo";
// strcat(arr1, "emo");
// printf("%s", arr1); // demoemo
strcat(arr1, "em\0o");
printf("%s", arr1); // demoem
char *my_strcat(char *dest, const char *str)
{
char *res = dest;
assert(dest && str);
while (*dest != '\0') // 找到目标空间的末尾\0
{
dest++;
}
while (*dest++ = *str++)
{
;
}
return res;
}
char arr3[20] = "hello ";
my_strcat(arr3, "world");
printf("%s\n", arr3); // hello world
两个字符串比较相等,应该使用strcmp
int strcmp ( const char * str1 , const char * str2 );
比较是基于字符的 ASCII 值来进行的。strcmp() 会逐个比较两个字符串对应位置上的字符的 ASCII 值,并按照以下规则返回结果:
当找到不同的字符时,根据其 ASCII 值的大小关系决定比较结果。较小的字符对应的字符串被认为是较小的。如果一个字符串是另一个字符串的前缀,则较短的字符串被认为是较小的。
strcmp() 是区分大小写的。大写字母的 ASCII 值小于小写字母的 ASCII 值。
strcmp() 返回一个整数,表示两个字符串的比较结果。
下面是一些比较的示例:
char arr1[20] = "zhangsan";
char arr2[20] = "zhangsanfeng";
int res = strcmp(arr1, arr2);
if (res < 0)
{
printf("<\n"); // <
}
else if (res == 0)
{
printf("=\0");
}
else
{
printf(">\0");
}
int my_strcmp(const char *s1, const char *s2)
{
assert(s1 && s2);
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0; // 如果全等 abc == abc
}
s1++;
s2++;
}
return *s1 - *s2;
}
char arr4[] = "zhanghai";
char arr5[] = "zhanghai";
printf("%d\n", my_strcmp(arr4, arr5)); // 0
strncpy
函数用于从源字符串复制指定数量的字符到目标字符串中,如果源字符串长度小于指定长度,则会用空字符进行填充。
char * strncpy ( char * destination, const char * source, size_t num );
在这个示例中,我们声明了一个目标字符串 dest
,一个源字符串 src
以及要复制的字符数量 n
。然后,我们使用 strncpy
函数将 src
中的前 n
个字符复制到 dest
中。最后,我们手动添加了一个结尾标记 \0
,以确保目标字符串正确终止。最后,我们打印复制后的目标字符串 dest
。
请注意,要确保目标字符串 dest
的长度足够大,以容纳复制的字符和结尾标记。如果 n
大于等于源字符串的长度,那么目标字符串将没有结尾标记
#include
#include
int main() {
char dest[20];
const char* src = "Hello, World!";
size_t n = 5;
printf("源字符串: %s\n", src);
printf("复制的字符数: %zu\n", n);
strncpy(dest, src, n);
dest[n] = '\0'; // 添加结尾标记
printf("目标字符串: %s\n", dest);
return 0;
}
#include
char* my_strncpy(char* dest, const char* src, size_t n) {
size_t i;
for (i = 0; i < n && src[i] != '\0'; i++) {
dest[i] = src[i];
}
for ( ; i < n; i++) {
dest[i] = '\0'; // 如果源字符串长度小于 n,则用空字符填充
}
return dest;
}
int main() {
char dest[20];
const char* src = "Hello, World!";
size_t n = 5;
printf("源字符串: %s\n", src);
printf("复制的字符数: %zu\n", n);
my_strncpy(dest, src, n);
printf("目标字符串: %s\n", dest);
return 0;
}
char * strncat ( char * dest , const char * src , size_t n );
strncat
用于将指定长度的字符串拼接(追加)到目标字符串的末尾。
参数说明:
dest
:目标字符串,要将源字符串拼接到其末尾的字符串。src
:源字符串,要拼接到目标字符串末尾的字符串。n
:要拼接的最大字符数,即 src
中要拷贝的字符数。strncat
函数的作用是将 src
指向的字符串的前 n
个字符(如果 src
的长度小于 n
则拷贝整个字符串)追加到 dest
指向的字符串的末尾,并在目标字符串的末尾添加字符串结尾标志 \0
。
该函数会返回指向目标字符串 dest
的指针,即拼接后的字符串的起始地址。
需要注意的是,目标字符串 dest
必须有足够的空间来容纳源字符串 src
的字符。否则,会导致缓冲区溢出和未定义的行为。
同时,strncat
不会检查源字符串 src
是否符合 C 字符串的规范(即是否以 \0
结尾),因此要确保源字符串 src
以 \0
结尾,以避免结果不符合预期。
在这个示例中,我们通过 strncat
函数将源字符串 src
的前 7 个字符拼接到目标字符串 dest
的末尾。输出中的最后一行显示了拼接后的字符串 dest
。由于目标字符串 dest
的长度限制在 20 个字符,所以只有部分字符被拼接进去,因此输出结果是 “Hello, Wo”。
#include
#include
int main() {
char dest[20] = "Hello";
const char* src = ", World!";
size_t n = 7;
printf("目标字符串: %s\n", dest); // 目标字符串: Hello
printf("源字符串: %s\n", src); // 源字符串: , World!
printf("拼接的字符数: %zu\n", n); // 拼接的字符数: 7
strncat(dest, src, n);
printf("拼接后的字符串: %s\n", dest); // 拼接后的字符串: Hello, Wo
return 0;
}
#include
char* strncat_sim(char* dest, const char* src, size_t n) {
char* dest_start = dest; // 保存目标字符串的起始位置
// 遍历目标字符串,直到达到结尾
while (*dest != '\0') {
dest++;
}
// 将源字符串中的字符逐个拼接到目标字符串中,直到达到指定的字符数 n 或源字符串结尾
while (n > 0 && *src != '\0') {
*dest = *src;
dest++;
src++;
n--;
}
*dest = '\0'; // 添加结尾标记
return dest_start; // 返回目标字符串的起始位置
}
int main() {
char dest[20] = "Hello";
const char* src = ", World!";
size_t n = 7;
printf("目标字符串: %s\n", dest); // 目标字符串: Hello
printf("源字符串: %s\n", src); // 源字符串: , World!
printf("拼接的字符数: %zu\n", n); // 拼接的字符数: 7
strncat_sim(dest, src, n);
printf("拼接后的字符串: %s\n", dest); // 拼接后的字符串: Hello, Wo
return 0;
}
int strncmp ( const char * str1, const char * str2, size_t num );
s1
小于 s2
,函数返回一个负值;如果 s1
大于 s2
,函数返回一个正值;如果两个字符串在前n个字符内相等,函数返回0。strncmp
类似,如果某个字符串的前n个字符中包含了'\0'
(即字符串结束符),则仅比较到该结束符为止。#include
#include
int main() {
const char* str1 = "Hello";
const char* str2 = "Hell";
int n = 4;
int result = strncmp(str1, str2, n);
if (result == 0) {
printf("两个字符串相等\n");
} else if (result < 0) {
printf("str1 小于 str2\n");
} else {
printf("str1 大于 str2\n"); // str1 大于 str2
}
return 0;
}
#include
int custom_strncmp(const char *s1, const char *s2, size_t n) {
for (size_t i = 0; i < n; i++) {
if (s1[i] != s2[i]) {
return (s1[i] - s2[i]);
}
if (s1[i] == '\0') {
return 0; // 达到了字符串结尾
}
}
return 0; // 前 n 个字符均相同
}
int main() {
const char *s1 = "Hello";
const char *s2 = "Hell";
int result = custom_strncmp(s1, s2, 4);
if (result < 0) {
printf("s1 小于 s2\n");
} else if (result > 0) {
printf("s1 大于 s2\n"); // s1 大于 s2
} else {
printf("s1 等于 s2\n");
}
return 0;
}
查找小串在大串是否出现,返回出现小串往后的字符
char* strstr(const char* haystack, const char* needle);
char email[] = "[email protected]";
char substr[] = "example.com";
char *res = strstr(email, substr);
if (res == NULL)
{
printf("子串不存在\n");
}
else
{
printf("%s", res); // example.com.demo
}
char *my_strstr(const char *str1, const char *str2)
{
assert(str1 && str2);
const char *s1 = str1; // 负责找大串
const char *s2 = str2; // 负责找小串
const char *p = 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;
}
char email[] = "[email protected]";
char substr[] = "example.com";
char *p = my_strstr(email, substr);
printf("%s\n", p); // example.com.demo
分割字符串
char * strtok ( char * str, const char * sep );
const char *sep = "@.";
char eml[] = "[email protected]";
char cp[40] = {0};
strcpy(cp, eml);
char *ret = NULL;
for (ret = strtok(cp, sep); ret != NULL; ret = strtok(NULL, sep))
{
/*
zhanghai
bitejiuyeke
com
net
*/
printf("%s\n", ret);
}
#include
#include
char* custom_strtok(char* str, const char* delim) {
static char* remaining = NULL;
if (str != NULL) {
remaining = str;
}
// 跳过开头的分隔符
while (*remaining != '\0' && strchr(delim, *remaining) != NULL) {
remaining++;
}
if (*remaining == '\0') {
return NULL;
}
char* token = remaining;
remaining = strpbrk(remaining, delim);
if (remaining != NULL) {
*remaining = '\0';
remaining++;
}
return token;
}
int main() {
char str[] = "Hello World! This is a test.";
char delim[] = " ";
char* token = custom_strtok(str, delim);
while (token != NULL) {
/*
Hello
World!
This
is
a
test.
*/
printf("%s\n", token);
token = custom_strtok(NULL, delim);
}
return 0;
}
char * strerror ( int errnum );
在这个示例中,我们尝试打开一个不存在的文件。由于文件不存在,fopen
函数将返回NULL
。然后,我们使用errno
变量获取最近一次错误的错误码,传递给strerror
函数。strerror
函数将错误码转换为对应的错误信息字符串。
在这里,strerror(errno)
将返回"No such file or directory",因为我们尝试打开一个不存在的文件。我们通过printf
函数将错误信息打印到控制台上。
#include
#include
#include
int main() {
FILE* file = fopen("nonexistent_file.txt", "r");
if (file == NULL) {
printf("Failed to open file: %s\n", strerror(errno));
}
return 0;
}