2013-04-07 59 views
0

我到K &爲我自己的薰陶工作R(第二版),並遇到了下面的練習(練習2-2 P42):Kernighan和Ritchie練習2-2調試?

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循環執行的測試順序顛倒過來,如果c == '\n'仍然沒有看到,請添加if語句以打破外部循環!我也很難嘗試運行GDB在命令行中輸入文本,並同時打印c的值,即使我試圖將gdb鏈接到正在運行的可執行副本的pid時也是如此。我意識到可能有其他解決此練習的方法,例如設置一個OK_TO_EXECUTE標誌或變量,只有在滿足所有三個條件的情況下才爲true,但我似乎無法在看似簡單的程序中找到該錯誤,這讓我感到困擾。這正是我爲什麼要回到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;輸入命令行條目AND print的值爲c。將gdb鏈接到可執行文件的pid仍然無法按預期工作。我甚至發佈了關於gdb的separate question

+1

轉到http://lysator.liu.se/c並查看列出的C教程。它們相當過時(幾乎和K&R2一樣多),但仍然非常相關。 – vonbrand 2013-04-07 20:07:29

+0

@vonbrand感謝您指出該資源。 – haziz 2013-04-07 20:28:03

回答

1

您添加了原來不存在的循環......這在概念上和邏輯上都是錯誤的。最明顯的解決方案使用break

for (i = 0; i < lim-1; ++i) 
{ 
    c = getchar(); 
    if (c == '\n') 
     break; 
    if (c == EOF) 
     break; 

    s[i] = c; 
} 

或者如果你假裝C沒有break,你可以做這樣的事情:

for (i = 0; i < lim-1; ++i) 
{ 
    c = getchar(); 
    if (c == '\n') 
     i = lim-1; 
    else if (c == EOF) 
     i = lim-1; 
    else 
     s[i] = c; 
} 

或者你可以使用帕斯卡爾的方法:

#include <stdbool.h> 
... 
bool done = false; 
for (i = 0; !done && i < lim-1; ++i) 
{ 
    c = getchar(); 
    if (c == '\n') 
     done = true; 
    else if (c == EOF) 
     done = true; 
    else 
     s[i] = c; 
} 
+0

謝謝!儘管我的解決方案比你的解決方案還要複雜得多,並且可能還有錯誤,但我終於想到了這一點後終於弄清楚了。我有點沮喪,我無法看到一個看似簡單的問題的解決方案,也無法有效地使用GDB來解決問題。我過去使用過GDB,但有點生疏,根本不記得或弄清楚如何輸入命令行參數,並且即使當我將gdb鏈接到可執行文件的pid時,也會同時打印變量值。 – haziz 2013-04-07 19:12:53

3

,但讓我吃驚它

愉快士兵你有三個嵌套循環。一個換行符可以終止其中一個內部循環,而最外面的循環會快樂地繼續(直到您點擊了輸入lim次)。

我可以給你一個提示:你可能不應該爲此使用嵌套循環。

+0

呃!謝謝。我需要考慮一下,但我懷疑將內部循環的邏輯逆轉到外部循環可能會達到預期的效果。 – haziz 2013-04-07 17:32:03

+2

@haziz不,認爲'break'。 – 2013-04-07 18:54:57