C语言详细分析常见字符串函数与模拟实现

目录
  • 一. strlen(求长度)
  • 二. strcpy(拷贝)
  • 三.strcat(追加)
  • 四.strcmp
  • 五.strncpy
  • 六.strncat
  • 七.strncmp
  • 八.strstr
  • 九.strtok
  • 十.strerror
  • 十一.memcpy
  • 十二.memmove
  • 十三.memcmp
  • 十四.memset

一. strlen(求长度)

size_t  strlen ( const char * str )

函数的返回值类型为size_t,为无符号数,且strlen返回值为字符串中‘\0’前的字符个数。

猜猜这个程序的输出

if (strlen("abc") - strlen("abcdef"))
	{
		printf(">");
	}
	else
	{
		printf("<");
	}

没错,是 >

因为strlen的返回值为无符号数,-3变成了一个很大的正整数。

二. strcpy(拷贝)

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

使用时,源字符串必须以\0结尾,并且'\0'也会拷过去

strcpy:"我不管你放不放得下,我就拷。"

目标地址必须够大且可修改,不然的话,虽然可以放进去,但是程序会崩溃

strcpy的模拟实现

char* my_strcpy(char* dest,const char* source)
{
	assert(dest && source);
	char* ret = dest;
	while (*dest++ = *source++);
	return ret;
}

三.strcat(追加)

char  * strcat ( char * destination , const char * souce)

源字符串必须有'\0',目标字符串也得有'\0'

追加后,目标空间的'\0'无了,源字符串的'\0'添加上

目标地址必须够大且可修改

strcat的模拟实现

char* my_strcat(char* dest,char* source)
{
	assert(dest && source);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *source++);
	return ret;
}

四.strcmp

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

strcmp函数比较的不是字符串的函数长度`

而是比较字符串中对应位置上的字符的大小,如果相同,就比较下一对字符,知道不同,或者遇到'\0'.

若相同则返回0,若大于则返回大于零的数。若小于则返回小于零的数

strcmp的模拟实现

int my_strcmp(const char* str, const char* qtr)
{
	assert(str && qtr);
	while (*str == *qtr)
	{
		if (*str == '\0')
			return 0;
		str++;
		qtr++;
	}
	if (*str > *qtr)
		return 1;
	else
		return -1;
}

五.strncpy

char * strncpy ( char * dest, const char * source , size_t count)

作用是将源字符串的前count个字符拷贝到目标字符串

char a[] = "abcd";
char b[] = "qwer";
strncpy(a,b,1);

如以上修改后字符串为qbcd

strncpy的模拟实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdlib.h>
#include<stdio.h>

void my_strncat(char*dest,char*src,size_t n)
{
	int t = strlen(dest);
	int f = strlen(src);
	for (int i = 0; i < n; i++)
	{
		*(dest + i) = *src;
		src++;
	}
}

int main()
{
	int n;
	scanf("%d", &n);
	char src[50], dest[50];
	strcpy(dest, "NICE");
	strcpy(src, "SHOOT");
	my_strncat(dest,src,n);
	printf("%s", dest);
}

六.strncat

char * strncat ( char * dest , const char * source ,size_t  count)

作用是将源字符串的前count个字符追加到dest后面、

并且会在结尾加上‘\0’

char arr1[]="abcdef\0xx";
char arr2[]="qwer";
strncat(arr1,arr2,2);

修改后为abcdefqw

strncat的模拟实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void my_strncpy(char* str, char* qtr, int size)
{
	assert(str && qtr);
	int t = strlen(str);
	for (int i = 0; i < size ; i++)
	{
		*(str + t + i) = *qtr;
		qtr++;
	}
	*(str + t + size) = '\0';
}
int main()
{
	char src[50], dest[50];
	strcpy(src, "A nice");
	strcpy(dest, " BOYYYYYYY");
	int n = 0;
	scanf("%d", &n);
	my_strncpy(src, dest, n);
	printf("%s", src);
}

七.strncmp

int strncm ( const char * str , const char * qtr , size_t num )

指定比较前num个字符,其他同strcmp一样

八.strstr

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

用于查找子串,返回第一次找到的地址

九.strtok

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

参数sep是由分隔符组成的一个字符串

str为一个字符串,包含sep中零个或者多个分隔符.

strtok会找到str中第一个分隔符,并把其替换成'\0',返回一个指向这个分隔符的指针

若第一个参数为'\0'',则从上一波保存的位置向后查找另一个分隔符

若字符串中不存在更多的分隔符,则返回NULL指针

	char a[] = "A@nice.boy";
	char sep[] = "@.";
	printf("%s", strtok(a, sep));
	printf("%s", strtok(NULL, sep));

如以上结果为Anice

    char a[] = "A@nice.boy";
	const char sep[] = "@.";
	char arr[30];
	char* str = NULL;
	strcpy(arr, a);
	for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s", str);
	}

以上输出为Aniceboy

十.strerror

char * strerror (int errnum )

errno是一个全局变量,记录最后的错误代码,程序刚刚启动的时候,errno 被设置为 0;程序在运行过程中,任何一个函数发生错误都有可能修改 errno 的值,让其变为一个非零值,用以告知用户发生了特定类型的错误。

十一.memcpy

void * memcpy ( void* dest , const void * source ,size_t count)

作用是将源字符串的前count个字节拷贝到dest上

int a1[20] = {1,2,3,4,5,6,7,8};
int a2[5] = {0};
memcpy(a1,a2,20);

执行后,a1数组前五个元素变成0

memcpy的模拟实现:

由于memcpy的拷贝是一个字节一个字节进行的

可用以下代码模拟实现

void* my_memcpy(void* dest, const void* source, size_t count)
{
	assert(source && dest);
	void* ret = dest;
	while (count--)
	{
		*(char*)dest = *(char*)source;
		source=(char*)source+1;
		dest=(char*)dest+1;
	}
	return ret;
}

十二.memmove

void * memmove (void * dest ,const void * source ,size_t count)

可以实现重叠内存拷贝

模拟实现:

void* my_memmove(void* dest, const void* source, size_t count)
{
	if (dest < source)
	{
		while(count--)
		{
		*(char*)dest = *(char*)source;
		dest = (char*)dest + 1;
		source = (char*)source + 1;
		}
	}
	else
	{
		while (count--)
		{
			*((char*)dest + count )= *((char*)source + count);
		}
	}
}

十三.memcmp

void * memcpy ( void * str , const void * qtr , size_t count)

比较str和qtr的前count个字节,注意是一个字节一个字节比较

这就很有意思了

请看以下代码

int a[5] = { 1,2,3,4,5 };
int b[5] = { 1,2,3,4,0x11223305};
memcmp(a,b,16);

很明显数组的前十六个字节相同,会返回0,但如果是前十七个呢

这是因为

5存储为  05 00 00 00

0x11223305为   05 33 22 11

十四.memset

void * memset ( void * dest , int c ,size_t count)

作用是将前count个字节改成参数c

int a[]={0,0x22222222};
memset(a,1,8);

如以上a数组变为0x01010101,0x0101010101

到此这篇关于C语言详细分析常见字符串函数与模拟实现的文章就介绍到这了,更多相关C语言 常见字符串函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言字符串函数介绍与模拟实现详解

    目录 2. strcpy(复制字符串) 2.1 strncpy函数 2.2 模拟实现strcpy 3. strcat (追加字符) 3.1 strncat 函数 3.2 模拟实现strcat 4. strcmp(比较两个字符串内容) 4.1 strncmp函数 4.2 模拟实现strcmp 5. strstr (返回str1出现在str2位置处第一次的指针) 5.1 模拟实现strstr 6. strtok(分割字符串) 总结 1. strlen(求字符串长度) 这个函数就是求一个字符串的长度.

  • 一篇文章教你用C语言模拟实现字符串函数

    目录 前言 模拟 1.strlen 函数 2.strcpy 函数 3.strcat 函数 4.strcmp函数 5.strncpy函数 6.strncat函数 7.strncmp函数 8.strstr函数 9.strtok函数 总结 前言 编程过程中经常会使用到一些字符串函数,这些字符串函数都在C语言标准库中,我们可以直接使用.但我们也要了解一下它们是如何实现的. 模拟 1.strlen 函数 strlen函数是用来求字符串长度的.官方给出的解释如图 返回值类型是无符号整型,参数类型是char*

  • C语言详细分析常见字符串函数与模拟实现

    目录 一. strlen(求长度) 二. strcpy(拷贝) 三.strcat(追加) 四.strcmp 五.strncpy 六.strncat 七.strncmp 八.strstr 九.strtok 十.strerror 十一.memcpy 十二.memmove 十三.memcmp 十四.memset 一. strlen(求长度) size_t  strlen ( const char * str ) 函数的返回值类型为size_t,为无符号数,且strlen返回值为字符串中‘\0’前的字符

  • C语言详细分析讲解内存管理malloc realloc free calloc函数的使用

    目录 C语言内存管理 一.动态空间申请 二.动态空间的扩容 三.释放内存 C语言内存管理 malloc && realloc && free && calloc c语言中为了进行动态内存管理,<stdlib.h>中提供了几个函数帮助进行内存管理. 我们知道,C语言中是没有C++中的容器或者说是python中list,set这些高级的数据结构的,我们一旦申请了一段内存空间以后这一段空间就归你了,比如我们举个例子,我们申请一个数组 int nums[

  • C语言详细讲解常用字符串处理函数

    目录 一.strlen() 1. 函数原型: 2. 手动实现: 二.strcat() 1. 函数原型: 2. 手动实现: 三.strcpy() 1. 函数原型: 2. 手动实现: 四.strcmp() 1. 函数原型: 2. 手动实现: 五.memset() 1. 函数原型: 2. 手动实现: 一.strlen() 1. 函数原型: size_t strlen(const char *str) 参数str: 要计算的字符串的长度返回值: 返回字符串 str 的长度,直到遇到结束字符'\0',但不

  • C语言详细分析讲解关键字const与volatile的用法

    目录 一.const 只读变量 二.const 全局变量的分歧 三.const 的本质 四.const 修饰函数参数和返回值 五.volatile 解析 六.小结 一.const 只读变量 const 修饰的变量是只读的,本质还是变量 const 修饰的局部变量在栈上分配空间 const 修饰的全局变量在全局数据区分配空间 const 只在编译期有用,在运行期无用 const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边. 二.const 全局变量的分歧 在现代C语言编

  • C语言详细分析宏定义与预处理命令的应用

    目录 宏定义与预处理命令 预处理命令 - 宏定义 定义符号常量 定义傻瓜表达式 定义代码段 预定义的宏 函数 VS 宏定义 预处理命令 - 条件式编译 示例 宏定义与预处理命令 预处理阶段:处理宏定义与预处理命令: 编译期:检查代码,分析语法.语义等,最后生成.o或.obj文件: 链接期:链接所有的.o或.obj文件,生成可执行文件. 预处理命令 - 宏定义 定义符号常量 #define PI 3.1415926 #define MAX_N 10000 定义傻瓜表达式 #define MAX(a

  • C语言 详细分析结构体的内存对齐

    目录 一.结构体 二.结构体内存对齐 1.非嵌套结构体的大小 2.含嵌套结构体的大小 三.为什么要内存对齐 1.平台原因(移植原因) 2.性能原因 一.结构体 结构体 (struct)是一种数据结构,可以包含很多数据类型,可以实现比较复杂的数据结构. 常见的int,char类型变量,我们可以一眼看出占多少字节,但对于结构体,可就有点难度了. 让我们来猜猜以下程序的输出 struct S1 { char c1; int i; char c2; }; struct S2 { char c1; cha

  • C语言详细分析讲解struct与union使用方法

    目录 一.struct 的小秘密 二.结构体与柔性数组 三.C语言中的 union 四.小结 一.struct 的小秘密 C语言中的 struct 可以看作变量的集合 struct 的问题:空结构体占用多大内存?下面编写程序看一下吧: #include <stdio.h> struct TS { }; int main() { struct TS t1; struct TS t2; printf("sizeof(struct TS) = %d\n", sizeof(stru

  • C语言详细分析宏定义的使用

    目录 一.C语言中函数的“缺陷” 二.再次理解函数 三.C语言中的宏 四.宏与函数的不同 五.编译器组成简介 六.宏使用示例 七.再论宏常量 八.小结 一.C语言中函数的“缺陷” 实参和形参之间仅仅是值传递,因此,函数中无法直接改变实参. 二.再次理解函数 函数是一种代码复用的手段 把实现某个功能的代码片段进行封装(当作一个整体) 给这个代码片段一个合适的名字(通过名字使用代码) 定义参数(定义代码片段需要处理的问题) 三.C语言中的宏 宏是C语言中代码复用的补充方式 宏定义语法:#define

  • C语言详细分析讲解多文件的程序设计

    目录 一.多文件与编译器链接 二.多文件之间的相互访问 三.关于#include 四.头文件使用的一些原则 五.再论全局变量 六.注意事项 七.实验程序 八.小结 一.多文件与编译器链接 如下图所示,.o 为目标文件,链接器将不同的目标文件装配组合在一起形成一个可执行文件. 二.多文件之间的相互访问 每个文件可以定义功能接口(可被其它文件访问的函数或数据) 源文件:代码实现文件,后缀为.c 头文件:源文件的接口定义文件,后缀为.h 当需要使用其它文件提供的功能时,包含对应的头文件 语法: #in

  • C语言详细i讲解qsort函数的使用

    目录 qsort 1.int型 2.float型 3.struct型 qsort 功能:Performs a quick sort.(快速排序) 参数:void qsort( void *base, size_t num, size_t width, int (*cmp )(const void *e1, const void *e2 ) ); 头文件:#include <stdlib.h> 用法: 第一个参数待排数组的首元素地址 第二个参数待排数据个数 第三个待排数据中每个参数的大小——单位

随机推荐