c语言(进阶)学习笔记11

  • 求字符串长度

  1. strlen
  • 长度不受限制的字符串函数

  1. strcpy
  2. strcat[重要][模拟实现]
  3. strcmp[重要][模拟实现]
  • 长度受限制的字符串函数
  1. strncpy
  2. strncat
  3. strncmp
  • 字符串查找
  1. strstr[重要][模拟实现]
  2. strtok[陌生]
  • 错误信息报告
  1. strerror[陌生]
  2. perror[陌生]
  • 字符操作
  • 内存操作函数
  1. memcpy
  2. memmove[重要][模拟实现]
  3. memset
  4. memcmp

字符函数和字符串函数

求字符串长度

strlen

size_t strlen ( const char * str );

  •  字符串已经以'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0' )。
  • 参数指向的字符串必须要以'\0'结束。
  • 函数的返回值为size_t,是无符号的(易错)。

模拟实现

#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* str)
{
    assert(str != NULL);
	int count = 0;
	while (*str)
	{
		++count;
		++str;
	}
	return count;
}
void main()
{
	char str[] = "Hello World!";
	printf("%zd", my_strlen(str));
}

长度不受限制的字符串函数

strcpy

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

  • Copies the C string pointed by source into the array pointed by destination, including the terminating null character(and stopping at that point).
  • 源字符串必须以'\0'结束。
  • 会将源字符串中的'\0'拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。
  • 返回值为目标地址

*strcat

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

  • Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null character is included at the end of the new string formed by the concatenation of both in destination.

  • 检测到源字符串的第一个'\0'就开始追加。[注意]

  • 源字符串必须以'\0'结束

  • 目标空间必须有足够的大,能容纳下源字符串的内容。

  • 目标空间必须可修改。

  • 字符串无法自己给自己追加。

  • 返回值为目标地址

模拟实现

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* destination, const char* source)
{
    assert(destination && source);
	char* ret = destination;
	while (*destination)
		++destination;
	while (*destination++ = *source++);
//利用符号优先级,++高于=
	return ret;
//返回初始的目的地址
}
void main()
{
	char str1[20] = "Hello ";
	char str2[] = "World!";
	printf("%s\n", my_strcat(str1, str2));
}

strcmp

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

  • This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.
  • 标准规定∶
  1. 第一个字符串大于第二个字符串,则返回大于0的数字。
  2. 第一个字符串等于第二个字符串,则返回0。
  3. 第一个字符串小于第二个字符串,则返回小于0的数字。

模拟实现

int my_strcmp(const char* str1, const char* str2)
{
	int ret = 0;
	while ((ret = *(unsigned char*)str1 - *(unsigned char*)str2) == 0 && *str2)
	{
		str1++;
		str2++;
	}
	return ((-ret) < 0) - (ret < 0);
}
void main()
{
	printf("%d", my_strcmp("abcdef", "abcdh"));
}

长度受限制的字符串函数

strncpy

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

  • 若num超过源字符串的长度,则剩下的部分会以'\0'来进行替换。

strncat

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

  • 若num超过源字符串的长度,函数识别到源字符串末尾'\0'之后直接停止。
  • 若num小于源字符串的长度,函数会在末尾添上'\0'而后停止。

strncmp

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

  • n来指示所需要比较的位数。

字符串查找

*strstr[重要]

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

  • Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.

*模拟实现[重要]

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
char* my_strstr(const char* str1, const char* str2)
{
	const char* s1 = NULL;
	const char* s2 = NULL;
	char* cp = (char*)str1;
	if (!*str2)
		return (char*)str1;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 && *s2 &&(*s1 == *s2))
			s1++,s2++;
		if (!*s2)
			return cp;
		cp++;
	}
	return NULL;
}
void main()
{
	char str1[] = "abcdefghijk";
	char str2[] = "ijk";
	char* ret = my_strstr(str1, str2);
	if (ret == NULL)
		printf("未找到!\n");
	else
		printf("找到了!\n%s\n", ret);
}

strtok[限制酶]

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

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

使用方式

错误信息报告

strerror[把错误码转为错误信息]

char * strerror ( int errnum );

配合c语言自带的全局变量错误码使用可以报出当前的错误信息

变量引用的头文件-------errno.h

变量名称-------------------errno

perror[直接输出错误信息]

void perror ( const char * str ); 

perror("接入自定义信息");

头文件:stdio.h

字符操作

头文件:#include<ctype.h>

字符分类函数

int 函数名 ( int c );

如果是满足条件返回非0值,不满足条件返回0。

函数如果它的参数符合下列条件就返回真
iscntrl任何控制字符
isspace空白字符:空格' '  换页'\f'  换行'\n'  回车'\r'  制表符'\t'或者垂直制表符'\v' 
isdigit十进制数字 0~9
isxdigit十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower小写字母a~z
isupper大写字母A~Z
isalpha字母a~z或A~Z
isalnum字母或者数字,a~z,A~Z,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符

字符转换函数

  • tolower(转小写)
  • toupper(转大写)

int tolower ( int c );

int toupper ( int c );

使用情况

内存操作函数

头文件#include <string.h>或#include<memory.h>

内存拷贝函数

*拷贝的三种类型--决定从左往右拷贝还是从右往左拷贝

1.source与destination所指向的内存完全不重叠

2.有重叠区域,并且destination小于source

3.有重叠区域,并且source大于destination

左往右拷贝还是从右往左拷贝取决于调整后红框在前

*memcpy

void * memcpy ( void * destination, const void * source, size_t num );

以字节为单位拷贝

返回destination的指针

(memcpy函数应该拷贝不重叠的内存 拷贝重叠内存可能出现问题)

(vs中既可以拷贝不重叠,也可以拷贝重叠内存,尽量以标准实现)

模拟实现

#include<stdio.h>
void* my_memcpy(void* destination, const void* source, size_t num)
{
	void* ret = destination;
	while (num--)
	{
		*(char*)destination = *(char*)source;
        destination = (char* )destination +1;
        source = (char* )source +1;
//标准的写法,使用++会在部分编译器内报错
	}
	return ret;
}
void main()
{
	int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
	int arr2[20] = {0};
	my_memcpy(arr2, arr1, 20);
	for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); ++i)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
}

注:(char*)为暂时性的强制类型转换与*和++配合使用容易出错,不同编译器下括号使用不同,采用+1来进行更为标准。

vscode

vs2022

*memmove

void * memcpy ( void * destination, const void * source, size_t num );

以字节为单位拷贝

返回destination的指针

(memmove函数可以拷贝不重叠的内存)(与memcpy功能类似)

模拟实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
void* my_memmove(void* dest, void* src, size_t num)
{
	if (dest > src)
		for (int i = num - 1; i >= 0; --i)
			((char*)dest)[i] = ((char*)src)[i];
	else
		for (int i = 0; i < num; ++i)
			((char*)dest)[i] = ((char*)src)[i];
	return dest;
}
void main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	//my_memmove(arr1 + 2, arr1, 20);
	my_memmove(arr1, arr1 + 2, 20);
	for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); ++i)
	{
		printf("%d ", arr1[i]);
	}
	printf("\n");
}

memset

void * memset ( void * ptr, int value, size_t num );

  • 以字节为单位设置内存。
  • value该值以int类型传递,但该函数使用此值的无符号char类型转换填充内存块。

使用情况

内存比较函数

memcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

<0两个内存块中不匹配的第一个字节在 ptr1 中的值低于 ptr2 中的值(如果计算以无符号字符值)
0两个内存块的内容相等
>0两个内存块中不匹配的第一个字节在 ptr2 中的值大于在 ptr2 中的值(如果计算以无符号字符值)

使用情况

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值