2015-02-07 45 views
-3

我寫了這個簡單的程序。我知道,在C printf()函數返回成功打印字符的總數,因爲任何非零值是C.檢查C和C++中的輸出錯誤

#include <stdio.h> 

int main(void) 
{ 
    if (printf("C")) 
    return 0; 
} 

true評估下面的C程序工作正常,但爲什麼下面的C++程序編譯&運行良好?如果cout是一個對象而不是函數,那麼爲什麼程序會給出預期的輸出?

#include <iostream> 
using namespace std; 

int main() { 
    if (cout << "C++") 
    // your code goes here 
    return 0; 
} 

回答

4
std::cout << "C++"; 

是一個函數調用std::operator<<(std::cout, const char*)它返回一個參考std::cout,其可轉化成bool。如果std::cout沒有發生錯誤,它將評估爲true

+1

in C++ 11轉換爲bool不是隱式的 – 2015-02-07 17:12:28

+1

@IvayloStrandjev對,謝謝。 – 2015-02-07 17:14:18

0

因爲這是一樣的書寫

cout << "C++"; 
if(cout){ 
//do whatever 
} 

它只是寫道:「C++」來清點和檢查,如果您的流仍處於打開狀態。

1

<<運營商返回cout。這就是爲什麼你可以鏈<<操作是這樣的:

std::cout << "Hello" << " " << "C++" << " " << "World!" << std::endl; 

返回cout會隱CONVER的值true在IF。

1

我不完全知道你正在嘗試做的,但假設你希望你的程序成功退出,當且僅當打印成功,你應該寫在C:

#include <stdlib.h> 
#include <stdio.h> 

int 
main() 
{ 
    if(printf("C") < 0) 
     return EXIT_FAILURE; 
    return EXIT_SUCCESS; 
} 

的原因是printf將返回一個負數來報告錯誤,-1也被認爲是「真」。

相應的C++程序應該是這樣的:

#include <cstdlib> 
#include <iostream> 

int 
main() 
{ 
    if (!(std::cout << "C++")) 
    return EXIT_FAILURE; 
    return EXIT_SUCCESS; 
} 

這部作品的原因是,在std::cout調用operator <<返回流本身,這也就是爲什麼之類的東西

參考
std::cout << "You've got " << 99 << " points" << std::endl; 

工作。每次調用都會返回對std::cout的引用,然後執行下一次調用。

現在,std::basic_ios其中std::cout源自於,定義了conversion operator。由於C++ 11,這被聲明爲

explicit operator bool() const; 

這意味着,如果流在布爾上下文中計算諸如作爲在if語句中的條件,它被轉換爲一個boollinked page底部的表格顯示在什麼條件下返回的bool將是truefalse。總之:它將返回true,除非在流上發生錯誤。

在C++ 11之前(當我們沒有explicit運算符時),當且僅當流中沒有錯誤發生時,才返回一個void *指針,該指針爲非NULL。再次,可以在布爾上下文中評估指針void *

請注意,在上面顯示的兩個程序中,測試可能表示成功,但輸出可能仍然失敗。原因是輸出通常在程序內緩衝,並且只有在收集足夠的輸出時纔會要求操作系統實際執行輸出。您可以隨時要求沖洗以使其發生現在。在C中,你可以在相應的FILE *指針上調用fflush

#include <stdlib.h> 
#include <stdio.h> 

int 
main() 
{ 
    if(printf("C") < 0 || fflush(stdout) < 0) 
     return EXIT_FAILURE; 
    return EXIT_SUCCESS; 
} 

在C++中,您可以使用std::flush常量。

#include <cstdlib> 
#include <iostream> 

int 
main() 
{ 
    if (!(std::cout << "C++" << std::flush)) 
    return EXIT_FAILURE; 
    return EXIT_SUCCESS; 
} 

如果您還想換行,可以使用std::endl。寫

std::cout << "hello, world\n" << std::flush; 

具有大致相同的效果寫

std::cout << "hello, world" << std::endl; 

然而要注意輸出緩衝用於性能的原因,所以如果你經常每一個輸出語句之後刷新你的緩衝區,你可能會降低你的程序的性能。

最後,在C++中,如果發生錯誤,您還可以請求流拋出異常。由於在正常操作期間I/O錯誤不應該發生,並且重複檢查它們可能會使代碼混亂,這可能會派上用場。

#include <cstdlib> 
#include <iostream> 

int 
main() 
{ 
    std::cout.exceptions(std::ifstream::failbit); 
    try 
    { 
     std::cout << "C++" << std::flush; 
     return EXIT_SUCCESS; 
    } 
    catch (const std::ios_base::failure &e) 
    { 
     return EXIT_FAILURE; 
    } 
} 

如果你想測試你的程序是否報告正確的退出狀態失敗I/O,你可以嘗試管道標準輸出/dev/full對POSIX系統。 /dev/full是一個特殊的文件,假裝由於文件系統的容量已超出,因此無法寫入任何文件。

+0

+5爲偉大的答案。 – Destructor 2015-11-13 19:09:54