2016-10-02 85 views
0

我意识到如果输入是一个以'y'或'n'开头的单词,它将会逃离循环。除非输入是单个字符,否则我怎样限制循环才能继续循环?如何限制为单字母输入?

do 
{ 
    printf("Do you want to try again? (Y/N): "); 
    fflush(stdin);        
    scanf("%c", &repeat); 
    repeat = toupper(repeat); 
    if (repeat != 'Y' && repeat != 'N')   
     printf("Invalid answer. Please enter 'Y' or 'N'.\n\n"); 

} while (repeat != 'N' && repeat != 'Y'); 
+1

'fflush(stdin);'是未定义的行为。 – StoryTeller

+1

什么是“重复”? – GMichael

+0

您需要[向您的橡皮鸭解释](https://en.wikipedia.org/wiki/Rubber_duck_debugging)双字符输入与两个单字符输入如何不同。如果输入了EOF,则为UB –

回答

1

这样的:

#include <stdio.h> 
#include <ctype.h> 

int main(void){ 
    char repeat[3] = {0};//3 : one character + one character + NUL 
    do{ 
     printf("Do you want to try again? (Y/N): ");fflush(stdout); 
     if(EOF==scanf("%2s", repeat)){ *repeat = 'N'; break; } 
     *repeat = toupper(*repeat); 
     if (repeat[1] || *repeat != 'Y' && *repeat != 'N'){//repeat[1] != '\0'..  
      printf("Invalid answer. Please enter 'Y' or 'N'.\n\n"); 
      scanf("%*[^\n]");scanf("%*c");//clear upto newline 
      *repeat = 0; 
     } 
    } while (*repeat != 'N' && *repeat != 'Y'); 
    puts("Bye!");//try agein or see ya, bye 
    return 0; 
} 
+0

。 – alk

+0

@alk如果输入了'EOF',你应该离开循环? – BLUEPIXY

+0

“* ...离开循环?*”:我不知道,因为这个案例的规范是由OP丢失的,但绝对不会......'toupper(* repeat)'。由于'* repeat'是未初始化的,至少在第一次迭代中是这样。 – alk

0

可选择使用scanf()可以使用fgets()读取行,然后做解析一个自:

#include <stdlib.h> 
#include <stdio.h> 
#include <ctype.h> 


int main(void) 
{ 
    char repeat = '\0'; 

    do 
    { 
    int input_valid = 0; /* Be pessimistic. */ 
    char line[3] = {0}; 

    puts("Do you want to try again? (Y/N):"); 

    do /* On-time loop, to break out on parsing error. */ 
    { 
     if (NULL == fgets(line, sizeof line, stdin)) 
     { 
     break; /* Either fgets() failed or EOF was read. Start over ... */ 
     } 

     if (line[1] != '\0' && line[1] != '\n') 
     { 
     break; /* There was more then one character read. Start over ... */ 
     } 

     line[0] = toupper(line[0]); 

     if (line[0] != 'Y' && line[0] != 'N') 
     {  
     break; /* Something else but Y or N was read. Start over ... */ 
     } 

     input_valid = 1; 
    } while (0); 

    if (input_valid == 0) 
    { 
     int c; 

     do /* Flush rest of input. if any. */ 
     { 
     c = getc(stdin); 
     } while (EOF != c && '\n' != c); 

     fprintf(stderr, "Invalid answer. Please enter 'Y' or 'N'.\n\n"); 
    } 
    else 
    { 
     repeat = line[0]; 
    } 
    } while ('\0' == repeat); 

    printf("The user entered: '%c'\n", repeat); /* Will only print either Y or N. */ 

    return EXIT_SUCCESS; 
} 
+0

我认为有必要清除输入缓冲区。 – BLUEPIXY

+0

@BLUEPIXY:通过将'repeat'的定义(及其初始化)移动到最不必要的范围来隐含地解决这个问题。 :-) – alk

+0

尝试'是的,我愿意.'进入。还有'} while(input_valid == 0)'< - 忘记了';' – BLUEPIXY

0

首先fflush(stdin);没有意义除了微软的世界。

然后,scanf族函数返回一个值,该值是成功解码的输入令牌的数量,返回值应该控制为总是。 %c应该谨慎使用,因为它可以返回一个留空的字符(空格或换行符),而%s只返回可打印的字符。有了这些言论,你的代码可能会变成:

repeat = '\0'; 
do 
{ 
    char dummy[2], inp[2]; 
    printf("Do you want to try again? (Y/N): "); 
    // fflush(stdin);        
    if (1 == scanf("%1s%1s", inp,dummy) repeat = toupper(inp[0]); 
    if (repeat != 'Y' && repeat != 'N')   
     printf("Invalid answer. Please enter 'Y' or 'N'.\n\n"); 

} while (repeat != 'N' && repeat != 'Y'); 
相关问题