我一直在创建一个程序,要求用户输入一个char值,但如果他们输入多个字符,它将移动到下一个函数并中断该程序。我在第二种方法中添加了在输入多个输入时运行的方法。
答案 0 :(得分:1)
您的问题不是限制写入cInput
的字符数;格式说明符%1s
已经这样做了。您的问题是在输入缓冲区中保留未处理的字符。如果后续输入无法处理它们,则需要从缓冲区中删除所有字符。例如,如果您在缓冲区中保留字母字符但稍后使用%d
读取,则该函数将立即返回(因为隐式地还有一个新行也被缓冲),但该字符将保持缓冲,因为它不是小数。如果您从未清除缓冲区,这将无限期地继续。
对于单个字符,您可以检查字符是否不是换行符,然后重复获取字符,直到找到换行符,如下所示:
scanf("%c", &cInput ) ;
while( cInout != '\n' && getchar() != '\n' ) { } // flush buffered line
如果您想确保用户只输入一个字符,那么您可以修改以上内容:
scanf("%c", &cInput ) ; // Get a single character
if( cInput != '\n' && // If the input is not "empty",
getchar() != '\n' ) // but the first character entered was not
// immediately followed by a newline...
{
// Flush to the end of the entered line
while( getchar() != '\n' ) { }
// Invalidate the input to force retry
cInput = 0 ;
}
至少会缓冲一个字符 - 至少是换行符。有效答案将在cInput
和换行符中包含两个字符。上面的if(...)
条件读取第二个字符(如果有的话)(使用cInput
的短路评估),并检查它是输入的结尾(换行符)。如果不是,则会读取所有缓冲的字符,然后使cInput
无效(例如,如果输入"No-way\n"
,则cinput
包含'N'
。
对于数字输入,您只需读取字符,直到找到换行符:
scanf("%d", &nValue);
while( getchar() != '\n' ) { } // flush buffered line
如果尾随的非数字字符应该使整个输入无效,则需要检查以下字符是否为换行符。
int converted = scanf("%d", &nValue);
if( converted == 0 || getchar() != '\n' )
{
valid_input = false ;
while( getchar() != '\n' ) { } // flush buffered line
}
请注意,还有其他可能的解决方案。这是我的首选解决方案。
当应用于您的功能时(通过其他简化):
int intAskUser(void)
{
char cInput = 0 ;
while( cInput != 'N' && cInput != 'Y' )
{
printf("Do you want to enter a value? Y or N\n");
scanf("%c", &cInput ) ;
if( cInput != '\n' && getchar() != '\n' )
{
while( getchar() != '\n' ) { } // flush buffered line
cInput = 0 ;
}
else
{
cInput = toupper(cInput) ;
}
}
// Return answer code 0 to 1
return (cInput == 'N') ? 0 : 1 ;
}
int getValue(int nLower, int nUpper)
{
assert( nLower < nUpper ) ; // precondition check
int nValue = 0 ;
bool valid_input = false ;
while( !valid_input )
{
printf("Enter a value between %d and %d: ", nLower, nUpper ) ;
int converted = scanf("%d", &nValue);
if( converted == 0 || getchar() != '\n' )
{
valid_input = false ;
while( getchar() != '\n' ) { } // flush buffered line
}
valid_input = nValue >= nLower &&
nValue <= nUpper ;
if( !valid_input )
{
printf( "Please try again. " );
}
}
printf("Value: %d", nValue);
return nValue;
}
请注意,toupper()
需要包含ctype.h
,而bool
类型需要stdbool.h
。
答案 1 :(得分:0)
如果我正确理解了您的问题,您希望在用户输入为
的任何一个时返回该函数y
后跟新行Y
后跟新行n
后跟新行N
后跟新行在所有其他情况下,您希望保留在该功能中并获得新的用户输入(例如nYnhhh
后跟换行符不返回)。
据我所知,没有可以实现的标准功能,所以你必须编写自己的代码。
当这样做时,有两件事需要记住:
\n
作为最后一个字符的输入。最后,我建议您使用fgets()
代替scanf()
,因为它更容易使用。不要使用gets()
- 它很容易受到缓冲区溢出的影响。
您的代码可能如下所示:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int AskUser(void)
{
char input[3] = {'\0'}; // Make room for a string of 2 chars + terminating null
int c;
int len;
printf("Do you want to enter a value? Y or N\n");
do
{
if (!fgets(input, 3, stdin))
{
printf("Input error");
exit(1);
}
len = strlen(input);
if (len)
{
if (input[len-1] != '\n') // Check whether last char is a newline
{
// It isn't so empty the input buffer
while ((c = getchar()) != '\n' && c != EOF) { }
}
}
if (len == 2) // Check for exactly 2 chars in input
{
if(toupper(input[0]) == 'Y' && input[1] == '\n')
{
return 1;
}
if(toupper(input[0]) == 'N' && input[1] == '\n')
{
return 0;
}
}
printf("Please enter a valid input, Y or N: \n");
} while(1);
}
int main(void) {
printf("Answer is %d\n", AskUser());
return 0;
}