常见字符串函数的初步讲解(使用与简单模拟实现)

前言:

在编程的过程中,我们经常要处理字符和字符串,为了方便操作字符和字符串,C语言标准库中提供了一系列库函数,现在接下来就简单讲解一下下面的字符串函数

一、字符分类函数

在C语言中,有一些常用的字符分类函数可以帮助我们对字符进行分类和判断。这些函数属于C标准库中的ctype.h头文件,并提供了对字符进行分类的功能。

(使用以下函数时都需要包含ctype.h头文件)

这些函数使用方法都大同小异,所以我就只举一个函数的使用例子来说明一下:

int islower(int c)

islower函数通过判断这里的c是否为小写字母而返回真值

下面来写一个代码排查一串大写字符中的小写字目母并将其改为大写字母:

#include<stdio.h>
#include<ctype.h>

//islower函数的使用举例
//islower函数可以判断是否为小写字符而返回真

int main()
{
	char arr[] = "Hehe";
	int i = 0;
	char c = 0;
	while (arr[i])
	{
		c = arr[i];
		putchar(c);
		i++;
	}
	printf("\n");
	i = 0;
	while(arr[i])
	{
		if (islower(arr[i]))//若为真,代表为小写字符,返回非零值,if条件满足进入if语句
		{
			arr[i]-=32;//减去32使小写字母变成大写字母
		}
		c = arr[i];
		putchar(c);
		i++;
	}
	return 0;
}

输出结果为:

Hehe
HEHE

二、字符转换函数

C语⾔提供了2个字符转换函数:
int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写

在上面我们写了一串代码将小写字符转换为大写,有了这两个函数后,我们就可以直接转换了:
 

#include<stdio.h>
#include<ctype.h>

//islower函数的使用举例
//islower函数可以判断是否为小写字符而返回真

int main()
{
	char arr[] = "Hehe";
	int i = 0;
	char c = 0;
	while (arr[i])
	{
		c = arr[i];
		if (islower(c))//若为真,代表为小写字符,返回非零值,if条件满足进入if语句
		{
		    c = toupper(c);
		}
		putchar(c);
		i++;
	}
	return 0;
}

三、常见字符函数 

1、strlen的使用与模拟实现

size_t strlen( const char *string );

strlen的使用需要包含头文件string.h,且它使用时,所指向的的字符串必须包含结束标识'\0',返回一个size_t类型的整形.

strlen统计string指针所指向的字符串第一个结束标识'\0'前字符的数量,倘若一个字符串不包含'\0’,那strlen将会继续往后统计直到找到结束标识并返回统计的个数:

下面是一个简单举例:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "hello";
	char arr2[] = { 'h','e','l','l','0' };
	size_t a, b;//strlen函数返回值类型为size_t类型,最好用同类型来接收
	a = strlen(arr1);
	b = strlen(arr2);
	printf("a=%zu,b=%zu", a, b);//size_t类型用%zu来转义
	return 0;
}

arr1数组最后包含了结束标识'\0',于是统计出来时5,但arr2中并不包含,于是统计出来是一个大于等于5的随机值

a=5,b=37

接下来我们就可以用多个简单的c语言知识来模拟实现一下strlen函数,探究其怎么实现的内容:

size_t my_strlen(const char* p)
{
	size_t count = 0;
	while (*p)
	{
		count++;
		*p++;
	}
	return count;
}

int main()
{
	char arr1[] = "hello";
	char arr2[] = { 'h','e','l','l','0' };
	size_t a, b;
	a = my_strlen(arr1);
	b = my_strlen(arr2);
	printf("a=%zu,b=%zu", a, b);
	return 0;
}

这是一种普遍的模拟方式,当然为了函数的安全,也可以在函数定义里加上assert断言来判断形参指针p所指向的空间。

当然,也可以不创建临时变量,采用迭代的方式来模拟实现:

size_t my_strlen(const char* p)
{
	if (*p == '\0')
		return 0;
	else
		return 1 + my_strlen(p + 1);//采用迭代,数据量上去了可能会崩溃
}

2、strcpy的使用与模拟实现

char* strcpy(char * destination, const char * source );

在C语言中,strcpy是一个常用的字符串操作函数,用于将一个字符串复制到另一个字符串中。使用strcpy函数时需要注意以下几点:
1、源字符串必须以 '\0' 结束,在拷贝的时候,strcpy会将源字符串的'\0’一起拷贝到目标字符串。

2、⽬标空间必须足够大,以确保能存放源字符串,且目标空间必须可修改。

以下举个例子看看strcpy函数的使用,与strlen一样,使用前也需要包含头文件string.h.

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "hello";
	char arr2[10] = { 0 };
	strcpy(arr2, arr1);
	int i = 0;
	while (arr2[i])
	{
		printf("%c", arr2[i]);
		i++;
	}
	return 0;
}

上述示例中,我们首先定义了一个源字符串arr1和一个目标字符串arr2。然后调用strcpy函数将源字符串复制到目标字符串中。最后输出目标字符串的内容。

运行上述代码,输出结果为

hello

下面我们来实现一个类似于strcpy函数的函数,名为my_strcpy:

#include<stdio.h>
#include<assert.h>

char* my_strcpy(char* dest, const char* str)
{
	char* p = dest;//这一步尤其关键,因为该函数会返回一个地址,我们定义
    //一个指针指向我们需要返回的地址
	assert(dest != NULL);
	assert(str != NULL);//p判断是否为空指针,要先声明头文件assert.h

	while (*dest++ = *str++)//*的优先级大于++,每次给*dest赋值后向后移动
    //直到*str变成'\0'条件为假
	{
		;
	}
	return p;//改地址指向原dest的首元素的地址
} 

int main()
{
	char arr1[] = "hello";
	char arr2[10] = { 0 };
	my_strcpy(arr2, arr1);
	int i = 0;
	while (arr2[i])
	{
		printf("%c", arr2[i]);
		i++;
	}
	return 0;
}

运行上述代码,输出结果与前面的示例相同:

hello

3、strcat的使用与模拟实现

char* strcat(char* destination, const char* source);

strcat函数接受两个参数:目标字符串destination和源字符串source。它将源字符串的内容追加到目标字符串的末尾,并返回指向目标字符串的指针。

在使用strcat时,必须注意以下几点:

1、源字符串必须以'\0’结尾,目标字符串也必须以'\0'结尾。

2、目标字符串的空间必须足够大,能够容纳源字符串,且目标字符串必须可以被改变。

3、不能让字符串自己追加自己。

以下我们来举个简单的例子来使用一下strcat:
 

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[30] = "hello ";
	char arr2[] = "world!";
	strcat(arr1, arr2);
	int i = 0;
	while (arr1[i])
	{
		printf("%c", arr1[i]);
		i++;
	}
	return 0;
}

在上面的代码中,我们调用strcat函数将源字符串追加到目标字符串的末尾。最后输出目标字符串的内容。

hello world!

下面我们来实现一个类似于strcat函数的函数,名为my_strcat。这个函数的功能与strcat相同,都是将源字符串追加到目标字符串的末尾:

char* my_strcat(char* dest, const char* sour)
{
	char* str = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *sour++)
	{
		;
	}
	return str;
}

int main()
{
	char arr1[30] = "hello ";
	char arr2[] = "world!";
	my_strcat(arr1, arr2);
	int i = 0;
	while (arr1[i])
	{
		printf("%c", arr1[i]);
		i++;
	}
	return 0;
}

在上述代码中,我们定义了一个my_strcat函数,在第一个while循环中找到目标字符串的末尾位置,然后使用指针遍历源字符串,将每个字符复制到目标字符串的末尾,并确保目标字符串正确终止。

运行代码,结果为:

hello world!

4、strcmp 的使用和模拟实现

int strcmp( const char *string1, const char *string2 );

 strcmp比较两个字符串的长度,并根据不同的情况返回不同的值。会按照字典序比较两个字符串的大小,如果string1小于string2,则返回一个负整数;如果string1大于string2,则返回一个正整数;如果两个字符串相等,则返回0。

如何判断两个字符串的大小呢?这里的原则是比较两个字符串中对应位置上字符ASCII码值的⼤⼩。
下面是一个使用strcmp函数的事例:
#include<string.h>

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcde";
	char arr3[] = "abcb";
	int a = strcmp(arr1, arr2);
	if (a > 0)
	{
		printf("arr1大于arr2\n");
	}
	else if (a < 0)
	{
		printf("arr1小于arr2\n");
	}
	else
	{
		printf("arr1等于arr2\n");
	}

	int b = strcmp(arr1, arr3);
	if (b > 0)
	{
		printf("arr1大于arr3\n");
	}
	else if (b < 0)
	{
		printf("arr1小于arr3\n");
	}
	else
	{
		printf("arr1等于arr3\n");
	}
	return 0;
}

运行结果为:

arr1小于arr2
arr1大于arr3

说明比较的原理确实是比较两个字符串中对应位置上字符ASCII码值的⼤⼩。

下面我们来实现一个类似于strcmp函数的函数,名为my_strcmp。这个函数的功能与strcmp相同,都是比较两个字符串的大小关系:
 

#include<stido.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)//两个参数都用const修饰防止被修改
{
	assert(str1 != NULL);
	assert(str2 != NULL);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')//此时str2其实与str1相同
		{
			return 0;//一直到取到'\0'都相同,直接返回0
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;//直接相减,返回值若为正,则说明str1大于str2
}

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcde";
	int a = my_strcmp(arr1, arr2);
	if (a > 0)
	{
		printf("arr1大于arr2\n");
	}
	else if (a < 0)
	{
		printf("arr1小于arr2\n");
	}
	else
	{
		printf("arr1等于arr2\n");
	}
	return 0;
}

运行上述代码,输出结果与前面的示例相同:

arr1小于arr2

5、strncpy的使用与模拟实现

在c语言中,strncpy是一个常见的字符串操作函数,用于将一个字符串的部分内容复制到另一个字符串中,它的使用与strcpy有相同之处,但不完全一样。

 char * strncpy ( char * destination, const char * source, size_t num );

strncpy函数接受三个参数:目标字符串destination、源字符串source和要复制的字符数num。它将source字符串的最多num个字符复制到destination字符串中,并返回指向目标字符串的指针。

使用时要注意以下几点:

1、该函数是从source中拷贝num个字符到destination字符串中

2、如果源字符串的⻓度⼩于num,则拷贝完源字符串之后,在⽬标的后边追加0,直到num个。

3、目标字符串空间要足够大。

下面是一个strncpy函数的事例:

#include<stdio.h>
#include<string.h>

int main()
{ 
	char arr1[] = "hello worldwide";
	char arr2[14];
	char* str = strncpy(arr2, arr1, 11);
	str[11] = '\0';//因为当num小于source的字符数时,不会复制'\0’到dest字符串中
	//这里是手动给一个'\0'方便打印的时候打印结束
	int i = 0;
	while (str[i])
	{
		printf("%c", str[i]);
		i++;
	}
	return 0;
}

运行上述代码,输出结果为:

hello world

 下面我们来实现一个类似于strncpy函数的函数,名为my_strncpy。这个函数的功能与strncpy相同,都是将源字符串的部分内容复制到目标字符串中。

char* my_strncpy(char* dest, const char* sour, size_t num)
{
	char* str = dest;
	while (*dest != '\0' && num > 0)
	{
		*dest++ = *sour++;
		num--;
	}//当num还未等于0时,还要继续赋值0
	while (num > 0)
	{
		*dest = '\0';
		dest++;
		num--;
	}
	return str;
}

int main()
{
	char arr1[] = "hello worldwide";
	char arr2[14];
	char* str = my_strncpy(arr2, arr1, 11);
	str[11] = '\0';
	int i = 0;
	while (str[i])
	{
		printf("%c", str[i]);
		i++;
	}
	return 0;
}

在上述代码中,我们定义了一个my_strncpy函数,使用指针遍历源字符串和目标字符串,并逐个字符进行复制,直到达到指定的字符数num或源字符串结束。如果num大于源字符串的长度,我们会在目标字符串中填充'\0'直到达到num个字符。

运行程序,结果一样:

hello world

6、strncat函数的使用与模拟实现

char * strncat ( char * destination, const char * source, size_t num );

strncat接受三个参数:目标字符串destination,源字符串source,与要追加的最大字符数num。它将source字符串中最多num个字符追加到destination的末尾,并返回指向目标字符串的指针。

使用时要注意以下几点:

1、strncat将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 ‘\0’符。

2、如果source 指向的字符串的⻓度⼩于num的时候,只会将字符串中到 '\0' 的内容追加到destination指向的字符串末尾。

下面是一个使用strncat函数的事例:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[20] = "hello";
	char arr2[] = ",world!";
	char* str = strncat(arr1, arr2, 7);
	int i = 0;
	while (str[i])
	{
		printf("%c", str[i]);
		i++;
	}
	return 0;

 运行程序:

hello,world!

下面我们来实现一个类似于strncat函数的函数,名为my_strncat。这个函数的功能与strncat相同,都是将源字符串的部分内容追加到目标字符串的末尾。

char* my_strncat(char* dest, const char* sour, size_t num)
{
	char* str = dest;
	while (*dest != '\0')//找到dest字符串的末尾
	{
		dest++;
	}
	while (*sour != '\0' && num > 0)
	{
		*dest = *sour;
		dest++;
		sour++;
		num--;
	}
	*dest = '\0';//手动赋予结束标志

	return str;
}

int main()
{
	char arr1[20] = "hello";
	char arr2[] = ",world!";
	char* str = my_strncat(arr1, arr2,8);
	int i = 0;
	while (str[i])
	{
		printf("%c", str[i]);
		i++;
	}
	return 0;
}

在上述代码中,我们定义了一个my_strncat函数,首先使用指针遍历目标字符串到末尾位置,然后使用指针遍历源字符串,并逐个字符进行追加,直到达到指定的字符数num或源字符串结束。最后手动添加结束符\0

运行上述代码,输出结果与前面的示例相同:

hello,world!

7、strstr的使用与模拟实现

 char * strstr ( const char * str1, const char * str2);

strstr函数接收两个参数str1,str2,它会在str1字符串中查找第一次str2字符串出现的位置,并返回一个指针指向该位置,若没有找到str2字符串,则会返回NULL指针。

下面是一个使用strstr函数的示例:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "my name is Jack,What is your name?";
	char arr2[] = "name";
	char* str = strstr(arr1, arr2);
	int i = 0;
	while (str[i])
	{
		printf("%c", str[i]);
		i++;
	}
	return 0;
}

运行上述代码,输出结果为:

name is Jack,What is your name?

需要注意的是,strstr函数返回的指针指向源字符串中第一次出现子字符串的位置。

面我们来实现一个类似于strstr函数的函数,名为my_strstr。这个函数的功能与strstr相同,都是在一个字符串中查找子字符串的位置。

char* my_strstr(const char* str1, const char* str2)
{
	while (*str1 != '\0')//当str1遍历一遍后还未找到,就说明没有,直接返回NULL
	{
		const char* p1 = str1;
		const char* p2 = str2;//
		while (*str2 != '\0' && *p1 == *p2)
		{
			p1++;
			p2++;
		}
		if (*p2 == '\0')
		{
			return (char*)str1;//当全部满足时返回此时str1的地址,由于返回应该是char*类型,所以还需要强制类型转化为char*
		}
		*str1++;//说明从这个地址出发找不到相同字符串,于是向后移动地址
	}
	return NULL;
}

int main()
{
	char arr1[] = "my name is Jack,What is your name?";
	char arr2[] = "name";
	char* str = my_strstr(arr1, arr2);
	int i = 0;
	while (str[i])
	{
		printf("%c", str[i]);
		i++;
	}
	return 0;
}

在上述代码中,我们定义了一个my_strstr函数,使用指针遍历源字符串,并逐个字符的开始比较。当查找到第一个相符合的字符时,内部循环开始了进一步的完全比较,如果完全匹配成功,就返回此时查找成功的首字符的地址,若一直没有成功,就返回NULL。

运行上述代码,输出结果与前面的示例相同:

name is Jack,What is your name?

接下里的函数,大多大同小异,我们就只是简单介绍一下这些函数使用实例:

8、strncmp函数的使用

 int strncmp ( const char * str1, const char * str2, size_t num );

比较str1与str2的前num个字符,如果提前发现不相等,就提前结束。如果num个字符全部相同,则返回0。

#include<string.h>

int main()
{
	char arr1[] = "abcdefgeg";
	char arr2[] = "abcdefghi";
	char arr3[] = "abcb";
	int a = strncmp(arr1, arr2, 8);
	if (a > 0)
	{
		printf("arr1大于arr2\n");
	}
	else if (a < 0)
	{
		printf("arr1小于arr2\n");
	}
	else
	{
		printf("arr1等于arr2\n");
	}

	int b = strncmp(arr1, arr3, 3);
	if (b > 0)
	{
		printf("arr1大于arr3\n");
	}
	else if (b < 0)
	{
		printf("arr1小于arr3\n");
	}
	else
	{
		printf("arr1等于arr3\n");
	}
	return 0;
}

运行程序,结果如下:
 

arr1小于arr2
arr1等于arr3

9、strtok函数的使用

char * strtok ( char * str, const char * sep);

strtok函数的接收两个参数:被分割的字符串str,与分隔符sep。他会将str根据sep分隔符进行分割,并返回指向第一个字符串的指针,当再次调用strtok函数的时候,就会将NULL指针当做str参数,就可以获取下一个字符串。

使用该函数的时候需要注意以下几点:
1、sep参数指向了一个字符串,定义了用作分隔符的字符集合。

2、str指向一个字符串,包含了零个或多个包含了sep分隔符的字符

3、strtok找到str中的下一个标记,并将其用'\0'结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串⼀般都是临时拷贝的内容 并且可修改。)

4、strtok的str参数不为NULL,strtok将会找到str中的第一个标记,strtok函数将会保存它在这个字符串的位置。

5、strtok的str参数为NULL,strtok将会从保存的位置开始,并查找下一个标记。

6、若字符串中不存在更多的标记,将会返回NULL指针。

我们举个例子来说明:
 

int main()
{
	char arr1[] = "Hello, World! Nice to meet you.";
	char* arr2 = strtok(arr1, " ,!.");

	while (arr2 != NULL)
	{
		printf("%s\n", arr2);
		arr2 = strtok(NULL, " ,!.");
	}
	return 0;
}

上述示例中,我们定义了一个字符串str,其中包含了一些词汇和标点符号。然后通过多次调用strtok函数来分割字符串。首先调用一次strtok函数,传入要分割的字符串和分隔符,获取第一个子字符串的指针。然后使用循环和printf函数输出每个子字符串的内容。在循环内部,通过再次调用strtok函数并传入NULL来获取下一个子字符串。(注意,这里的sep字符串包含空格,逗号,感叹号,句号)

运行上述代码,结果为:

Hello
World
Nice
to
meet
you

需要注意的是,strtok函数会修改原始字符串,并将分隔符替换成\0,因此在后续调用时要传入NULL作为参数。

由于strtok函数是一个有状态的函数,它会记住上一次调用结束的位置,所以在多线程环境中使用时要小心。

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渡我白衣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值