C 检查意外用户输入的方法
我明白了,一个人永远不应该相信用户的输入。在处理它之前检查它已经成为一种习惯。我几乎总是使用这种类型的函数,并且经常想知道这两个版本之间是否有差异 下面是我的检查函数的简单示例: 第1版C 检查意外用户输入的方法,c,validation,input,C,Validation,Input,我明白了,一个人永远不应该相信用户的输入。在处理它之前检查它已经成为一种习惯。我几乎总是使用这种类型的函数,并且经常想知道这两个版本之间是否有差异 下面是我的检查函数的简单示例: 第1版 int checkASCII(char c) // Here we check, print error and return if it succeeded or not { if (!isascii(c)) { fprintf(stderr, "Error. Not an A
int checkASCII(char c) // Here we check, print error and return if it succeeded or not
{
if (!isascii(c))
{
fprintf(stderr, "Error. Not an ASCII character.\n.");
return 1;
}
if (!isdigit(c))
{
fprintf(stderr, "Error. Not a number.\n.");
return 1;
}
// potentially more checks
return 0;
}
int printASCIINumber() // So that here we just have to verify the success
{
char c;
c = getc(stdin);
if (checkASCII(c))
putc(c, stdout);
else return 1;
return 0;
}
第2版
int checkASCII(char c) // Here we just check errors regardless of what failed
{
if (!isascii(c))
return 1;
if (!isdigit(c)
return 1;
... // potentially more checks
return 0;
}
int printASCIINumber() // And here we verify success and print a general error message
{
char c;
c = getc(stdin);
if (checkASCII(c))
putc(c, stdout);
else
{
fprintf(stderr, "Error. Please input an ASCII number.\n");
return 1;
}
return 0;
}
如果有任何目标需要改进,我也不反对。谢谢。首先:您的返回值与您随后进行的检查不匹配。如果你认为结果是一个错误代码,0表示成功,那么你必须通过<代码>(如果.CasaScCII(C))< /C> >进行测试。如果你认为结果是布尔值,那么你需要反转返回的值。在这种情况下,我建议包括
,将返回类型更改为bool
,并将函数重命名为isASCII
。这将使你的意图更加明显
比较您的两个版本,我想说,总的来说,这两个版本都不优于另一个版本——这取决于您正在编程的环境
假设您正在编写一些通用库。然后我当然更喜欢变量2,因为您不知道使用您的库的人是否需要控制台输出,或者控制台是否可用(linux守护进程、windows服务等)。无论出于何种原因,用户都可能希望使用自己的日志记录功能
另一方面,如果您只编写程序中使用的帮助器函数,变体1可能更方便:
- 您可以直接在发生故障的函数中提供更细粒度的输出,而无需在函数外计算一些errno或返回值(这可能是库函数提供有关出错原因的进一步信息的方式)
- 当您调用测试函数时,能够依赖已经完成的日志记录是很方便的,特别是在频繁调用检查函数的情况下,这样您就可以继续编写代码了
,将返回类型更改为bool
,并将函数重命名为isASCII
。这将使你的意图更加明显
比较您的两个版本,我想说,总的来说,这两个版本都不优于另一个版本——这取决于您正在编程的环境
假设您正在编写一些通用库。然后我当然更喜欢变量2,因为您不知道使用您的库的人是否需要控制台输出,或者控制台是否可用(linux守护进程、windows服务等)。无论出于何种原因,用户都可能希望使用自己的日志记录功能
另一方面,如果您只编写程序中使用的帮助器函数,变体1可能更方便:
- 您可以直接在发生故障的函数中提供更细粒度的输出,而无需在函数外计算一些errno或返回值(这可能是库函数提供有关出错原因的进一步信息的方式)
- 当您调用测试函数时,能够依赖已经完成的日志记录是很方便的,特别是在频繁调用检查函数的情况下,这样您就可以继续编写代码了
char
s更改为int
s(所有这些函数都需要int
)getc
需要一个,以便捕获EOF
,以及ctype系列函数。if(!checkASCII(c))
?@BLUEPIXY只检查失败,因为检查失败和成功都是无用的?我的评论是,这与它的意图相反。关于可移植性的兴趣点:isascii()
不在标准库中,而是gcc中的BSD扩展,并且在POSIX中。将isascii()
标记为已过时,并声明此函数可能会从未来版本中删除。是的,将所有char
s更改为int
s(所有这些函数都需要int
)getc
需要一个,以便捕获EOF
,以及ctype系列函数。if(!checkASCII(c))
?@BLUEPIXY只检查失败,因为检查失败和成功都是无用的?我的评论是,这与它的意图相反。关于可移植性的兴趣点:isascii()
不在标准库中,而是gcc中的BSD扩展,并且在POSIX中。将isascii()
标记为已过时,并声明此函数可能会从将来的版本中删除。如果我必须编写库,为流添加参数以打印版本1中的错误会是一个好主意吗?或者设置一个全局常量变量,该变量将在每个检查函数中调用?@Badda通过添加一个流参数,您可以强制用户提供一个参数——即使他根本不想有任何日志记录/输出——或者流可能与他自己的日志记录系统不兼容,因此他必须以任何合适的方式解决此问题(比如创建自己的流实现,这可能效率低下)。全局变量-好吧,它不能是常量,否则您不能设置它…但正是出于这个目的,已经有一个:errno
(includeerrno.h
)。优点:(通常!)它是线程安全的,因为每个线程都有一个实例……顺便说一下,BADA——流是C++概念,用C来获得这样的灵活性比较困难。