在 D readf 中输入了错误的类型后如何读取输入?
How can I read input after the wrong type has been entered in D readf?
我想知道在程序读取了不合适的值后如何继续在 D 中使用标准输入。 (例如,期待 int 时的字母)
我写这个是为了测试它:
import std.stdio;
void main()
{
int a;
for(;;){
try{
stdin.readf(" %s", a);
break;
}catch(Exception e){
writeln(e);
writeln("Please enter a number.");
}
}
writeln(a);
}
输入不正确的值(例如'b')后,程序会不确定地打印出消息。我还检查了表明它试图再次读取相同字符的异常,所以我做了一个这样的版本:
import std.stdio;
void main()
{
int a;
for(;;){
try{
stdin.readf(" %s", a);
break;
}catch(Exception e){
writeln(e);
writeln("Please enter a number.");
char c;
readf("%c", c);
}
}
writeln(a);
}
尝试读取 a 而不是 c 时仍然抛出异常。我也尝试使用 stdin.clearerr(),但没有效果。有谁知道如何解决这个问题?谢谢
我的建议:不要使用 readf
。太糟糕了。每个人都首先使用它,因为它在 stdlib 中(自 1979 年以来一直如此,哈哈,scanf 有……而且我认为 scanf 比 readf 更好!但我离题了),几乎每个人都遇到了麻烦。当它正确时,它对格式和空格消耗非常挑剔,而当它出错时,它会给出糟糕的错误消息并使输入流处于不确定状态。而且,最重要的是,它在实际读取的数据类型方面仍然非常有限,而且对用户非常不友好,甚至不允许在大多数系统上进行退格等操作!
比 readf
稍微好一点的是使用 readln
然后 strip
和 to!int
一旦你检查了行并给出了错误。像这样:
import std.stdio;
import std.string; // for strip, cuts off whitespace
import std.algorithm.searching; // for all
import std.ascii; // for isAscii
import std.conv; // for to, does string to other type conversions
int readInt() {
for(;;) {
string line = stdin.readln();
line = line.strip();
if(all!isDigit(line))
return to!int(line);
else
writeln("Please enter a number");
}
assert(0);
}
void main()
{
int a = readInt();
writeln(a);
}
我知道有很多进口垃圾邮件(还有一堆单独的琐碎功能),readln 对最终用户来说仍然很糟糕,但是这个小功能对您的用户和自己而不是尝试使用 readf。它将始终如一地 一次消耗一行并给出一个很好的信息。此外,相同的模式可以扩展到您需要的任何其他类型的验证,并且可以将对 readln
的调用替换为对更用户友好的函数的调用,该函数允许稍后编辑和历史记录以及其他内容,如果您决定沿着那条路走下去。
如果您无论如何都必须使用 readf
,那么在 catch
块中使事情恢复正常的最简单方法仍然是调用 readln
并丢弃其结果。因此,它只是跳过包含错误的整行,让您的用户重新开始。如果他们正在做“1 2”并且希望一次读取两个整数,那也会下降......但是,嗯,我宁愿重新开始它们,也不愿尝试在中途选择错误的行。
我想知道在程序读取了不合适的值后如何继续在 D 中使用标准输入。 (例如,期待 int 时的字母) 我写这个是为了测试它:
import std.stdio;
void main()
{
int a;
for(;;){
try{
stdin.readf(" %s", a);
break;
}catch(Exception e){
writeln(e);
writeln("Please enter a number.");
}
}
writeln(a);
}
输入不正确的值(例如'b')后,程序会不确定地打印出消息。我还检查了表明它试图再次读取相同字符的异常,所以我做了一个这样的版本:
import std.stdio;
void main()
{
int a;
for(;;){
try{
stdin.readf(" %s", a);
break;
}catch(Exception e){
writeln(e);
writeln("Please enter a number.");
char c;
readf("%c", c);
}
}
writeln(a);
}
尝试读取 a 而不是 c 时仍然抛出异常。我也尝试使用 stdin.clearerr(),但没有效果。有谁知道如何解决这个问题?谢谢
我的建议:不要使用 readf
。太糟糕了。每个人都首先使用它,因为它在 stdlib 中(自 1979 年以来一直如此,哈哈,scanf 有……而且我认为 scanf 比 readf 更好!但我离题了),几乎每个人都遇到了麻烦。当它正确时,它对格式和空格消耗非常挑剔,而当它出错时,它会给出糟糕的错误消息并使输入流处于不确定状态。而且,最重要的是,它在实际读取的数据类型方面仍然非常有限,而且对用户非常不友好,甚至不允许在大多数系统上进行退格等操作!
比 readf
稍微好一点的是使用 readln
然后 strip
和 to!int
一旦你检查了行并给出了错误。像这样:
import std.stdio;
import std.string; // for strip, cuts off whitespace
import std.algorithm.searching; // for all
import std.ascii; // for isAscii
import std.conv; // for to, does string to other type conversions
int readInt() {
for(;;) {
string line = stdin.readln();
line = line.strip();
if(all!isDigit(line))
return to!int(line);
else
writeln("Please enter a number");
}
assert(0);
}
void main()
{
int a = readInt();
writeln(a);
}
我知道有很多进口垃圾邮件(还有一堆单独的琐碎功能),readln 对最终用户来说仍然很糟糕,但是这个小功能对您的用户和自己而不是尝试使用 readf。它将始终如一地 一次消耗一行并给出一个很好的信息。此外,相同的模式可以扩展到您需要的任何其他类型的验证,并且可以将对 readln
的调用替换为对更用户友好的函数的调用,该函数允许稍后编辑和历史记录以及其他内容,如果您决定沿着那条路走下去。
如果您无论如何都必须使用 readf
,那么在 catch
块中使事情恢复正常的最简单方法仍然是调用 readln
并丢弃其结果。因此,它只是跳过包含错误的整行,让您的用户重新开始。如果他们正在做“1 2”并且希望一次读取两个整数,那也会下降......但是,嗯,我宁愿重新开始它们,也不愿尝试在中途选择错误的行。