让我们假设以下代码:
from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string("""
<UserSelectionInput@BoxLayout>:
orientation: 'horizontal'
size_hint: None, 1
spacing: 4
lb_text: ''
sp_values: '', ''
text: user_selection_spinner.text
Label:
id: user_selection_label
size_hint_x: 0.4
text: root.lb_text
Spinner:
id: user_selection_spinner
text: 'Select'
values: root.sp_values
<InnerBox@AnchorLayout>:
anchor_x: 'center'
anchor_y: 'center'
BoxLayout:
orientation: 'horizontal'
size_hint: None, 1
width: 2 * root.width / 3
spacing: 1
UserSelectionInput:
width: root.width / 3
sp_values: 'A', 'B', 'C'
lb_text: 'Type'
on_text:
print("UserSelectionInput.spinner_1: text=", self.text)
UserSelectionInput:
width: root.width / 3
sp_values: 'D', 'E', 'F', 'G'
lb_text: 'Version'
on_text:
print("UserSelectionInput.spinner_2: text=", self.text)
<MainContent@GridLayout>:
rows: 3
Label:
text: "Some Text"
GridLayout:
cols: 1
InnerBox:
MainContent:
"""))
如何确保用户提供的数据是整数(而不是char)?
是否存在用于确保用户读取数据的库?
答案 0 :(得分:0)
您需要围绕scanf
进行其他工作。
首先,scanf
将返回成功的转换和分配的次数-在这种情况下,您期望1
成功。如果没有成功的转换和分配,它将返回0
。如果输入错误,它将返回EOF
。
因此,作为第一步,您将执行以下操作:
if ( scanf( "%d", &n ) != 1 )
// input was not an integer or error on input
else
// successful input, do something with n
仅靠这本身是不够的。
%d
告诉scanf
跳过前导空格,然后读取第一个非数字字符。如果输入"abc"
,则没有有效的数字字符,scanf
返回0
,而n
未经修改。
但是,如果您输入"12c"
之类的字符串,则会读取并转换"12"
,n
将被赋值为12
,scanf
将返回1
,并且 'c'
将留在输入流中以阻止下一次读取。理想情况下,您应该拒绝整个输入。
有两种解决方法。您可以在输入后立即查看字符-如果它是空格,则输入有效:
char dummy;
int items_read = scanf( "%d%c", &n, &dummy );
如果items_read
为2,则表示scanf
至少读 一个十进制数字字符,然后读取一个非十进制数字字符。如果dummy
包含空格字符,则表示输入为有效整数。如果dummy
包含非空格字符,则用户在输入中用手指指了一个非数字字符(这意味着n
中的值不应被信任)。无论哪种方式,我们都需要先将该虚拟字符推回输入流,然后再继续。
如果items_read
为1,则表示我们至少读取 个十进制数字字符,然后按EOF键,这意味着我们的输入也必须是有效的整数。
因此,测试看起来像这样:
if ( items_read == 2 && isspace( dummy ) || items_read == 1 )
{
// do something with n
if ( items_read == 2 )
ungetc( dummy, stdin );
}
else
{
// input was not an integer, or error on input
}
或者,您可以将输入作为 string 读取,然后使用strtol
进行转换:
char input[MAX_INPUT_LENGTH+1];
if ( fgets( input, sizeof input, stdin ) ) // using fgets instead of scanf for this
{
char *chk; // stores address of first character *not* converted
long tmp = strtol( input, &chk, 0 ); // convert into a temporary
if ( isspace( *chk ) || *chk == 0 )
{
// input is good, assign tmp to n
if ( tmp <= INT_MAX && tmp >= INT_MIN )
n = tmp;
else
// input was within range for long but not int
}
else
// trailing non-digit character
}