簡體   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