代码改变世界

Functions and Program Structure_1

2017-02-09 18:07  星星之火✨🔥  阅读(313)  评论(1)    收藏  举报

1、编写函数strrindex(s, t),它将返回字符串t 在s 中最右边出现的位置。如果s 中不包含t,则返回-1。

// strrindex: returns rightmost index of t in s, -1 if none
int strrindex(char s[], char t[])
{
	int i, j, k, pos;
	
	pos = -1;
	for(i = 0; s[i] != '\0'; i++)
	{
		for(j = i, k = 0; t[k]!='\0' && s[j]==t[k]; j++, k++)
			;
		if(k > 0 && t[k] == '\0')
			pos = i;
	}
	return pos;
}

strrindex函数与strindex函数(TCPL读书笔记&心得第36条)很相似。两者的区别是strindex函数只要找到字符串t 在字符串s 中第一次(最左边)出现的位置就结束了;而strrindex函数在找到字符串s 中的匹配之后只记录其位置,然后继续搜索,因为它必须返回字符串t 在字符串s 中最后一次(最右边)出现的位置。下面提供另一种解决方法:

#include <string.h>

// strrindex: returns rightmost index of t is s, -1 if none
int strrindex(char s[], char t[])
{
	int i, j, k;
	
	for(i = strlen(s) - strlen(t); i >= 0; i--)
	{
		for(j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++, k++)
			;
		if(k > 0 && t[k] == '0')
			return i;
	}
	return -1;
}

就本题而言,第二种方法比第一种方法执行效率更高。它从字符串s 的尾部(最右边)再向串首推荐字符串t 的长度个字符的位置开始寻找字符串t。如果没有匹配,strrindex函数将从右向左后退一个位置并再次进行比较。这样,当strrindex函数在字符串s 中找到字符串t 时,它将立刻返回变量i,因为变量i 此时的取值就是字符串t 在字符串s 中最右边出现的位置。

2、对TCPL读书笔记&心得第37条进行扩充,使它可以处理形如123.45e-6的科学表示法,其中,浮点数后面可能会紧跟一个e 或E 以及一个指数(可能有正负号)。

#include <ctype.h>

// atof: convert string s to double
double atof(char s[])
{
	double val, power;
	int exp, i, sign;
	
	for(i = 0; isspace(s[i]); i++) // skip white space
		;
	sign = (s[i] == '-') ? -1 : 1;
	if(s[i] == '+' || s[i] == '-')
		i++;
	for(val = 0.0; isdigit(s[i]); i++)
		val = 10.0 * val + (s[i] - '0');
	if(s[i] == '.')
		i++;
	for(power = 1.0; isdigit(s[i]); i++)
	{
		val = 10.0 * val + (s[i] - '0');
		power *= 10.0;
	}
	val = sign * val / power;
	
	if(s[i] == 'e' || s[i] == 'E')
	{
		sign = (s[++i] == '-') ? -1 : 1;
		if(s[i] == '+' || s[i] == '-')
			i++;
		for(exp = 0; isdigit(s[i]); i++)
			exp = 10 * exp + (s[i] - '0');
		if(sign == 1)
			while(exp-- > 0) // positive exponent
				val *= 10;
		else
			while(exp-- > 0)
				val /= 10; // negative exponent
	}
	return val;
}

这个函数的前半部分与读书心得37条中atof 函数完全相同。该版本基于它扩展出了对可能遇到的科学表示法进行处理这一功能。如果浮点数没有可选的指数部分,atof 函数将返回保存在变量val 中的数值。

用val 去除以10而不是用val 去乘以0.1 的原因是:0.1无法用二进制数精确地表示出来。在大多数机器上,0.1的二进制表示法都要比0.1稍微小一点,用10.0乘以0.1并不能精确地得到1.0。从结果上看,虽然两种做法都有一定的误差,但连续地"除以10"要比连续地"乘以0.1"更精确。

补充知识点:

十进制小数转换成二进制小数采用"乘2取整,顺序排列"法。具体做法是:用2乘十进制小数得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,续行此法,直到积中的小数部分为零,或者达到所要求的精度为止。然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。