C/C++教程

C语言:字符函数与字符串函数

本文主要是介绍C语言:字符函数与字符串函数,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

  • 字符串的多种形式
    • 1.字符数组形式(不写元素个数)
    • 2.字符数组形式(写元素个数)
    • 3.字符指针(常量字符串)
    • 总结
  • 1.求字符串长度函数strlen( )
  • 2.拷贝字符串函数strcpy( )——长度不受限
  • 3.追加字符串函数strcat( )——长度不受限
  • 4.比较字符串函数strcmp( )——长度不受限
  • 5.拷贝字符串函数strcpy( )——长度受限
  • 6.追加字符串函数strncat( )——长度受限
  • 8.比较字符串函数strncmp( )——长度受限
  • 7.寻找字符串函数strstr( )

字符串的多种形式

1.字符数组形式(不写元素个数)

	char str1[] = { 'a','b','c' };
	char str2[] = { "abc" };
	char str3[] = "abc";

在这里插入图片描述

可见在不写数组元素个数,只写[ ]时,str1不会在后面自动补充\0
在写成字符串时可自动补\0


2.字符数组形式(写元素个数)

	char str1[3] = { 'a','b','c' };
	char str2[4] = { 'a','b','c' };

	char str3[3] = { "abc" };
	char str4[4] = { "abc" };

	char str5[3] = "abc";
	char str6[4] = "abc";

在这里插入图片描述

可见在输入元素后大家表现的都非常一致,当元素仅仅够字符不够加上\0时都不会主动加\0,当有元素多出时会在字符串后面出现\0
但要注意,str2这种情况有\0是因为多出的元素默认为\0
str4和str6这种情况有\0是因为字符串末尾会自己追加\0
str3和str5之所以没有追加上\0是因为元素不足


3.字符指针(常量字符串)

	char* str1 = "abc";
	char* str2 = { "abc" };
	printf("%s\n", str1);
	printf("%s\n", str2);

在这里插入图片描述

这个里用字符指针接收的都是常量字符串,在内存中你看不到到底后面是否有\0
所以利用%s遇到\0停止打印这一特性,会发现str1和str2都可以正常打印创建的常量字符串,所以常量字符串后面会自动追加\0

总结

输入“abc”这种字符串时,只要开辟的空间够多就可以自动追加\0,如果不够也就是少了\0的空间,那就无法追加\0
“abc”和{“abc”}的情况相同
{ ‘a’,‘b’,‘c’ }这种情况不论什么时候都不会自动追加\0

在开辟字符串时多出的内存会默认变为\0






1.求字符串长度函数strlen( )

size_t strlen ( const char * str );


功能:记录字符串\0前有多少个字符


1.字符串已经 '\0’作为结束标志,strlen函数返回的是在字符串中 '\0’前面出现的字符个数(不包含 ‘\0’)




2.参数指向的字符串必须要以 '\0’结束
在这里插入图片描述
只所以len1是15是因为str1中没有\0,strlen在str1中一直没找到\0,终于在第15个字符后找到了,所以记录15,实则是随机值,而str2中有\0,所以返回3也就是记录了3个字符




3.注意函数的返回值为size_t是无符号的
在这里插入图片描述
strlen(“abc”)应该是3而strlen(“qwerty”)应该是6,结果输出的是>,这时为什么呢,是因为strlen返回的是一个size_t的无符号整形,3-7虽然是-4但是size_t会认为它是一个很大的正数,所以输出的>而不是<=
修改:在这里插入图片描述



strlen函数的模拟实现
计数器方法

size_t my_strlen(const char* str)
{
	assert(str);
	int count = 0;
	while (*str++ != '\0')
	{
		count++;
	}
	return count;
}

递归方法

size_t my_strlen(const char* str)
{
	if (*str == '\0')
	{
		return 0;
	}
	else
	{
		return my_strlen(str+1) + 1;
	}
}

指针-指针方法

size_t my_strlen(const char* str)
{
	assert(str);
	char* p = str;
	while (*str)
	{
		str++;
	}
	return str - p;
}





2.拷贝字符串函数strcpy( )——长度不受限

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


功能:将源字符串的内容拷贝到目标字符串(同时拷贝源字符串的\0)


1.源字符串必须以 '\0’结束。
在这里插入图片描述
此时str2是“abcdef\0”后面是有\0的,所以可以将str2拷贝给源字符串
在这里插入图片描述
当str2后面没有\0,将str2拷贝给str1就会失败




2.会将源字符串中的 '\0’拷贝到目标空间。
在这里插入图片描述
我们创建一个XXXXXXXXX字符数组,故意比str2大一些,然后让str2拷贝到str1中看看在众多X前会不会出现\0,出现了就说明strcpy会将源字符串中的 '\0’拷贝到目标空间




3.目标空间必须足够大,以确保能存放源字符串。
在这里插入图片描述
当要把“abcef\0”拷贝到只有4个字符空间的str1时,你会发现直接报错,是因为必须要目标空间足够大,才能确保能存放源字符串




4.目标空间必须可变。
在这里插入图片描述
因为str1指向的常量字符串,常量是不能修改的



strcpy函数的模拟实现

#include<stdio.h>
#include<assert.h>
char* my_strcpy(char*dest,const char*src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest++=*src++)
	{
		;
	}
	return ret;
}
int main()
{
	char str1[20] = {0};
	char*str2="hello world";
	printf("%s", my_strcpy(str1, str2));
}

这里写的*dest++=*src++,需要多理解理解
他是先执行++,但是是后置++,放在了最后执行
再去去将src中的值赋值给dest所指向的内容,然后执行++,各自地址跳一位
然后当src指向\0时,先赋值给dest,因为\0=0,被赋值0后,dest此时表示为假了,所以可以while跳出循环
这样就能做到,将源字符串的所有字符串包括\0赋值到目标字符串

strcpy函数的返回值要返回目标字符串被替换的首地址,所以用ret先存储一下首地址,然后最后返回ret就行,这样在printf中可以直接调用函数,输出的就是被更改完毕的目标字符串,做到链式访问的效果






3.追加字符串函数strcat( )——长度不受限

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


功能:从目标字符串\0处开始追加源字符串的内容(追加源字符串的\0)


1.源字符串必须以’\0’ 结束。
我们不知道是否追加源字符串的\0,所以我们可以根据,strcat函数时要从目标字符串的\0处开始追加源字符串内容,这一特点来设计一个内容去验证一下源字符串是否要追加自己的\0
在这里插入图片描述
可见strcat函数确实能让源字符串中的\0追加到目标字符串,所以说源字符串还必须要有\0,不然目标字符串中大概率会没有\0,是的字符串不完整,所以源字符串必须以’\0’ 结束




2.目标字符串必须以’\0’ 结束。
因为strcat函数要寻找到\0后才能追加,所以目标字符串必须要出现\0
在这里插入图片描述
之所以后面又追加到world是因为strcat在后面的随机值中找着找着,找到了\0最后追加在它的后面了



3.目标空间必须有足够的大,能容纳下源字符串的内容。
在这里插入图片描述



4.目标空间必须可修改。
目标字符串不能是常量字符串这种无法修改的字符串
在这里插入图片描述



strcat函数的模拟实现

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)//找个目标字符串中的\0
	{
		dest++;
	}
	while (*dest++ = *src++)//和strcpy的实现差不多,继续拷贝
	{
		;
	}
	return ret;
}
int main()
{
	char str1[20] = "hello";
	char*str2 = " world";
	my_strcat(str1, str2);
	printf("%s", str1);
}


strcat函数的模拟实现的问题
你会发现我们实现的strcat函数后,字符串自己追加自己时就会出问题,当dest找到\0后将第一个字符赋值到\0的位置是,src指向的字符串整体就没有\0了,这样while (*dest++ = *src++),这句话就不会停止,因为解引用src不会在出现\0了,这样就会发现我们模拟实现的strcat无法让字符串自己追加自己,而我们调用的strcat是可以做到本字符串自己追加自己的
在这里插入图片描述
但有些版本调用strcat库函数可以实现本字符串追加到自己末尾!!!版本不同,编译器不同结果不同
在这里插入图片描述
上面是库函数里面提供的参考实现strcat的代码






4.比较字符串函数strcmp( )——长度不受限

int strcmp ( const char * str1, const char * str2 );


功能:挨个比较字符串中每个字符的ASCII码值


标注规定:strcmp比较的不是字符串的长度,而是比较字符串中对应位置上的字符大小,如果相同,就比较下一个,直到不用或者都遇到\0
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

vs2019编译器中的库函数大于时返回1,等于返回0,小于返回-1
在这里插入图片描述
如果字符串的长度不相同,且前面的字符大小都一样的情况下,短字符串会跳到字符串最后\0然后去和长字符串对应的字符比较,这样长的字符串此时会比短字符串大
在这里插入图片描述



strcmp函数的模拟实现

这里我们返回的时候直接返回两个字符ASCII差值,更利用实现和使用,返回值虽然不和vs只返回1或者-1一样,但是也是返回>0或者<0

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

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (str1 == 0)
		{
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;
}

int main()
{
	char str1[5]="abcde";
	char str2[5] = "abc";
	int i = my_strcmp(str1, str2);
	if (i > 0)
	{
		printf(">\n");
	}
	else
	{
		if (i == 0)
		{
			printf("=\n");
		}
		else
		{
			printf("<\n");
		}
	}
	printf("%d",my_strcmp(str1, str2));
}





5.拷贝字符串函数strcpy( )——长度受限

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


功能:拷贝num个字符从源字符串到目标空间


1.拷贝num个字符从源字符串到目标空间。
2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加\0,直到num个
在这里插入图片描述
还要记住其他情况都要遵循上面所写的strcpy的情况,比如说目标字符串空间必须充足,长度超出会报错
在这里插入图片描述






6.追加字符串函数strncat( )——长度受限

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


功能:从目标字符串\0处开始追加num个源字符串的内容(追加源字符串的\0)


追加完毕后会在后面放入一个\0
在这里插入图片描述

目标字符串开辟的内存必须足够多,不然会报错
在这里插入图片描述






8.比较字符串函数strncmp( )——长度受限

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


功能:挨个比较前num个字符串中每个字符的ASCII码值


返回值和strcmp相同
制定了比较字符串的长度
对比长度要在制定范围内,不要超出字符串长度,否则返回内容不可预料






7.寻找字符串函数strstr( )

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


功能:寻找目标字符串中是否有源字符串,有的话返回出现源字符串的起始地址,没有返回NULL



strstr函数的模拟实现

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

char* my_strstr(const char* str1, const char* str2)
{
	char* s1 = str1;
	char* s2 = str2;

	char* cur = str1;
	while (*cur)
	{
		s1 = cur;
		while (*s1 && *s2 && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cur;
		}
		cur++;
	}
	return NULL;

}
int main()
{
	char str1[20] = "abcdefghijk";
	char str2[5] = "ghi";
	char* ret = my_strstr(str1, str2);
	if (ret==NULL)
	{
		printf("找不到子串\n");
	}
	else
	{
		printf("%s", ret);
	}

}
这篇关于C语言:字符函数与字符串函数的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!