簡體   English   中英

使用while <0條件將字符串輸入scanf會導致無限循環

[英]entering a string into scanf with a while < 0 condition causes infinite loop

我有一個“分鍾”變量,我希望用戶輸入一個正數。

int main(void)
{
    float minutes;
    minutes = -1;
    printf("Find out how many bottles worth of water your showers use!\n");
    printf("How many minutes do you spend in the shower? ");
    scanf("%f", &minutes);
    while(minutes < 0)
    {
        printf("Please enter a positive number: ");
        scanf("%f", &minutes);
    }
}

它適用於數字。 如果分鍾> = 0,它接受它,如果分鍾<0,它會一直詢問。 如果我輸入一個字符串,它會無限循環

printf("Please enter a positive number: "); 

從來沒有給我機會輸入新的價值。 為什么這樣,我該如何解決? 謝謝!

如果未輸入數值,則輸入緩沖區中的任何類型都將保留。 您可以通過讀取scanf的返回值來檢查這一點,它會告訴您讀取的項目數。 如果為0,則可以使用getchar讀取字符,直到下一個換行符刷新緩沖區。

int main(void)
{
    int rval, c;
    float minutes;
    minutes = -1;
    printf("Find out how many bottles worth of water your showers use!\n");
    printf("How many minutes do you spend in the shower? ");
    rval = scanf("%f", &minutes);
    if (rval == 0) {
        while (((c = getchar()) != '\n') && (c != EOF));
    }
    while(minutes < 0)
    {
        printf("Please enter a positive number: ");
        rval = scanf("%f", &minutes);
        if (rval == 0) {
            while (((c = getchar()) != '\n') && (c != EOF));
        }
    }
}

%f轉換說明符告訴scanf在看到不屬於合法浮點常量的字符(即,不是數字,小數點或符號)時立即停止讀取輸入。 這個壞字符留在輸入流中,因此下一次調用scanf失敗,下一次調用,下一次調用等等。

您應該始終檢查scanf的返回值 - 它將告訴您從輸入流中成功讀取和分配了多少項。 在這種情況下,您期望單個項目,因此您應該獲得返回值1.如果返回值為0,則表示輸入不是正確的浮點值,並且輸入不良以某種方式被清除。 這是一個可能的解決方案:

if ( scanf( "%f", &minutes ) == 1 )
{
  // process minutes as normal
}
else
{
  // clear everything up to the next whitespace character
  while ( !isspace( getchar() ) )
    ; // empty loop 
}

唯一的問題是scanf有點笨,如果你鍵入123fgh類的東西,它會轉換並分配123同時在輸入流中留下fgh ; 你可能想完全拒絕整個輸入。

一種解決方案是將輸入作為文本讀取,然后使用strtod進行轉換:

char buffer[BUFSIZE]; // where BUFSIZE is large enough to handle expected input
...
if ( fgets( buffer, sizeof buffer, stdin ) )
{
  char *chk; // chk will point to the first character *not* converted; if
             // it's anything other than whitespace or the string terminator,
             // then the input was not a valid floating-point value.
  double tmp = strtod( buffer, &chk );
  if ( isspace( *chk ) || *chk == 0 )
  {
    minutes = tmp;
  }
  else
  {
    // input was not a proper floating point value
  }
}

這樣做的好處是不會在輸入流中留下垃圾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM