100 Days of Code-day17

K&R exercise 4-9、4-10

4-9

Our getch and ungetch do not handle a pushed-back EOF correctly. Decide what their properties ought to be if an EOF is pushed back, then implement your design.

思考:

int类型-1在内存中的表示(16位的系统int占两个字节,而32位机器中它占4个字节,所以int型至少为16位):
(1字节(Byte) = 8个二进制位 = 8bits)
原码:1000 0000, 0000 0001
取反:1111 1111,1111 1110
加一:1111 1111,1111 1111
转化为十六进制为FFFF
char占一个字节,所以由int转化为char时高位丢失
字符(二进制表示):1111 1111
转化为十六进制为FF
当char再次转化为int时,有的机器可能将其转化为FF,而有的会转化为FFFF
为了避免“宽类型”(int)转化为“窄类型”(char)时可能导致数据信息丢失这种情况的发生,可以将缓存区buf数组由原来的char类型转化为int类型
也就是将

char buf[bufsize];

转化为

int buf[bufsize];

其余内容不变。

4-10

An alternate organization uses getline to read an entire input line; this makes getch and ungetch unnecessary. Revise the calculator to use this approach.

思考1:

对所读取数组line的索引Li的初始化

int Li = 0;//input line index

int getop(char s[])
{
	int c, i;
	if (line[Li] == '\0')//the end of input line
	{
		if (GetLine(line, MaxLine) == 0)//input line length is 0
			return EOF;
		else
			Li = 0;
	}

当getop函数到达输入行line的末尾时,需要调用GetLine函数再读取一行。若读取的行长度不为0,就需要重新对索引Li进行初始化操作。
为什么要重新初始化呢,不多余吗?

解释:

这次对line数组的索引Li的初始化并不多余,虽然在第一次读取输入时本来Li就等于0。但当第二次读取输入时,索引位置还停留在上一次读取结束的位置
,所以应该将其位置更新到line数组起始位置。

思考2:

当程序要确定读取数字的完整性,需要多读一个字符。此时只需要对Li减一即可达到后退一个字符的效果。那么此时需不需要判断字符c是否等于EOF呢(也就是说要不要判断到达文本结尾处)。

解释:

此处不需要判断是否到达文档结尾处(EOF),因为读取的line数组是从GetLine函数传递过来的。若长度为0,在前面的程序段就会将其定义为EOF,并返回。当其长度不为0时,才会对字符串进行读写操作

完整程序:

#define MaxLine 100
int GetLine(char[], int);
char line[MaxLine];//one input line
int Li = 0;//input line index

int getop(char s[])
{
	int c, i;
	if (line[Li] == '\0')//the end of input line
	{
		if (GetLine(line, MaxLine) == 0)//input line length is 0
			return EOF;
		else
			Li = 0;
	}
	while ((s[0] = c = line[Li++]) == ' ' || c == '\t')//assign to c variable the value 
		;											//present at line character array
	s[1] = '\0';
	i = 0;
	if (!isdigit(c) && c != '.' && c != '-' && !islower(c))//遵循从左到右的顺序进行判断
		return c;
	if (c == '-')
	{
		if (isdigit(c = line[Li++]) || c == '.')
			s[++i] = c;
		else
		{
			Li--;
			return '-';//返回输入的结尾
		}
	}
	if (islower(c))//如果c为小写字母
	{
		while (islower(s[++i] = c = line[Li++]))
			;
		s[i] = '\0';
		if (c != EOF)//不管所读取的是单个小写字母,还是一个小写字母组成的字符串
			//为了确定所读取内容的准确性,都需要多读取一个字符,然后将其“压回”栈中
			Li--;
		if (strlen(s) > 1)
			return Name;
		else
			return s[--i];//return c;是不正确的,因为此时c是程序为了确定字符串完整性所多读取的字符
						//而在其之前的那个字符才是执行相应操作的字符标志
	}
	if (isdigit(c))//收集整数部分
		while (isdigit(s[++i] = c = line[Li++]));
	if (c == '.')//收集小数部分
		while (isdigit(s[++i] = c = line[Li++]));
	s[i] = '\0';
	Li--;
	return number;
}

//GetLine:take input in the character array
int GetLine(char s[], int limit)
{
	int i = 0;
	char c;

	while (i < limit - 1 && (c = getchar()) != '\n' && c != EOF)
		s[i++] = c;
	if (c == '\n')
		s[i++] = c;
	s[i] = '\0';
	return i;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值