2013-07-11 210 views
7

我想在if語句的括號中聲明一個局部變量。例如, 。如何在if語句的括號中聲明一個變量?

if((char c = getc(stdin)) == 0x01)//This is not OK with g++. 
{ 
    ungetc(c, stdin); 
} 

我想要的是看看角色是否是我想要的角色。 一般來說,我想在如果如果但是不在如果之外使用變量(char c)。

但g ++(GCC 4.8.1)說期望在'char'之前的主表達式。 我不知道是否有一種方法可以做到這一點,因爲我不希望像

char c = getc(stdin); 
if(c == 0x01) 
{ 
    bla... 
} 
+3

你可能會濫用'for'循環。 – SLaks

+2

如果是污染問題,您可以隨時使用新的作用域或for循環。 – chris

+0

最簡潔(愚蠢)的解決方案可能是'if(int c = getc(stdin) - 1); else ungetc(c + 1);'。 – Potatoswatter

回答

17

如果這是你擔心你總是可以定義命名空間污染區塊內if聲明:

{ 
    char c = getc(stdin); 
    if(c == 0x01) 
    { 
     // ... 
    } 
} 

這樣c將只持續,直到到達塊的結束。

+4

雖然沒有回答問題,但這種寫代碼的方式簡單明瞭有效。謝謝。 – Wesley

+3

@ qlb1234有時候一個問題,就像你的情況一樣,有效地詢問「我如何最好地編寫錯誤的代碼」。這些問題不應該用「這就是你如何編寫錯誤的代碼」來解決,而是「不要編寫錯誤的代碼,而是做這個」。 :-) –

+2

@NikosC .:這個答案的吸引力在於它的簡單性,但我很少在代碼評論中發現這樣的結構是可以接受的。當我看到像這樣的獨立語句塊時,我總是認爲代碼應該在一個單獨的函數中。 – jxh

10

我不知道如何創建一個變量,並看到一些貼後測試其與if值,直到解決方案。但是,您可以使用switch。這將允許你向另外的值(也許EOF)反應:

switch (int c = getc(stdin)) { 
case 0x01: ungetc(c, stdin); break; 
case EOF: // ...handle EOF 
default: break; 
} 

你總是可以放置if聲明內聯函數來代替,而且代碼看起來乾淨了一點。如果你確實需要在該位置的源代碼,但是沒有用一個新變量在if周圍創建一個新的範圍,那麼你可能會接受一個lambda。

[](int c){ if (c == 0x01) ungetc(c, stdin); }(getc(stdin)); 

由於您只對一個值M比較您的具體問題並不需要一個變量可言,所以你可以簡單地做:

if (getc(stdin) == 0x01) { 
    char c = 0x01; 
    ungetc(c, stdin); //or bla... 
} 

如果你想要進行比較的一組值,那麼switch建議是更好的選擇。

傑裏棺材的解決方案看起來有吸引力,但它確實可以歸結爲:

if (int c = (getc(stdin) == 0x01)) //... 

這可能不是你真正想要的,因爲它如果要比較從0x01不同的值,並不能一概而論好。

Potatoswatter的解決方案似乎更接近你想要什麼,但也許這將是更好的拉式出到一個獨立的類:

template <typename T> 
class SetAndTest { 
    const T test_; 
    T set_; 
public: 
    SetAndTest (T s = T(), T t = T()) : set_(s), test_(t) {} 
    operator bool() { return set_ == test_; } 
    operator bool() const { return set_ == test_; } 
    operator T &() { return set_; } 
    operator T() const { return set_; } 
}; 

//... 
if (auto c = SetAndTest<int>(getc(stdin), 0x01)) { 
    ungetc(c, stdin); //or bla... 
} 
+2

這就是......聰明:p – chris

+0

哇,從來沒有想到這一點。 – Manas

+0

你爲什麼要重複操作符重載? – aah134

8

可以if語句裏面定義變量就好了。例如,這應該編譯:

if (int ch = getchar()) 
    ; 

問題是,類型(例如,,int)必須在右括號後跟着。你有的額外括號是導致編譯失敗的原因。所以,如果你真的想這樣做,你需要得到一個小聰明,用這樣的:一部分後

if (char ch = 0 || ((ch = getchar()) == 0x1)) 

這可以讓你創建和初始化ch做,然後的表達是完整的,放在圍繞ch=getchar()的括號中以覆蓋賦值與比較的優先級。

請注意,&&||做短路評估,所以你需要小心你的初始化。您可以使用:

if (char ch = 0 || ... 

...或:

if (char ch = 1 && ... 

...但如果您嘗試使用if (ch = 1 || ...if (ch = 0 && ...,短路評估將保持正確的操作數(部分你真的關心)被評估。

現在需要注意的是,雖然我相當肯定這段代碼符合標準的要求,而且大多數(所有)當前編譯器都會接受它,但很可能會導致大多數程序員閱讀代碼時會認真摸清頭緒你已經完成了,爲什麼。我會非常猶豫(充其量)關於在實際代碼中使用這種「技術」。

編輯:有人指出,由此產生的結果可能比最初期望的更具誤導性,所以我會試着澄清一下情況。會發生什麼是從輸入中讀取一個值。該值分配給ch並與0x1進行比較。到現在爲止還挺好。之後,比較結果(轉換爲整數,因此01)將被分配到ch。我相信它有足夠的順序點,結果是定義的行爲。但這可能不是你或者任何人想要的 - 因此你可能不想使用它的建議,以及提及它可能會讓大多數程序員撓着腦袋,想知道你在做什麼。在與0x1進行比較的特定情況下,if語句內的ch值將爲1,但這或多或少都是巧合。如果您比較的是0x2,則if內的ch的值仍將爲1,而不是2

+0

難道你不能使用逗號嗎? – sje397

+0

@ sje397:奇怪的是,沒有 - 在這種情況下不允許。 –

+0

'0 ||'部分是做什麼的?看起來'ch = true'將不可避免地發生在'ch = getchar()'之後。 – Potatoswatter

相關問題