K&R exercise 4-7、4-8
4-7
Write a routine ungets(s) that will push back an entire string onto the input. Should ungets know about buf and bufp, or should it just use ungetch?
初始思路:
将字符串的字符按照其输入顺序压入到缓存区中
void ungets(char s[])
{
int i = 0;
void ungetch(int);
while (s[i] != '\0')
ungetch(s[i++]);
}
出现的问题:
getch函数是在缓存区为空时再调用getchar函数。为了便于判断缓存区为空,弹出缓存区字符与压入字符到缓存区的顺序是相反的。
举例:
输入内容:abc 压入缓存区顺序:a->b->c
弹出顺序:c->b->a(弹出a后,bufp=0,缓存区为空)
改进:
应该调整将字符压入字符串的顺序
void ungets(char s[])
{
void ungetch(int);
while (len > 0)
ungetch(s[--len]);
}
4-8
假定最多只压回一个字符,请相应修改getch和ungetch这两个函数。
错误程序:
int getch(void)
{
return buf ? buf : getchar();
}
错误原因:
题目说最多只压入一个字符,那么表明只存在两种状态,压入和没压入字符
buf这一个变量根本无法表示这两种状态
改进:
int getch(void)
{
char c;
if (buf != 0)
{
c = buf;
buf = 0;
}
else
c = getchar();
return c;
}
void ungetch(int ch)
{
if (buf != 0)
printf("too many characters \n");
else
buf = ch;
}
完整程序:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
#include<math.h>
#include<time.h>
#define MaxLine 100
int mgetline(char[], int);
void ungets(char []);
int len = 0;
int main()
{
char c,line[MaxLine];
len = mgetline(line, MaxLine);
ungets(line);
while ((c = getch()) != EOF)
putchar(c);
return 0;
}
int mgetline(char s[],int lim)
{
int i = 0;
char c;
while (i < lim - 1 && (c = getch()) != '\n' && c != EOF)
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
//改进:应该调整将字符压入字符串的顺序
void ungets(char s[])
{
void ungetch(int);
while (len > 0)
ungetch(s[--len]);
}
char buf = 0;
//当变量buf为0时,执行getchar函数,它从输入中读取一个字符,相当于清除掉输入中的该字符
int getch(void)
{
char c;
if (buf != 0)
{
c = buf;
buf = 0;
}
else
c = getchar();
return c;
}
void ungetch(int ch)
{
if (buf != 0)
printf("too many characters \n");
else
buf = ch;
}