[英]While Loop doesn't break when error occurrs
添加字母時,下面的 while 循環會中斷。 我希望它繼續循環,即使添加了一個字母,以及添加了一個負數。 這是我當前的代碼:
float monthpay;
printf("Please enter your monthly wage:\t");
scanf("%f", &monthpay);
while (monthpay <= 0)
{
printf("\nThat was invalid");
printf("\n Please try again: ");
scanf("%f", &monthpay);
}
printf("%.2f", monthpay);
我試圖制作一個循環,如果錯誤地添加了一個字母,它就會循環。
scanf()
返回成功匹配和分配的輸入項數。 如果您不檢查返回值 ( rv
),您的變量 ( monthpay
) 可能未初始化,使用它是未定義的行為。
void flush() {
for(;;) {
char ch;
int rv = scanf("%c", &ch);
if(rv == EOF || rv == 1 && ch == '\n') return;
}
}
printf("Please enter your monthly wage:\t");
float monthpay;
for(;;) {
int rv = scanf("%f", &monthpay);
if(rv == EOF)
return;
if(rv == 1)
break;
printf("\nThat was invalid");
printf("\n Please try again: ");
flush();
}
printf("%.2f", monthpay);
在嘗試使用結果之前,您應該始終檢查scanf
的返回值以確定輸入是否已成功轉換。
但是,對於基於行的用戶輸入,通常不建議使用 function scanf
,因為它的行為不直觀。 它通常不會消耗整行輸入,這會導致各種麻煩。 例如, scanf
在輸入 stream 上留下換行符可能會導致此問題。 如果用戶輸入6abc\n
,那么情況更糟:在這種情況下, scanf
會將6
匹配為有效輸入,但將abc\n
保留在輸入 stream 上,這很可能導致下一個輸入操作無法正常運行按照預期,除非您事先明確丟棄輸入 stream 中該行的其余部分。
出於上述原因,通常最好始終將整行輸入作為字符串一次讀取,例如使用 function fgets
。 然后,您可以使用 function strtof
嘗試將字符串轉換為數字。
這是一個示例,它執行廣泛的輸入驗證:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
float get_float_from_user( const char *prompt );
int main( void )
{
float monthpay;
//loop forever until user enters a valid number
for (;;) //infinite loop, equivalent to while(1)
{
monthpay = get_float_from_user( "Please enter your monthly wage: ");
if ( monthpay > 0 )
{
//input is ok, so we can break out of the loop
break;
}
printf( "Please enter a positive number!\n" );
}
printf( "Input was valid. You entered: %.2f\n", monthpay );
return 0;
}
float get_float_from_user( const char *prompt )
{
//loop forever until user enters a valid number
for (;;)
{
char buffer[1024], *p;
float f;
//prompt user for input
fputs( prompt, stdout );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "Unrecoverable input error!\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL && !feof( stdin ) )
{
int c;
printf( "Line input was too long!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
fprintf( stderr, "Unrecoverable error reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//attempt to convert string to number
errno = 0;
f = strtof( buffer, &p );
if ( p == buffer )
{
printf( "Error converting string to number!\n" );
continue;
}
//make sure that number is representable as a "float"
if ( errno == ERANGE )
{
printf( "Number out of range error!\n" );
continue;
}
//make sure that remainder of line contains only whitespace,
//so that input such as "6abc" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected input encountered!\n" );
//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto continue_outer_loop;
}
}
return f;
continue_outer_loop:
continue;
}
}
該程序具有以下行為:
Please enter your monthly wage: abc
Error converting string to number!
Please enter your monthly wage: 6abc
Unexpected input encountered!
Please enter your monthly wage: 6e+2000
Number out of range error!
Please enter your monthly wage: -5
Please enter a positive number!
Please enter your monthly wage: 0
Please enter a positive number!
Please enter your monthly wage: 6.3
Input was valid. You entered: 6.30
我在上面的代碼中使用的 function get_float_from_user
是基於 function get_int_from_user
from this answer of mine to another question 。 有關 function 如何工作的進一步解釋,請參閱該答案。
在嘗試掃描float
之后,掃描並丟棄換行符以外的空格,掃描丟棄並計算所有剩余的不是換行符的字符,然后掃描換行符。
%n
說明符將提供掃描處理的字符數,直到說明符為止。
掃描集中的星號%*[ \t\f\v]
告訴 scanf 丟棄匹配的字符。 scanset %*[^\n]
中的 carat 告訴 scanf 處理不匹配的字符,以便丟棄所有不是換行符的字符。 %1[\n]
告訴 scanf 掃描一個字符,它必須是換行符。 如果輸入一個浮點數后僅跟有空格,則循環將退出,因為scanned
將為 2, extra
將為 0。
#include <stdio.h>
int main ( void) {
char newline[2] = "";
int extra = 0;
int scanned = 0;
float monthpay = 0.0;
do {
printf ( "enter monthly pay\n");
scanned = scanf ( "%f", &monthpay);
if ( scanned == EOF) {
return 1;
}
extra = 0;
scanf ( "%*[ \f\t\v]"); // scan and discard whitespace except newline
scanf ( "%*[^\n]%n", &extra); // scan discard and count non-whitespace
scanned += scanf ( "%1[\n]", newline);
} while ( monthpay < 0 || scanned != 2 || extra != 0);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.