<string.h>中部分函数的实现

在一般的c语言学习中,我们通常是将C作为我们接触编程的引导,而非主要编程手段。这主要与C语言相较之下贴合英语,以及C可以直接修改内存有关。如果概括的话,就是C语言能为未来的编程奠定良好的基础。如果我们能在初学阶段,对c语言中的基本函数进行探究,也将有益于未来的编程学习。

1.strlen

strlen一般会作为我们接触到的第一个库函数,作用为检测字符串长度,更为准确的表示是,strlen接收到一个字符串的地址后,从该字符的位置开始读取字符并计数,直至发现'\0'为止。因此我们根据它的运作原理,设计出自己的是strlen函数:

int mystrlen(const char* s)
{
	int i = 0;
	while (*(s + i) != '\0')
		i++;
	return i;
}

该函数没有太多的复杂点,值得注意的是,初期学习时会把strlen与sizeof的用途混淆,两者并无直接联系!sizeof可以应用于所有数据类型,而strlen只能用于字符串。

2.strcpy

如何去复制一个字符串到另外的空间?C中给出了strcpy函数来实现这个功能,我们也可以尝试使用一个字符一个字符替换的方式来实现:

char* mystrcpy(char* dest, const char* src)
{
	while (*src!='\0')
	{
		*dest=*src;
        src++;
        dest++;
	}
}

dest表示目标字符串,src表示复制源字符串。

通过*将地址对应的字符内容一个一个替换,逐步向前,直至发现代表结束的'\0'。函数的基本功能已经完成了,但其实还可以做到更加精简:

char* mystrcpy(char* dest, const char* src)
{
	while ((*dest++=*src++)!='\0')
	{
		;
	}
}

这样通过一行实现函数所有功能。

3.strcat

当我们希望拼接字符串时,应该如何进行替换。延续上文strcpy的思路,我们怎么保证第一个字符串中被取代的'\0'和第二个字符串中添加的'\0'不影响整个函数的表达,首先可以想到最直观的方式,是通过strlen函数确定要拼接的个数,再通过if或循环语句来强制执行。

但是有没有更好的办法?或许我们可以参照strcpy的做法,只不过是在第一个字符串处于'\0'的位置进行strcpy,通过以上思路我们可以得到以下代码:

char* strcat(char* dest,const char* src)
{
	while (*dest!='\0')
	{
		dest++;
	}
	while (*dest++=*src++)
	{
		;
	}
}

这里直接给出最简代码,不再赘述。

4.strcmp

当我们需要排序时,面对int型数组,我们可以采用a[i]>b[i]?的方式来进行判断,并使用冒泡排序来进行排序。但是,在大学考题实际应用中,很多时候我们需要依据字典序(a最大z最小)或反字典序对不同字符串中内容进行比对。这时候,就不能简单地使用大于小于符号进行判断,我们必须给出一个判断标准,尽管'a'的ASCII码值要比'z'小。

当字符串中前一个字符相同时,进行下一个字符的比对,同时,不能遗漏两个字符串相同或前一部分相同(如lyboos与ly)的情况。因此我们仍然使用while循环进行逐一对比,下面给出反字典序的案例:

int mystrcmp(const char* a, const char* b)
{
	while (*a==*b)
	{
		if (*a == '\0')
			return 0;
		a++;
		b++;
	}
	return (*a - *b);
}

当a在我们的定义中“大”时,返回值大于0;相应地,相同时返回0,“小"时返回值小于0.而事实上,c语言给出的库函数也采用了如此规则。

ps:strcmp中思想在qsort排序有重要应用,这会在之后的排序总结中详细说明。

5.其他

<string.h>中基本的四个函数就是这些。除此之外,strstr、memmove、memcpy、strncat等也经常用到,由于篇幅限制不再叙述。

另外,了解上述函数,也可以应对c语言中不允许使用<stdio.h>以外库函数的上机考试。

特别鸣谢:比特鹏哥