2012-10-14 34 views
1

什麼如何使用斷言功能

assert(scanf("%d", &t) == 1); 

assert(1 <= t && t <= 10); 

回報?

我的目標是含有1 t至10

+1

這在技術上是一個宏,不是一個函數。 – chris

+0

第一次檢查用戶輸入是否爲1,另一次檢查範圍是否在1到10之間 – MimiEAM

+1

@MimiEAM,'scanf'的返回值是成功輸入的項目數。 – chris

回答

1
assert(expression);​ 

什麼斷言確實是評估表達,如果它的計算結果進行比較,以0 /假,程序終止。

7

不要在用戶輸入中使用斷言。 Assert旨在通過崩潰程序來捕獲邏輯錯誤(通過在斷言失敗時調用中止),並且用戶輸入不會導致程序崩潰。

但要回答你的問題,如果NDEBUG被定義,然後assert什麼都不做。這可能是您的程序未按預期崩潰的原因。

+4

實際上,它的目的是通過在故障點_terminating_你的程序來捕獲邏輯錯誤,而不是你的程序_crashing_在覆蓋你的音樂文件夾中的所有字節 –

+0

之後潛在很遠,即我不會調用什麼'assert'會「崩潰「 –

+2

@LightnessRacesinOrbit - 對我來說,」崩潰「是當一個程序終止時,一個信號使程序掉核。這正是'assert'所做的。 'assert'的SIGABRT和'malloc'或'free'的SIGABRT在進入恐慌模式時有什麼區別?您使用'assert'來檢測程序員錯誤,而不是用戶錯誤。對於程序員來說,核心轉儲是一個很好的錯誤信息。對於用戶來說,核心轉儲是一個非常糟糕的錯誤消息。 –

6

你可以假設斷言聲明爲以下幾點:

/*! 
* Immediately crash the program if assumption is proven invalid. 
*/ 
void assert (bool assumption); 

如果你「知道」一個變量t絕不會超出範圍[1,10],因爲你寫的代碼,並有沒有辦法你的代碼可以產生任何其他值,那麼它是適當的斷言該聲明。

斷言明顯的事情

考慮以下使用斷言:

int t = 9; 
assert (9 == t); // A very valid assertion, if a little pedantic. 

上面的代碼應該看起來像說明明顯。聲明的表達(顯然)是真實的,但更重要的是任何其他結果將是瘋狂的。知道t != 9會清除所有關於C++如何工作的假設,計算機如何執行數學和存儲值,無論我們是否存在,或者意識是否僅僅是由許多惡化的電子形成的錯覺...

但這就是斷言的價值。

即使這樣的電腦是爲所有實際目的100%確定性,「瘋狂」的事情發生。這也不是罕見的。實際上,我們在我們的代碼中明確地寫出斷言來檢測這些情況,並給我們一個機會來找出發生了什麼。 這裏考慮幾個真實世界的瘋狂行爲原因。「瘋狂」 的行爲

原因

你的斷言應該防範此類錯誤的...

  1. 不正確的線程同步。

    int t; 
    
    // Thread 1 
    t = 9; 
    assert(t == 9); 
    
    // Thread 2 
    t = 3; 
    assert(t == 3); 
    
  2. 內存管理不好。

    class X { 
        void sayHello() { 
         assert(this != NULL); // An object that does not exist cannot say hello. 
         std::cout << "Hello?" << std::endl; 
        } 
    }; 
    
    // Without the assertion, this code would actually run! 
    X* x = NULL; 
    x->sayHello(); 
    
  3. 堆棧(或堆)腐敗。

    (合理的例子見Stack corruption in C++。)

行爲是不方便,但不是瘋了:

雖然這可能會大大改變你的程序的執行路徑,這些東西都是不合適的斷言。拋出異常,打印錯誤,很好地關閉程序,並負責任地清理程序的資源。 不要斷言這些「失敗」!

  1. 用戶輸入了一些荒謬的東西。

    int t; 
    scanf("%d", &t); 
    assert (0 <= t <= 10);  // What, are you friends with this user? 
               // You're going to let him crash your program? 
    
  2. 某些I/O設備發生故障。

    int s = socket(); 
    // blah blah connect blah blah 
    
    char buffer[64]; 
    int bytes_received = recv(s, buffer, 64, NULL); 
    assert (bytes_received > 0); // Do you know how hard it is to send a packet 
               // from Estonia to the US?! 
    

這個列表是不完整的,但它應該給你如何(以及如何不)應用的斷言更廣泛的指南。

0

妥善解決你的問題是封裝在一個函數scanf()功能,知道它在做什麼:

int AskNumberOfWidgetFrobs() { 
    int count = 0; 
    for(;;) // Until we get a valid number 
    scanf("%d", &count); 
    if (count > 0 && count <= 10) { 
     return count; 
    } else { 
     printf("%d is not a valid number of WidgetFrobs\n", count); 
    } 
    } 
} 
1

這是我希望這樣回答的:

Specifiy

#include <assert.h> 

在源文件開始的單獨行中。

現在,只要bool不正確,您就可以使用assert(bool)來終止程序。

(其他的答案是這樣一個問題:「如何使用斷言正確」)