入门学习计算机第十七天—字符串函数使用和剖析

入门学习计算机第十七天—字符串函数使用和剖析

编译器:Microsoft Visual Studio 2019

前言:
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 或者 字符数组中,字符串常量适用于那些对它不做修改的字符串函数。

字符函数介绍 :

strlen: 字符串长度

size_t strlen (const char* str)
//typedef unsigned int  size_t 
  • 字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’ 前面出现的字符个数。
  • 参数指向的字符串必须要以’\0’结束。
  • 注意函数的放回值为size_t ,是无符号的(易错)
int main()
{
	if (strlen("abc") - strlen("abcdef") > 0)
	{
		printf("hehe");
	}
	else
	{
		printf("haha");
	}
	return 0;
}

输出的结果是 “hehe”
strlen 返回值的类型是无符号数,两个无符号数相减,得到的结果依然是无符号数

不创建临时变量,求字符串长度

int my_strlen(char* a)
{
	if (*a != 0)
		return 1 + my_strlen(a + 1);
	else
		return 0;
}
int main()
{
	char arr[] = "abcdef";	
	printf("%d\n", my_strlen(arr));
		return 0;
}

输出的结果是6。

strcpy 字符串拷贝

char*  strcpy(char* destination ,const char* source);
  • 原字符串以’\0’结束
  • 会将字符串中的’\0’拷贝到目标空间
  • 目标空间必须足够大,以确保能存放原字符串
  • 目标空间必须可变

模拟实现strcpy

char* my_strcpy(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* ret = dest;
	//拷贝src指向的字符串到dest指向的空间,包含'\0'
	while (*dest++ = *src++)
	{
		;
	}
	//返回目的空间的起始地址
	return ret;
}
int main()
{
	char arr1[] = "abcdefghi";
	char arr2[] = "bit";
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

strcat 字符串追加

char* strcat (char* destnation, const char* source);
  • 原字符串以’\0’结束
  • 目标空间必须足够大,以确保能容纳原字符串的内容
  • 目标空间必须可修改
  • 字符串自己给字节追加?

模拟实现 strcat

char* my_strcat(char* dest, const char* src)
{
    assert(dest);
    assert(src);
    char* ret = dest;
    //1.找到目的字符串的'\0'
    while (*dest != '\0')
    {
        dest++;
    }
    //2.追加
    while (*dest++ = *src++)
    {
        ;
    }
    return ret;
}

int main()
{
    char arr1[50] = "hello";
    char arr2[] = "world";
    my_strcat(arr1, arr2);
    printf("%s\n", arr1);
    return 0;
}

strcmp 字符串比较

int strcmp(const char *str1 , const char * str2)
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,返回0
  • 第一个字符串小于第二个字符串,返回小于0的数字
int main()
{
	const char* p1 = "chen";
	const char* p2 = "wen";
	int rent = (strcmp(p1, p2));
	printf("%d\n", rent);
	return 0;

}

输出的值是 -1

模拟实现strcmp

int my_strcmp(const char* a1, const char* a2)
{
	while (*a1 ==*a2)
	{
		if (*a1 == '\0')
		{
			return 0;//相等
		}
		a1++;
		a2++;
	}
	if (*a1 > *a2)
		return 1;//
	else
		return -1;
}
int main()
{
	const char* p1 = "chen";
	const char* p2 = "when";
	printf("%d\n", my_strcmp(p1, p2));
	return 0;
}

strncpy 长度受限制的字符拷贝

char* strncpy(char* strDest, const* strSource , size_t count) //count 的单位是字节
  • 拷贝num个字符从原字符串到目标空间
  • 如果原字符串的长度小于num,则拷贝完原字符串之后,在目标的后边追加0,直至num个
int main()
{
	char arr1[10] = "abcdefgh";
	char arr2[] = "hello bit";
	strncpy(arr1, arr2, 5);
	printf("%s\n", arr1);
	return 0;

}

输出的结果是
在这里插入图片描述
模拟实现strncpy

char* my_strncpy(char* arr1, char* arr2, int count)
{
	char* start = arr1;
	while (count && (*arr1++ = *arr2++))
	{
		count--;
	}
	if (count)
	{
		while (--count)
		{
			*arr1++ = '\0';
		}
	}
	return start;
}

int main()
{
	char arr1[10] = "ab";
	char arr2[] = "hello bit";
	my_strncpy(arr1, arr2, 10);
	printf("%s\n", arr1);
	return 0;

}

strncat 长度受限制的字符追加

char* strncat(char* strDest, const char* strSource, size_t count)
int main()
{
   char arr1[30] = "hello\0XXXXXXX";
   char arr2[] ="world";
   strncat(arr1,arr2,3);//strncat会主动补\0
   printf("%s\n",arr1);
}

在这里插入图片描述
模拟实现strncat

char* my_strncat(char* front, const char* back, size_t count)
{
	char* start = front;
	while (*front++)
	{
		;
	}
	front--;
	while (count--)
	{
		if (!(*front++ = *back++))
		{
			return start;
		}
    }
	*front = '\0';
	return start;
}

int main()
{
	char arr1[30] = "hello";
	char arr2[]= "world";
	my_strncat(arr1, arr2, 3);//strncat会主动补\0
	printf("%s\n", arr1);
}

strncmp 长度受限制的字符比较

int strncmp(const char* str1 , const char* str2 ,size_t num);
  • 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
int main()
{
	char arr1[30] = "hello";
	char arr2[]= "helle";
	int ret = strncmp(arr1, arr2, 4);//strncat会主动补\0
	printf("%d\n",ret );
	return 0;
}

输出的结果是0

模拟实现strncmp

strstr 寻找子字符串

char* strstr(const char* string, const char * strCharSet)
int main()
{
 char* p1 = "abcdef";
 char* p2  = "def";
 char* ret = strstr(p1,p2);
 if(ret == NULL)
 {
   printf("子串不存在\n");
 }
   else
   {
      printf("%s\n",ret);
   }   
  return 0;
}

模拟实现

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1);
	assert(str2);
	const char* s1 = str1;
	const char* s2 = str2;
	const char* cur = str1;
	if (*str2 == '\0')
	{
		return (char*)str1;
	}
	while (*cur)
	{   
		s1 = cur;
		s2 = str2;
		while ((*s1!='\0') && (*s2 != '\0') && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cur;
		}
		if (*s1 == '\0')
		{
			return NULL;
		}
		cur++;
	}
	return NULL;//找不到子串
}


int main()
{
	char arr1[30] = "abcdefgih";
	char arr2[]= "defasdawrawra";
	const char* len = my_strstr(arr1, arr2);
	printf("%s\n",len );
	return 0;
}

strtok 提取被符号分割的字符串

char* strtok(char* str ,const char* sep)
  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串一个或者多个分隔符分割的标记
  • strtok 函数找到了str中的下一个标记,并将其用\0结尾 ,返回一个指向这个标记的指针(注:strtok函数会改变被操作的字符串找到str中的下一个标记,所以使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)
  • strtok函数的第一个参数不为NULL,函数将找到str第一个标记,strtok函数将保存它在字符串中的位置
  • strtok函数的第一个参数为NULL,函数将同一个字符串中被保存的位置开始,查找下一个标记
  • 如果字符串不存在更多的标记,则返回NULL指针

函数的基本使用

int main()
{
	char arr[] = "abcd.ad.w@er";
	const char* p = "@.";
	char* len = NULL;
	for (len = strtok(arr, p); len != NULL; len = strtok(NULL, p))
	{
		printf("%s\n", len);
	}

	return 0;
}

在这里插入图片描述
strerror 错误信息函数 需要引头文件<errno.h>

char* strerror(int errnum);
//返回错误码,所对应的错误信息

errno 是一个全局的错误码变量
当C语言的库函数在执行过程中,发生了错误,将会把对应的错误码,赋值到errno中
函数使用:打开text.txt文件

int main()
{
	FILE* pf = fopen("text.txt", "r");//打开文件
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	else
	{
		printf("open file success\n");
	}
	return 0;
}

当code文件夹下没有text.txt文件时:
在这里插入图片描述
没有该文件或者目录
当文件下有text.txt文件时
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述字符转换:需要引头文件 <ctype.h>

 int tolower(int c);//大写转小写
 int toupper(int c);//小写转大写
int main()
{
  char arr = tolower("Q");
  putchar(arr);
}

输出的结果是q

将一个字符串全部打印成小写

int main()
{
	char arr[] = "I Am A Student";
	int i = 0;
	while (arr[i])
	{
		if (isupper(arr[i]))//判断是否为大写
		{
			arr[i] = tolower(arr[i]);
		}
		i++;
	}
	printf("%s\n", arr);
	return 0;
}

输出的结果为:
在这里插入图片描述

内存函数

memmove: 内存移动函数

void* memmove(void* destination ,const void* soure,size_t num);
  • 和mencpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理

memcpy: 内存拷贝函数

void* memcpy(void* destination , const void* source, size_t num)
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
  • 这个函数在遇到’\0’的时候并不会停下来
  • 如果source和destination有任何的重叠,复制的结果都是未定义的
int main()
{
  int arr1[] = {1,2,3,4,5,6};
  int arr2[] = {0};
  memcpy(arr2,arr1,6);
}

在这里插入图片描述
模拟实现memcpy函数:

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest);
	assert(src);
	void* ret = dest;
	while(num--)
	{
		*(char*)dest = *(char*)src;
		++(char*)dest;
	    ++(char*)src;
	}
	return ret;
}

int main()
{
	int arr1[] = { 1,2,3,4,5,6 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1,sizeof(arr1));
	return 0;
}

计算机知识/代码知识(零碎)

阅读文档的时候:
NULL - 空指针
NUL / Null - ‘\0’

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值