[英]Please Explain this Example C Code
此代碼來自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()。 據我所知,這是它需要采取的步驟:
我想問一個更具體的問題,但我真的不知道這段代碼是如何實現它的目標的,所以我的問題是:(a)目的和(b)這段代碼的推理是什么?
提前致謝。
注意:對於任何K&R風扇,此代碼可以在第79頁找到(根據您的版本,我想)
(a)這段代碼的目的是能夠讀取一個字符然后“取消讀取”它,如果事實證明你不小心讀了太多字符(最多100
字符是“未讀”) )。 這在具有前瞻性的解析器中很有用。
(b)中getch
從讀取buf
,如果它有內容,以表示bufp>0
。 如果buf
為空,則調用getchar
。 請注意,它使用buf
作為堆棧:它從右到左讀取它。
ungetch
在檢查堆棧是否已滿后將字符推入堆棧buf
。
代碼並不是真正用於“讀取太多輸入”,而是它可以放回已讀取的字符 。
例如,你用getch
讀取一個字符,看看它是否是一個字母,用ungetch
將它放回去並讀取循環中的所有字母。 這是一種預測下一個角色的方式。
此代碼塊旨在供根據從流中讀取內容做出決策的程序使用。 有時這樣的程序需要從流中查看一些字符而不實際消耗輸入。 例如,如果您的輸入看起來像abcde12xy789
並且您必須將其拆分為abcde
, 12
, xy
, 789
(即連續字母組中的連續字母的單獨組),您不知道您已到達一組字母的末尾直到你看到一個數字。 但是,您不希望在看到它時消耗該數字:您只需知道該組字母即將結束; 你需要一種“回放”那個數字的方法。 在這種情況下, ungetch
會派上用場:一旦你在一組字母后面看到一個數字,你就可以通過調用ungetch
將數字放回去。 您的下一次迭代將通過相同的getch
機制重新選擇該數字,從而節省您需要保留您閱讀但未消費的字符。
我遇到了問題代碼的問題。 在此代碼中使用緩沖區(以堆棧的形式)是不正確的,因為當獲得多個額外輸入並且推入堆棧將在后面的處理(從緩沖區獲得輸入)中具有不期望的效果。
這是因為當后一個處理(獲取輸入)繼續時,此緩沖區(堆棧)將以相反的順序提供額外的輸入(意味着首先給出的最后一個額外輸入)。
由於堆棧的LIFO(后進先出)屬性,此代碼中的緩沖區必須是quene,因為在多個額外輸入的情況下它將更好地工作。
代碼中的這個錯誤使我感到困惑,最后這個緩沖區必須如下所示。
#define BUFSIZE 100
char buf[BUFSIZE];
int bufr = 0;
int buff = 0;
int getch(void)
{
if (bufr ==BUFSIZE)
bufr=0;
return(bufr>=0)?buf[bufr++]:getchar();
}
int ungetch(int c)
{
if(buff>=BUFSIZE && bufr == 0)
printf("too many characters");
else if(buff ==BUFSIZE)
buff=0;
if(buff<=BUFSIZE)
buf[buff++]=c;
}
這是通過上面的代碼片段來解決的。這個概念的擴展用於文件處理,特別是在編輯文件時。在這種情況下,不使用用於從標准輸入獲取輸入的getchar(),而是使用文件作為輸入來源。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.