2011-11-07 90 views
0

嗯,我有這樣的代碼,以找到一個房間的油漆質量。SCANF不斷循環

void get_room_size(char room_id, int * length, int * width) { 
    while (*length <= 0 && *width <= 0) { 
     printf("Enter length and width of room %c in feet: ", room_id); 
     if (scanf("%d,%d", length, width)) { 
      if (*length <= 0) { 
       printf("###Error! Length must be a positive value!\n"); 
      } 
      if (*width <= 0) { 
       printf("###Error! Width must be a positive value!\n"); 
      } 
      printf("\n"); 
     } else { 
      printf("bad data"); 
      *length = 0; 
      *width = 0; 
     } 
    } 
} 

基本上,如果我進入

一,1

它會發瘋,並不斷循環。有什麼問題?

+0

你有沒有代碼,可以讀取「一個',所以它永遠不會被讀取。 –

回答

5

的原因,它是怎麼回事「瘋狂」如下。當scanf失敗a作爲數字讀取(因爲它不是數字,很明顯),它不會前進文件指針。

這就是爲什麼你不應該一般使用scanf操作,故障可能離開文件指針在一個不確定的位置(例如,如果你只在3月12日的項目掃描)。

的另一個原因是,scanf意思是「掃描格式化」,你將很難找到什麼比用戶輸入更多格式化

不管怎樣,回到失敗。由於文件指針不先進,下次你再來做fscanf,它會嘗試讀取a再次(又一遍)。

如果你想爲處理用戶輸入一個體面的功能,那沒有比這裏:

#include <stdio.h> 
#include <string.h> 

#define OK  0 
#define NO_INPUT 1 
#define TOO_LONG 2 
static int getLine (char *prmpt, char *buff, size_t sz) { 
    int ch, extra; 

    // Get line with buffer overrun protection. 
    if (prmpt != NULL) { 
     printf ("%s", prmpt); 
     fflush (stdout); 
    } 
    if (fgets (buff, sz, stdin) == NULL) 
     return NO_INPUT; 

    // If it was too long, there'll be no newline. In that case, we flush 
    // to end of line so that excess doesn't affect the next call. 
    if (buff[strlen(buff)-1] != '\n') { 
     extra = 0; 
     while (((ch = getchar()) != '\n') && (ch != EOF)) 
      extra = 1; 
     return (extra == 1) ? TOO_LONG : OK; 
    } 

    // Otherwise remove newline and give string back to caller. 
    buff[strlen(buff)-1] = '\0'; 
    return OK; 
} 

這將用戶的輸入線,防溢保護(不像getsscanf無界"%s")。

這也刷新到行結束時,如果輸入太長,這將影響下次輸入操作停止線的其餘部分。

然後,您可以sscanf緩衝你的心臟的內容沒有任何的擔憂重新文件指針。

下面的測試程序演示瞭如何使用這樣的:

int main (void) { 
    int rc; 
    char buff[10]; 

    rc = getLine ("Enter string> ", buff, sizeof(buff)); 
    if (rc == NO_INPUT) { 
     // Extra NL since my system doesn't output that on EOF. 
     printf ("\nNo input\n"); 
     return 1; 
    } 

    if (rc == TOO_LONG) { 
     printf ("Input too long [%s]\n", buff); 
     return 1; 
    } 

    printf ("OK [%s]\n", buff); 

    return 0; 
} 

順便說一句,你可能要重新審視你的邏輯,有效大小的房間。你現在有將允許一個房間由-42英尺:-)

輸入爲7這也是通常不是好的形式依靠輸出值被設定爲在進入特定的值。如果輸入時長度和寬度爲(例如)3和4,則此功能將立即退出,而不要求用戶輸入。

第一個問題可以通過使用||代替&&被固定。第二種方法是在函數開始時將變量初始化爲0,以便輸入循環。


爲了完整起見,如果你把該原始片段上方具有以下(在include報表及getLine()功能)略作修改get_room_size()功能:

static void get_room_size(char room_id, int * length, int * width) { 
    char buff[100]; 
    *length = *width = 0; 
    while ((*length <= 0) || (*width <= 0)) { 
     printf("Enter length and width of room %c in feet: ", room_id); 
     int rc = getLine (NULL, buff, sizeof (buff)); 

     if (rc == NO_INPUT) { 
      printf ("\nEnd of file encountered.\n"); 
      return; 
     } 

     if (rc == TOO_LONG) { 
      printf ("\nInput too long, please retry.\n"); 
      continue; 
     } 

     if (sscanf(buff, "%d,%d", length, width) != 2) { 
      *length = *width = 0; 
      printf ("\nInput not in desired form (<number>,<number>), " 
       "please retry.\n"); 
      continue; 
     } 

     if ((*length <=0) || (*width <= 0)) { 
      *length = *width = 0; 
      printf ("\nBoth length and width must be greater than zero, " 
       "please retry.\n"); 
     } 
    } 
} 

和非常簡單的測試main(),你」我將看到一個完整的程序,展示如何去做。

int main (void) { 
    int len, wid; 
    get_room_size ('x', &len, &wid); 
    printf ("Length is %d, width is %d.\n", len, wid); 
    return 0; 
} 
+0

讀取一個字符串,然後嘗試將其解析爲一個int。 –

0

您的scanf採取兩個整數。 A是一個字符,認爲你想要 scanf(「%c」,* room_id); scanf(「%d」,length);

我reccommend你單獨做他們

+0

我懷疑房間ID是已知的,因爲它已經被傳入(並且_not_作爲可以被改變並傳回的指針),並且它被用在'printf'中。 – paxdiablo

0

試試這個:

... 
     if (scanf("%d,%d", length, width) == 2) { 
      if (*length <= 0) { 
       printf("###Error! Length must be a positive value!\n"); 
      } 
      if (*width <= 0) { 
       printf("###Error! Width must be a positive value!\n"); 
      } 
      printf("\n"); 
     } else { 
      printf("bad data"); 
      *length = -1; 
      *width = -1; 
     } 
+0

這仍然會在'a,1'上循環,因爲它不會超過原始代碼的前進文件指針。 – paxdiablo

+0

關鍵是要正確檢查scanf()的狀態! – paulsm4

-1

你不把&在scanf()語句,因此如何其讀

if (scanf("%d,%d", &length, &width)) 
+0

在你的scanf()語法中試試這個傢伙的錯誤。 –

+1

這不是問題...... scanf已指向長度和寬度。 – TheAJ