繁体   English   中英

有关在Objective-C中验证用户输入的问题,编号与字符串

[英]Questions about validating user input in Objective-C, number vs string

如果您输入非数字字符,为什么“确切”这个代码会无休止地循环?

第一个问题是因为我想学好防守编码。 有谁知道检查用户输入的好方法? 我的google-fu让我失望了。 有些人似乎认为,如果我在scanf中指定%f ,我“要求” float ; 我在某种程度上通过打印userInput的值来验证这userInput 事实上,如果我注释掉do while循环,那么执行代码就没有问题了。 它为userInput分配一个0并开始其业务。

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    float userInput;
    float result;

    NSLog(@"3X^3 -5x^2 + 6");

    do {
        NSLog(@"What is x?");
        scanf("%f", &userInput);
        NSLog(@"userInput = %f", userInput);
    } while(userInput == 0);

    result = 3 * (userInput * userInput * userInput) - 5 * (userInput * userInput) + 6;
    NSLog(@"the result is: %f", result);

    [pool drain];
    return 0;
}

这与Objective-C或Cocoa无关。 问题只是使用标准C库函数scanf ,并处理错误情况。 scanf联机帮助页,描述返回码:

零表示虽然有可用输入,但没有分配转换; 通常这是由于输入字符无效,例如'%d'转换的字母字符。

scanf可以使用%f说明符解析有效的数字输入,因此显然可以按预期工作。 但是如果输入非数字字符,则scanf无法将其转换为float,并将文本stdinstdin的缓冲区中 由于代码没有检查scanf的返回代码,只测试userInput是否为非零,因此循环永远不会退出,因为userInput恰好从0.0开始,并且永远不会更新,因为scanf不会提取非数字stdin缓冲区中的字符。 这就是为什么你的代码在无限循环中运行的原因。

如果已将userInput初始化为非零值,则会以一种方式解决问题,因为非数字输入会导致scanf失败并触发while条件。 但更好的解决方法是检查scanf的返回码。 如果它为零,则打印错误消息,并在再次循环之前执行fpurge(stdin)清除无效输入,如下所示:

int rc = scanf("%f", &userInput);
if (rc == 0)
{
    NSLog(@"Invalid input, try again.");
    fpurge(stdin);
}

所以这是输入和解析的简单C方法。 防御性编码的底线是你应该经常检查返回码!

正如Chris所提到的,对于一个实际的Cocoa应用程序,你会想要查看NSNumberFormatter之类的东西,但是你可能会从小部件而不是文件流中获取输入,因此代码与上面的代码完全不同。

在Cocoa中验证用户输入的正确方法是使用NSFormatter的适当子类的实例,在这种情况下类似于NSNumberFormatter。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM