C语言之操作符详解


(一)求字符串长度函数

strlen

  strlen是求字符串长度函数,以\0为结束,长度不包括\0
  MSDN上解释为(这里的size_t是无符号整型):
            size_t strlen( const char *string );

int main()
{
	char arr1[]="abcdef";
	char arr2[]={ 'a','b','c' };
	size_t sz = strlen(arr1);
	printf("%d", sz);
	printf("%d", strlen(arr2));//打印随机值
	return 0;

  这里的arr2数组中找不到\0,strlen随即向后查找,输出随机值。

	if (strlen("abc") - strlen("abcdef") > 0)
	{
		printf("hehe\0");//打印hehe
	}
	else
	{
		printf("haha\0");
	}

  strlen返回无符号整型,计算过后不可能是负数,所以打印hehe。
  strlen的模拟实现如下,有三种方式
  1.计数器

size_t my_strlen(char* p)
{
	size_t x = 0;//计数器
	while (*p)
	{
		x++;
		p++;
	}
	return x;
}

2.指针 - 指针

size_t my_strlen(char* p)
{
	size_t x = 0;
	char* ch = p;//字符串头指针
	while (*p)
	{
		p++;
	}
	return p - ch;
}

3.递归

size_t my_strlen(char* p)
{
	if (*p)
	{
		return 1 + my_strlen(++p);
	}
	else
	{
		return 0;
	}
}

(二)字符串拷贝函数

strcpy — strncpy

  strcpy字符串拷贝函数,将一个字符串内容拷贝到另一个字符串中,遇到\0停下来,原字符串必须以\0结束。
  MSDN上解释为:
            char *strcpy( char *strDestination, const char *strSource );

int main()
{
	char arr1[] = "xxxxxxxxxxxxxxxxxx";
	char arr2[] = "hello";
	printf("%s\n", strcpy(arr1, arr2));//输出为hello
	return 0;
}

  将字符串arr2的内容拷贝到arr1中,连同\0一起拷贝过去。
  下面模拟实现strcpy函数

char* my_strcpy(char* str1,const char*  str2)
{
	assert(str1 && str2);//确保传入不为空
	char* ret = str1;
	while (*str1)
	{
		*str1++ = *str2++;
	}
	return ret;//返回目标空间的起始地址
}

  strncpy函数相对于strcpy在长度方面受限,比strcpy更加安全,可以指定拷贝字符的个数。
  MSDN上解释为:
            char *strncpy( char *strDest, const char *strSource, size_t count );

int main()
{
	char arr1[20] = "abcdefghi";
	char arr2[] = "xxx";
	strcpy(arr1, arr2, 2);
	printf("%s", arr1);//输出为xxcdefghi
	return 0;
}

  strncpy函数的模拟实现如下,

char* my_strncpy(char* str1, const char* str2, size_t count)
{
	assert(str1 && str2);//确保传入不为空
	char* ret = str1;
	for (int i = 0;i < count;i++)
	{
		*str1++ = *str2++;
	}
	return ret;//返回目标空间的起始地址
}

(三)字符串追加函数

strcat — strncat

  strcat是字符串连接/追加函数,在一个字符串末尾连接另一个字符串,原字符串必须以\0结束,且要保证目标空间大小足够。
  MSDN上解释为:
            char *strcat( char *strDestination, const char *strSource );

int main()
{
	char arr1[4] = "abf";
	char arr2[] = { 'a','b','f','\0' };//末尾必须是\0
	strcat(arr1, arr2);//出现错误,连接目标空间不够
	return 0;
}

  这时虽然打印仍然是abfabf,但是也会弹出对话框显示错误,arr1的空间不足,没有办法在后面连接,给arr1[4]分配更大的空间即可。
  下面是模拟实现strcat函数

char* my_strcat(char* dest,const char* src)
{
	assert(dest && src);
	char* ret = dest;
	//1.找到目标字符串的末尾,从\0开始
	while (*dest)
	{
		dest++;
	}
	//2.追加字符串
	while (*dest++ = *src++)//赋值dest为\0时,跳出循环
	{
		;
	}
	return ret;
}

  与strcpy和strncpy的关系类似,strncat函数相对于strcat在长度方面受限,比strcat更加安全,可以指定追加字符的个数。
  MSDN上解释为:
            char *strncat( char *strDest, const char *strSource, size_t count );

int main()
{
	char arr1[10] = "abf";
	char arr2[] = { 'a','b','f','\0' };//末尾必须是\0
	strncat(arr1, arr2, 2);
	printf("%s", arr1);//输出为abfab
	return 0;
}

  strncat函数的模拟实现如下,

char* my_strncat(char* dest,const char* src,size_t count)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	for(int i=0;i<count;i++)
	{
		*dest++ = *src++;
	}
	return ret;
}

(四)字符串比较函数

strcmp — strncmp

  strcmp是字符串比较函数,strcmp比较的是内容(即ASCII码值),不是长度,字符串1小于字符串2的时候返回-1(小于0),大于时返回1(大于0),等于时返回0。
  MSDN上解释为:
            int strcmp( const char *string1, const char *string2 );

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abc";
	int ret = strcmp(arr1, arr2);
	if (ret == 0)
		printf("=");
	else if (ch > 0)
		printf(">");
	else if(ch<0)
		printf("<");
	return 0;
}

  strcmp函数的模拟实现如下,

int my_strcmp(const char* s1,const char* s2)
{
	assert(s1 && s2);
	while (*s1 == *s2)
	{
		if (*s1 == '\0')
			return 0;  //*s1 = *s2 = \0
		s1++;
		s2++;
	}
	return *s1 - *s2;
}

  strncmp函数相对于strcmp在长度方面受限,比strcmp更加安全,可以指定比较字符的个数。

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abce";
	int ret = strncmp(arr1, arr2, 3);
	printf("%d",ret);//输出为0
	return 0;
}

  strncmp函数的模拟实现如下,

int my_strncmp(const char* s1,const char* s2,size_t count)
{
	assert(s1 && s2);
	for (int i = 0;i < count;i++)
	{
		if (*s1 == *s2)
		{
			if (*s1 == '\0')
				return 0;
			s1++;
			s2++;
		}
		else
			return *s1 - *s2;
	}
	return 0;
}

(五)字符串查找函数

strstr

  strstr是字符串查找函数,可以实现在一个字符串中查找另一个字符串是否存在,返回str2在atr1中第一次出现的位置(char*的指针),如果不存在,则返回为空。
  MSDN上解释为:
            char *strstr( const char *string, const char *strCharSet );

int main()
{
	char arr1[] = "i am a student";
	char arr2[] = "student";
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到");
	}
	else
	{
		printf("%s\n", ret);//输出为student
	}
	return 0;
}

  strstr函数的模拟实现如下,

char* my_strstr(const char* str1,const char* str2)
{
	assert(str1 && str2);
	char* cp = str1;
	char* s1;
	char* s2;
	if (*str2 == '\0')//排除arr2为空的情况
		return str1;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s2 != '\0' && *s1 != '\0' && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		cp++;
	}
	return NULL;
}

  在实现过程中,要注意如下的情况,如果在匹配字符串过程中发现不相等,则需要从开始匹配的位置开始重新进行匹配。
在这里插入图片描述

(五)字符串切割函数

strtok

  strtok是字符串切割函数,它会找到str中的下一个标记,并将其用\0来结尾,返回一个指向这个标记的指针。
  MSDN上解释为:
            char *strtok( char *strToken, const char *strDelimit );
  第一个参数用来指定字符串,第二个参数sep是一个字符串,定义用作分隔符的字符集合。
  strtok函数的第一个参数不为NULL,将找到str中的第一个标记并且保存它在字符串中的位置。strtok函数的第一个参数为NULL时,函数将在同一个字符串被保存的位置开始,查找下一个标记。如果字符串中不存在更多的标记,则返回NULL指针。

int main()
{
	char arr1[] = "lyy@editor.csdn.net";//在@处和.处截断
	char arr2[30] = { 0 };
	char ch[] = "@.";
	strcpy(arr2, arr1);
	char* ret = NULL;
	for (ret = strtok(arr2, ch);ret != NULL;ret = strtok(NULL, ch))
	{
		printf("%s\n",ret);
	}
	return 0;
}

  此时的输出值如下:

(六)错误信息报告函数

strerror & perror

  strerror是错误信息报告函数,返回的是错误码对应的错误信息。C语言库函数调用失败的时候,会把错误码存到errco变量里面去,再调用的时候,解释errno变量中对应的错误信息。
  MSDN上解释为:
            char *strerror( int errnum );

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

  此时屏幕上打印为,
在这里插入图片描述
  perror也是错误信息报告函数,相对于strerror操作更为简单。
  MSDN上解释为:
            void perror( const char *string );

int main()
{
	FILE* pf = fopen("text,txt", "r");
	if (pf == NULL)
	{
		perror("测试");
	}
	else
	{
		printf("打开文件成功");
	}
	return 0;
}

  perror函数会打印自定义信息之后再添加一个冒号和空格,随后打印错误信息。需要注意的是,perror函数一旦使用就必须要打印,输出如下,
在这里插入图片描述

(七)内存操作函数

memcpy

  memcpy是内存拷贝函数,不仅限于字符串。(不能进行重叠拷贝)
  MSDN上解释为:
            void *memcpy( void *dest, const void *src, size_t count );
  前两个是目标地址和原始地址,最后是要拷贝地址的大小。

int main()
{
	int arr1[5] = { 1,2,3,4,5 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 5 * sizeof(int));
	for (int i = 0;i < 10;i++)
	{
		printf("%d ", arr2[i]);//输出为1 2 3 4 5 0 0 0 0 0 
	}
	return 0;
}

  memcpy函数的模拟实现如下,

void* my_memcpy(void* dest, const void* src, size_t count)
{
	char* ch = dest;
	assert(dest && src);
	while (count--)
	{
		 *(char*)dest = *(char*)src;//转化为char*后赋值
		 dest = (char*)dest + 1;
		 src = (char*)src + 1;
	}
	return ch;
}

memmove

  memmove函数和memcpy作用类似,不同的是memmove可以实现重复内存拷贝。
  MSDN上解释为:
            void *memmove( void *dest, const void *src, size_t count );

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

  同一个字符串内部进行拷贝时,memmove输出为1 2 1 2 3 4 7 8 9 0,但是对于memcpy来说,在拷贝过程中,原字符串发生改变,输出为1 2 1 2 1 2 7 8 9 0,后续并不是我们想要的效果。memmove在本质上相当于memcpy的高级版本。
  由于拷贝过程中可能存在原字符串改变的问题,我们需要考虑以下情况,当dest在低地址,src在高地址时,需要从前向后拷贝,当dest在高地址,src在低地址的时候,需要从后向前拷贝(拷贝顺序与指针位置有关)。
在这里插入图片描述
  memmove函数的模拟实现如下,

void* my_memmove(void* dest, const void* src, size_t count)
{
	char* ch = dest;
	if (dest < src)//从前向后
	{
		while (count--)
		{
			 *(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			 src = (char*)src + 1;
		}
	}
	else//从后向前
	{
		while (count--)
		{
			*((char*)dest+count) = *((char*)src+count);
			//指向末尾后赋值
		}
	}
	return ch;
}

memcmp

  memcmp是内存比较函数,比较的是内存数据的大小,可以指定字节个数,大于返回1(大于0的数),小于返回-1(小于0的数),相等返回0。
  MSDN上解释为:
            void *memcpy( void *dest, const void *src, size_t count );

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
	int arr2[] = { 1,2,3,6,6 };
	//01 00 00 00 02 00 00 00 03 00 00 00 06 00 00 00
	int ret = memcmp(arr1, arr2, 12);//前12个字节,输出为0
	return 0;
}

memset

  memset是内存设置函数,以字节为单位改变内存中的数据。
  MSDN上解释为:
            void *memset( void *dest, int c, size_t count );

int main()
{
	int arr[] = { 1,2,3,4,5 }; 
	memset(arr, 1, 24);//24是改动字节的数目
	//目标空间起始地址,改成目标值,改动字节数(以字节为单位)
	return 0;
}

  内存中显示为,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值