字符串函数和字符函数

这篇具有很好参考价值的文章主要介绍了字符串函数和字符函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在C语言中,我们经常会遇到字符串的处理,我们要是每当用到字符串总要自己写函数去解决问题的时候,未免有些麻烦,所以在这里我们可以调用库中的 “string.h" 的头函数来解决问题;下面就对一些经常使用的字符函数和字符串函数进行使用讲解和函数解析;

strlen()

size_t strlen ( const char * str );
获取字符串的长度

对于一个字符串,如”abc“,会通过字符串的首个字符开始计算,直至遇到终止字符‘\0’开始结束计算,终止字符’\0’ 不会算进去,所以”abc"长度为3;
当我们要使用的时候,输入一个字符指针或者字符数组即可;

char arr1[]=“abc”;
char* arr2=“bcd”
strlen(arr1);
strlen(arr2);

先看下面例子:

#include <string.h>
#include<stdio.h>
int main()
{
	if (strlen("abc") - strlen("abcdef") > 0)
	{
		printf("大于\n");
	}
	else
	{
		printf("小于等于\n");
	}

	return 0;
}

大于

我们可以很明显看出,"abc"是比“abcdef”字符串长度短的,但程序的结果却是大于,这是因为对于strlen()函数来说,它的返回类型是size_t,这个类型相当于unsigned char,是一个无符号的数据类型;所以对于使用strlen()来比较字符串长短,要用大于小于,像程序中的操作,只会显示错误;
正确方式:

#include <string.h>
#include<stdio.h>
int main()
{
	if (strlen("abc") >strlen("abcdef") )
	{
		printf("大于\n");
	}
	else
	{
		printf("小于等于\n");
	}

	return 0;
}

实现strlen()

代码:

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

对于一个字符串来说,我们用指针传参,那么传过去的是字符串的首个字符的地址,那么就可以通过指针的移动来统计字符串的长短;这里要注意:由于count类型和函数的类型不统一,一般以函数类型为主。

strcpy()

char * strcpy ( char * destination, const char * source );
复制字符串
将源指向的 C 字符串复制到目标指向的数组中,包括终止的 null 字符(并在该点停止)。
为避免溢出,目标指向的数组的大小应足够长,以包含与源相同的 C 字符串(包括终止空字符),并且不应在内存中与源重叠。

所以strcpy函数一般用于字符数组;
使用例子:

int main()
{
	
	char arr1[11] = "";
	char arr2[6] = "abcdef";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);

	return 0;
}

abcdef

模拟实现

代码:

#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest != NULL);
	assert(src != NULL);

	while (*dest++ = *src++)
	{
		;
	}

	return ret;
}

对于源字符串src是不可变的,所以用const来修饰;首先先用ret指针来记住arr1的首元素位置,然后对传参进行断言判断,如果为空那么将会在报出在哪行代码发生错误,可以快速的找到错误源头;这里的循环用到星号和++的优先级关系;这里是先解引用dest和src,然后将src赋值给dest,执行完之后dest和src才++,当src走到终止字符时,就会将终止字符赋给*dest当while循环条件判断时,将会终止该循环,最后返回ret指针

strcat()

char * strcat ( char * destination, const char * source );
连接字符串
将源字符串的副本追加到目标字符串。目标中的终止空字符被源的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符。这里不用在意源字符串的大小
目的地和来源不得重叠。

对于字符串来说都有终止字符,那么说明可以在目标字符串终止字符位置上开始追加源字符串;
使用例子:

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	strcat(arr1, arr2);

	printf("%s\n", arr1);
	return 0;
}

hello world

strcat()模拟实现

代码:

char* my_strcat(char*dest, const char *src)
{
	assert(dest && src);

	char* ret = dest;
	//1. 找目标空间中的\0
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

首先先对dest和src进行断言;然后用ret记住dest的地址,然后对dest移动,当移动到终止符号时停下,然后开始src对dest赋值;最后返回ret。

这里记住不能这样写:

字符串函数和字符函数,C语言,C语言的进阶,字符串函数,字符函数
这是因为当我们指针指向终止字符’\0’时,本来是判断结束了,但由于后置加加,所以加速之后指针还会向后走一步;

strcmp()

int strcmp ( const char * str1, const char * str2 );
比较两个字符串
将 C 字符串 str1 与 C 字符串 str2 进行比较。
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续以下对,直到字符不同或达到终止空字符.

这里的字符比较,将会根据字符对应的ACLII码字表对应的十进制数字进行比较大小,在VScode的gcc编译环境下,大于则返回1,小于则返回-1,等于则返回0;

int main()
{
    char* arr1="abc";
    char* arr2="ABC";
    printf("%d\n",strcmp(arr1,arr2));
    printf("%d\n",strcmp(arr2,arr1));
}

1
-1

模拟实现strcmp()

代码:

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);
}

先对str1,str2进行断言判断;当两个字符串的字符都相等时,则指针先后移动,移动到终止字符时就返回0,当两个字符串的字符不一样时,就返回它们的差值。

strstr()

const char * strstr ( const char * str1, const char * str2 );
char * strstr ( char * str1, const char * str2 );
查找子字符串
返回指向 str2 中第一次出现的 str1 的指针,如果 str2 不是 str1 的一部分,则返回一个空指针。
匹配过程不包括终止空字符,但它到此为止。

例子:

#include <stdio.h>
#include <string.h>
int main ()
{
  char str[] ="This is a simple string";
  char * pch;
  pch = strstr (str,"simple");
  
  printf("%s\n",pch);
  return 0;
}

simple string

模拟实现strstr()

代码:

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

	//str2为空直接返回str1首元素
	if (*str2 == '\0')
		return str1;

	while (*cp)
	{
		//开始匹配
		s1 = cp;
		s2 = str2;
		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return cp;

		cp++;
	}

	return NULL;
}

由于我们要多次循环匹配str1是否有str2字符串,所以利用循环嵌套的方法,外面的循环的对str1中每条子字符串进行匹配判断,指针逐渐先后移动;内层循环是判断str1中的子字符串中的字符是否与str2中的字符一致;
这里用cp记住str1的每个子字符串的首元素,s1是用来遍历str1每个子字符串中的字符是否与str2匹配;倘若内层遍历完到s2走到str2的终止字符,那么直接返回cp。外层循环一直没有结果就返回空指针;

strncpy(),strncmp(),strncat()

这类函数可以说是 strcpy(),strcmp(),strcat()函数的进阶版;它们的函数意义都没有改变,只是可以具体到了某个字节位置,不再是只到字符串的终止字符才停止;

char * strncpy ( char * destination, const char * source, size_t num );
从字符串中复制字符
将源的第一个字符数复制到目标。如果在复制 num 个字符之前找到源 C 字符串的末尾(由 null 字符表示),则目标将填充零,直到总共写入 num 个字符为止。
如果源长度超过 num,则不会在目标末尾隐式附加空字符。因此,在这种情况下,不应将目标视为以空结尾的 C 字符串(这样读取它会溢出)。
目的地和来源不得重叠

int strncmp ( const char * str1, const char * str2, size_t num );
比较两个字符串的字符
将 C 字符串 str1 的字符数与 C 字符串 str2 的字符数进行比较。
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同,直到达到终止的空字符,或者直到两个字符串中的 num 字符匹配,以先发生者为准。

char * strncat ( char * destination, const char * source, size_t num );
从字符串追加字符
将源的第一个数字字符追加到目标,外加一个终止空字符。
如果源中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容。

strtok()

char * strtok ( char * str, const char * delimiters );
将字符串拆分为标记
对此函数的一系列调用将 str 拆分为标记,这些标记是由分隔符中的任何字符分隔的连续字符序列。
在第一次调用时,该函数需要一个 C 字符串作为 str 的参数,其第一个字符用作扫描令牌的起始位置。在后续调用中,该函数需要一个空指针,并使用最后一个令牌末尾之后的位置作为扫描的新起始位置。
为了确定标记的开头和结尾,该函数首先从起始位置扫描分隔符中未包含的第一个字符(该字符将成为标记的开头)。然后从令牌的开头开始扫描分隔符中包含的第一个字符,该字符将成为令牌的末尾。如果找到终止空字符,扫描也会停止。
令牌的此结尾将自动替换为空字符,并且令牌的开头由函数返回。
一旦在对 strtok 的调用中找到 str 的终止空字符,则对此函数的所有后续调用(以空指针作为第一个参数)都将返回空指针。
找到最后一个令牌的点由要在下一次调用中使用的函数在内部保留(不需要特定的库实现来避免数据争用)。

具体使用请看下面代码:

int main()
{
	char arr[] = "zpengwei@yeah.net@666#777";
	char copy[30];
	strcpy(copy, arr);

	char sep[] = ".@#";
	char* ret = NULL;

	for (ret = strtok(copy, sep); ret != NULL; ret=strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}
	return 0;
}

字符串函数和字符函数,C语言,C语言的进阶,字符串函数,字符函数

在第一次调用的时候,需要对需要拆分的字符串写进去(程序中的copy),当使用strtok函数对copy拆分之后,该函数可以想象为有记忆功能,相当于该函数有某个指针,在第一次调用后,指针会指向”拆分的字符串“拆分标志字符之后的一个位置(@后的y),对该字符串拆分第一个参数用空指针即可,函数会根据你给的字符串(sep)中的字符进行匹配对比,只要”拆分的字符串“中有sep中的字符,那么将会对字符串进行拆分。直至走到”拆分的字符串“的终止字符就停下来。

memcpy()

void * memcpy ( void * destination, const void * source, size_t num );
复制内存块
将字节数的值从源指向的位置直接复制到目标指向的内存块。
源指针和目标指针指向的对象的基础类型与此函数无关;结果是数据的二进制副本
该函数不检查源中的任何终止空字符 - 它总是准确地复制字节数。
为避免溢出,目标和源参数指向的数组大小应至少为字节数,并且不应重叠

相比于strcpy()不再只是局限于字符串,它是可以任意类型的。
如,可以将整型数组中的元素进行复制:

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	//将arr1中的内容,拷贝到arr2中
	memcpy(arr2, arr1, 40);
	int i = 0;
	for (i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}

	return 0;
}

1 2 3 4 5 6 7 8 9 10 0 0 0 0 0 0 0 0 0 0

要记住memcpy是根据字节进行复制的,如将上面的memcpy改为:

memcpy(arr2, arr1, 37);

由于小端的存储方式所以打印出来和上面结果一致;
字符串函数和字符函数,C语言,C语言的进阶,字符串函数,字符函数

memcpy()的模拟实现

代码:

void* my_strcpy(void* dest,const void* src,size_t num)
{
    void* ret=dest;
    assert(src&& dest);

    while(num--)
    {
        *(char*)dest=*(char*)src;
        dest=(char*)dest+1;
        src=(char*)src+1;
    }
    return ret;
}

思路大体和strcpy()一致,主要当指针在移动的时候,由于参数类型是void*,且 num是size_t类型的,所以在移动指针的时候需要对指针先强制转换,赋值也一样,这样就可以在num的限制下完成操作;

在上面的介绍函数中说过,memcpy()是不可重叠的,具体如下:

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };	
	my_memcpy(arr1+2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
			printf("%d ", arr1[i]);
	}
	return 0;
}

当我们想从数组中复制该数组成 1 2 1 2 3 4 5 8 9 10的时候,我们试着运行代码,结果是:1 2 1 2 1 2 1 8 9 10,发现答案与预想情况不一致,这是因为当要将3复制过去给5之前,3由于1的复制已经变为1了,所以无法达到效果;

在这里,如果我们要实现这种可重叠的效果,就可用到memmove()函数来解决。

memmove()

void * memmove ( void * destination, const void * source, size_t num );
移动内存块
将字节数的值从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样,允许目标和源重叠。
源指针和目标指针指向的对象的基础类型与此函数无关;结果是数据的二进制副本。
该函数不检查源中的任何终止空字符 - 它总是准确地复制字节数。
为避免溢出,目标参数和源参数指向的数组的大小应至少为字节数。

从描述介绍中知道,该函数功能与memcpy函数几乎一致,唯一不同的就是可重叠;

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };	
	memmove(arr1+2, arr1, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
			printf("%d ", arr1[i]);
	}
	return 0;
}

1 2 1 2 3 4 5 8 9 10

memmove()的模拟实现

代码:

void* my_memmove(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);

	if (dest < src)
	{
		//前->后
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后->前
		while (num--)//20
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

在这里,需要判断dest与src的位置,
字符串函数和字符函数,C语言,C语言的进阶,字符串函数,字符函数
主要看重叠的位置,清楚谁给谁赋值,赋值不能改变源数组中的内容即可;

memset()

void * memset ( void * ptr, int value, size_t num );
填充内存块
将 ptr 指向的内存块的第一个字节数设置为指定值(解释为无符号字符)。

函数相当于对数组进行初始化,可以设置指定值,当然也是以字节为准;
所以不要出现以下这种错误:
例如说想要给整型数组初始化为1,那么这样结果将会不符合预期。

int main()
{
    int arr1[]={1,2,3};
    memset(arr1,1,12);
    printf("%d",arr1[0]);
    return 0;
}

答案:16843009 相当于0x01010101;

所以该函数经常使用在对字符数组的初始化;文章来源地址https://www.toymoban.com/news/detail-551458.html

到了这里,关于字符串函数和字符函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(下))

    上篇文章介绍了一些常用的字符串函数,大家可以跳转过去浏览一下:c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(上))_总之就是非常唔姆的博客-CSDN博客 今天接着来介绍一些:  目录 一.字符串查找 1.strstr() 1.1示例 1.2注意事项: 1.3模拟实现  2.

    2024年02月07日
    浏览(33)
  • 【C进阶】字符串函数

     C语言中对字符和字符串的处理很频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中 字符串常量适用于那些对它不做修改的字符串函数 本章重点介绍处理字符串函数的库函数的使用和注意事项 这些函数都要引头文件: #includestring.

    2024年02月08日
    浏览(26)
  • 【再识C进阶3(上)】详细地认识字符串函数、进行模拟字符串函数以及拓展内容

           小编在写这篇博客时,经过了九一八,回想起了祖国曾经的伤疤, 勿忘国耻,振兴中华!加油,逐梦少年! 💓作者简介: 加油,旭杏,目前大二,正在学习 C++ , 数据结构 等👀 💓作者主页:加油,旭杏的主页👀 ⏩本文收录在:再识C进阶的专栏👀 🚚代码仓库

    2024年02月07日
    浏览(28)
  • C语言:字符函数和字符串函数(一篇拿捏字符串函数!)

    目录 求字符串长度: 1. strlen(字符串长度) 长度不受限制函数: 2. strcpy(字符串拷贝) 3. strcat(字符串追加) 4. strcmp(字符串比较) 长度受限制函数: 5. strncpy(字符串拷贝) 6. strncat(字符串追加) 7. strncmp(字符串比较) 字符串查找: 8. strstr(查找字符串子串) 9. strtok(字符串分割) 错误信

    2024年02月10日
    浏览(83)
  • R语言 | 进阶字符串的处理

    目录 一、语句的分割  二、修改字符串的大小写  三、unique()函数的使用  四、字符串的连接 4.1 使用paste()函数常见的失败案例1 4.2 使用paste()函数常见的失败案例2 4.3 字符串的成功连接与collapse参数 4.4 再谈paste()函数 4.5 扑克牌向量有趣的应用 五、字符串数据的顺序 六、查找

    2024年02月02日
    浏览(31)
  • 【C语言】字符函数,字符串函数,内存函数

    大家好!今天我们来学习C语言中的字符函数,字符串函数和内存函数。 目录 1. 字符函数 1.1 字符分类函数 1.2 字符转换函数 1.2.1 tolower(将大写字母转化为小写字母) 1.2.2 toupper(将小写字母转化为大写字母) 2. 字符串函数 2.1 字符串输入函数 2.1.1 gets() ​2.1.2 fgets() 2.2 字符串

    2024年02月10日
    浏览(46)
  • C语言——字符函数和字符串函数

    assert.h 头文件定义了宏assert(),⽤于在运⾏时确保程序符合指定条件,如果不符合,就报 错终⽌运⾏。这个宏常常被称为 “断⾔” 。 assert() 宏接受⼀个表达式作为参数。如果该表达式为真(返回值⾮零), assert() 不会产⽣任何作⽤,程序继续运⾏。如果该表达式为假(

    2024年04月25日
    浏览(46)
  • C语言:字符函数和字符串函数

    C语言:初识C语言 C语言:分支语句和循环语句 C语言:函数 C语言:数组 C语言:操作符详解 C语言:指针详解 C语言:结构体 C语言:数据的存储 今天来盘一下字符函数和字符串函数。 C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常

    2024年02月11日
    浏览(58)
  • C语言—字符函数和字符串函数

    C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串中或者字符数组中。字符串常量适用于那些对它不做修改的字符串函数。 strlen函数的介绍 strlen函数用于求字符串的长度 注: 字符串已经 ‘\\0’ 作为结束标志,strlen函

    2024年02月07日
    浏览(36)
  • 【C语言】字符函数和字符串函数

      目录 1.求字符串长度strlen 2.长度不受限制的字符串函数 字符串拷贝strcpy 字符串追加strcat 字符串比较strcmp 3.长度受限制的字符串函数介绍strncpy strncat ​编辑strncmp 4.字符串查找strstr 5.字符串分割strtok 6.错误信息报告 strerror perror 7.字符分类函数 8.字符转换函数  9.内存操作函

    2024年02月12日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包