请解释一下这个示例 C 代码
此代码来自 K&R。我已经读了好几遍了,但它似乎还是逃不过我的掌握。
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
int getch(void)
{
return(bufp>0)?buf[--bufp]:getchar();
}
int ungetch(int c)
{
if(bufp>=BUFSIZE)
printf("too many characters");
else buf[bufp++]=c;
}
K&R 表示,这两个函数的目的是防止程序读取过多的输入。即,如果没有此代码,函数可能无法确定它已读取足够的数据,而无需首先读取太多数据。但我不明白它是如何工作的。
例如,考虑 getch()。 据我所知,这是它所采取的步骤:
- 检查 bufp 是否大于 0。
- 如果是,则返回 buf[--bufp] 的 char 值。
- 否则返回 getchar()。
我想问一个更具体的问题,但我确实不知道这段代码如何实现其预期目的,所以我的问题是:这段代码的(a)目的和(b)推理是什么?
提前致谢。
注意:对于任何 K&R 粉丝,可以在第 79 页找到此代码(我想这取决于您的版本)
This code comes from K&R. I have read it several times, but it still seems to escape my grasp.
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
int getch(void)
{
return(bufp>0)?buf[--bufp]:getchar();
}
int ungetch(int c)
{
if(bufp>=BUFSIZE)
printf("too many characters");
else buf[bufp++]=c;
}
The purpose of these two functions, so K&R says, is to prevent a program from reading too much input. i.e. without this code a function might not be able to determine it has read enough data without first reading too much. But I don't understand how it works.
For example, consider getch().
As far as I can see this is the steps it takes:
- check if bufp is greater than 0.
- if so then return the char value of buf[--bufp].
- else return getchar().
I would like to ask a more specific question, but I literally dont know how this code achieves what it is intended to achieve, so my question is: What is (a) the purpose and (b) the reasoning of this code?
Thanks in advance.
NOTE: For any K&R fans, this code can be found on page 79 (depending on your edition, I suppose)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
(a) 此代码的目的是能够读取一个字符,然后如果您不小心读取了太多字符(最多
100
个字符),则可以“取消读取”该字符为“未读”)。这对于具有前瞻功能的解析器很有用。(b)
getch
从buf
读取,如果它有内容,由bufp>0
指示。如果buf
为空,则调用getchar
。请注意,它使用buf
作为堆栈:它从右到左读取它。在检查堆栈是否未满后,
ungetch
将一个字符推送到堆栈buf
上。(a) The purpose of this code is to be able to read a character and then "un-read" it if it turns out you accidentally read a character too many (with a max. of
100
characters to be "un-read"). This is useful in parsers with lookahead.(b)
getch
reads frombuf
if it has contents, indicated bybufp>0
. Ifbuf
is empty, it callsgetchar
. Note that it usesbuf
as a stack: it reads it from right-to-left.ungetch
pushes a character onto the stackbuf
after doing a check to see if the stack isn't full.该代码实际上并不是为了“读取太多输入”,而是为了让您可以放回已经读取的字符。
例如,您使用
getch
读取一个字符,看看它是否是一个字母,然后使用ungetch
将其放回去,然后循环读取所有字母。这是一种预测下一个角色是什么的方法。The code is not really for "reading too much input", instead is it so you can put back characters already read.
For example, you read one character with
getch
, see if it is a letter, put it back withungetch
and read all letters in a loop. This is a way of predicting what the next character will be.该代码块旨在供根据从流中读取的内容做出决策的程序使用。有时,此类程序需要查看流中的几个字符,而不实际消耗输入。例如,如果您的输入类似于
abcde12xy789
,则必须将其拆分为abcde
、12
、xy
、< code>789(即,将连续字母组与连续数字组分开),直到看到数字为止,您不知道已经到达一组字母的末尾。但是,您不想在看到该数字时就使用它:您所需要的只是知道该字母组正在结束;您需要一种方法来“放回”该数字。在这种情况下,ungetch
会派上用场:一旦您在一组字母后面看到一个数字,就可以通过调用ungetch
将数字放回去。您的下一次迭代将通过相同的getch
机制重新选择该数字,从而使您无需保留已读取但未使用的字符。This block of code is intended for use by programs that make decisions based on what they read from the stream. Sometimes such programs need to look at a few character from the stream without actually consuming the input. For example, if your input looks like
abcde12xy789
and you must split it intoabcde
,12
,xy
,789
(i.e. separate groups of consecutive letters from groups of consecutive digits) you do not know that you have reached the end of a group of letters until you see a digit. However, you do not want to consume that digit at the time you see it: all you need is to know that the group of letters is ending; you need a way to "put back" that digit. Anungetch
comes in handy in this situation: once you see a digit after a group of letters, you put the digit back by callingungetch
. Your next iteration will pick that digit back up through the samegetch
mechanism, sparing you the need to preserve the character that you read but did not consume.1. The other idea also shown here can be also called as a very primitive I/O stack mangement system and gives the implementation of the function getch() and ungetch().
2. To go a step further , suppose you want to design an Operating System , how can you handle the memory which stores all the keystrokes?
上面的代码片段解决了这个问题。这个概念的扩展用于文件处理,特别是编辑文件。在这种情况下,不使用用于从标准输入获取输入的 getchar() ,而是使用文件作为输入来源。
1. The other idea also shown here can be also called as a very primitive I/O stack mangement system and gives the implementation of the function getch() and ungetch().
2. To go a step further , suppose you want to design an Operating System , how can you handle the memory which stores all the keystrokes?
This is solved by the above code snippet.An extension of this concept is used in file handling , especially in editing files .In that case instead of using getchar() which is used to take input from Standard input , a file is used as a source of input.
我对所给出的代码有疑问。在此代码中使用缓冲区(以堆栈的形式)是不正确的,因为当获取多个额外输入并推入堆栈时,将在后面的处理(从缓冲区获取输入)中产生不良影响。
这是因为当后面的处理(获取输入)进行时,该缓冲区(堆栈)将以相反的顺序提供额外的输入(意味着首先给出最后的额外输入)。
由于 stack 的 LIFO(后进先出)属性,此代码中的缓冲区必须是队列,因为在有多个额外输入的情况下它会更好地工作。
代码中的这个错误让我很困惑,最后这个缓冲区必须是队列,如下所示。
I have a problem with code given in question. Using buffer (in form of stack) in this code is not correct as when getting more than one extra inputs and pushing into stack will have undesired effect in latter processing (getting input from buffer).
This is because when latter processing (getting input) going on ,this buffer (stack) will give extra input in reverse order (means last extra input given first).
Because of LIFO (Last in first out ) property of stack , the buffer in this code must be quene as it will work better in case of more than one extra input.
This mistake in code confused me and finally this buffer must be quene as shown below.