[英]Kernighan and Ritchie Exercise 2-2 Debugging?
我正在通過 K&R(第 2 版)進行自己的啟蒙,並遇到以下練習(練習 2-2 p42):
Write a loop equivalent to the following without using && or ||:
for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i)
s[i] = c;
這是我的解決方案:
#include <stdio.h>
/* write a loop equivalent to the following without using && or ||
for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i)
s[i] = c;
*/
int main()
{
int counter = 0, lim = 1000;
int s[lim], c;
while(counter < lim-1)
{
while((c = getchar()) != '\n')
{
while(c != EOF)
{
s[counter] = c;
}
}
counter++;
}
return 0;
}
我期待縮進循環,因此一旦遇到換行符( '\\n'
)或 EOF 字符(我的 Linux 機器上的Ctrl-d
),整個程序就會正常退出,但令我驚訝的是,它高興地繼續前進。 我嘗試使用 gdb 調試它,但仍然無法弄清楚。
我沒有看到什么?
附錄:我試圖顛倒 while 循環執行的測試順序,並添加了一個 if 語句來跳出外循環 if c == '\\n'
但我仍然沒有看到它! 我也很難嘗試運行 GDB,在命令行中輸入文本並同時打印c
的值,即使我嘗試將 gdb 鏈接到可執行文件的運行副本的 pid 也是如此。 我意識到可能有其他方法來解決這個練習,例如設置一個OK_TO_EXECUTE
標志或變量,只有當所有三個條件都滿足時才為真,但我似乎無法在一個看似簡單的程序。 這正是我回到 K&R 更徹底地閱讀本書並正確解決練習的原因。
重做代碼(仍然有問題!!!):
#include <stdio.h>
/* write a loop equivalent to the following without using && or ||
for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i)
s[i] = c;
*/
int main()
{
int counter = 0, lim = 1000;
int s[lim], c;
while((c = getchar()) != EOF)
{
if ( c == '\n')
break;
while(c != '\n')
{
while(counter < lim-1)
{
s[counter] = c;
counter++;
}
}
}
return 0;
}
解決了! - 我認為! 我想我終於想通了。 在我重做的解決方案中寫入的內部循環仍將無休止地循環或至少直到達到lim
為止。 我添加了 break 語句,並認為我正在尋求解決方案。
不過,我仍在努力解決如何在這個問題上運行 gdb; 輸入命令行條目並print
c
的值。 將 gdb 鏈接到可執行文件的 pid 仍然沒有按預期工作。 我什至發布了一個關於 gdb 的單獨問題。
但令我驚訝的是它快樂地堅持着
您有三個嵌套循環。 換行符將終止內部循環之一,而最外層循環將繼續進行(直到您按 Enter lim
次)。
我可以給你一個提示:你可能不應該為此使用嵌套循環。
您添加了原始版本中不存在的循環……這在概念上和邏輯上都是錯誤的。 最明顯的解決方案是使用break
:
for (i = 0; i < lim-1; ++i)
{
c = getchar();
if (c == '\n')
break;
if (c == EOF)
break;
s[i] = c;
}
或者,如果您假裝 C 沒有break
,您可以執行以下操作(這並不完全等效,因為如果遇到'\\n'
或EOF
i
沒有相同的值):
for (i = 0; i < lim-1;)
{
c = getchar();
if (c == '\n')
i = lim-1;
else if (c == EOF)
i = lim-1;
else
s[i++] = c;
}
或者您可以使用 Pascal 方法:
#include <stdbool.h>
...
i = 0;
bool more = i < lim-1;
while (more)
{
c = getchar();
if (c == '\n')
more = false;
else if (c == EOF)
more = false;
else
{
s[i++] = c;
more = i < lim-1;
}
}
帶goto
i=0;
loop:
if( i >= lim - 1) goto end;
c = getchar();
if(c == '\n') goto end;
if(c == EOF) goto end;
s[i++] = c;
goto loop;
end:
沒有break
, goto
並且只有一個for
,仍然沒有&&
和||
.
for (i=0; i < lim - 1 ? ((c=getchar()) == '\n' | c == EOF) == 0 : 0; ++i)
s[i] = c;
更新
正如@Jim 所指出的那樣,最好使用內部?:
顯式設置執行順序?:
for (i=0; i >= lim - 1 ? 0 : (c=getchar()) == '\n' ? 0 : c != EOF; ++i)
s[i] = c;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.