2013-07-11 57 views
7

Tôi muốn khai báo biến cục bộ trong dấu ngoặc của câu lệnh if. Ví dụ.Làm thế nào để khai báo một biến trong dấu ngoặc của câu lệnh if?

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

Điều tôi muốn là, để xem liệu ký tự đó có phải là ký tự tôi muốn hay không. Để nói thông thường, tôi muốn sử dụng biến (char c) cả hai trong dòng nếu và phần thân của nếu, nhưng không nằm ngoài số nếu.

Nhưng g ++ (GCC 4.8.1) nói biểu thức chính được mong đợi trước 'char'. Tôi tự hỏi nếu có một cách để làm điều đó, bởi vì tôi không muốn cái gì đó như

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

Bạn có thể lạm dụng vòng lặp 'for'. – SLaks

+2

Nếu đó là về ô nhiễm, bạn luôn có thể sử dụng phạm vi mới hoặc vòng lặp for. – chris

+0

Giải pháp gọn gàng nhất (ngu ngốc) có lẽ là 'if (int c = getc (stdin) - 1); khác ungetc (c + 1); '. – Potatoswatter

Trả lời

17

Nếu đó là tình trạng ô nhiễm không gian tên bạn đang lo lắng về việc bạn luôn có thể xác định if tuyên bố trong một khối:

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

Vì vậy mà c sẽ chỉ kéo dài cho đến cuối của khối là đạt.

+4

Mặc dù không trả lời câu hỏi, nhưng cách viết mã này rất đơn giản, rõ ràng và hiệu quả. Cảm ơn bạn. – Wesley

+3

@ qlb1234 Đôi khi một câu hỏi, như trong trường hợp của bạn, là có hiệu quả yêu cầu "làm thế nào để tôi viết tốt nhất mã xấu". Những câu hỏi này không phải là câu trả lời với "đây là cách bạn viết mã xấu", nhưng với "không viết mã xấu, hãy làm điều này để thay thế." :-) –

+2

@NikosC .: Sự hấp dẫn của câu trả lời này là sự đơn giản của nó, nhưng tôi hiếm khi tìm thấy các cấu trúc như vậy được chấp nhận trong một đánh giá mã. Khi tôi thấy một khối câu lệnh độc lập như thế này, tôi luôn nghĩ rằng mã phải ở trong một hàm riêng biệt. – jxh

10

Tôi không biết làm thế nào để tạo ra một biến và kiểm tra giá trị của nó với một if cho đến khi sau khi nhìn thấy một số posted các giải pháp. Tuy nhiên, bạn có thể sử dụng switch. Điều này sẽ cho phép bạn phản ứng với những giá trị bổ sung (có lẽ EOF):

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

Bạn luôn có thể đặt câu lệnh if trong một chức năng inlined thay vào đó, và mã sẽ xem xét một chút bụi. Nếu bạn thực sự muốn mã nguồn ngay tại vị trí đó, nhưng không tạo phạm vi mới xung quanh một if với biến mới, thì có lẽ một lambda sẽ được chấp nhận cho bạn.

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

Vì bạn chỉ so sánh với một VALUEm vấn đề cụ thể của bạn không đòi hỏi một biến ở tất cả, vì vậy bạn chỉ có thể làm:

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

Nếu bạn đang muốn so sánh với một tập hợp các giá trị , sau đó đề xuất switch là tùy chọn tốt hơn.

giải pháp

Jerry Coffin trông hấp dẫn, nhưng nó thực sự nắm tới:

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

Đây có lẽ không phải những gì bạn thực sự muốn, vì nó không khái quát tốt nếu bạn muốn so sánh với một giá trị khác nhau từ 0x01 .

giải pháp Potatoswatter dường như gần gũi hơn với những gì bạn muốn, nhưng có lẽ nó sẽ đẹp hơn để kéo các loại ra vào một lớp độc lập:

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

Đó là ... thông minh : p – chris

+0

Wow, không bao giờ nghĩ về điều đó. – Manas

+0

tại sao bạn lặp lại quá tải của nhà điều hành? – aah134

8

Bạn có thể xác định biến bên trong câu lệnh if tốt. Ví dụ: điều này sẽ biên dịch:

if (int ch = getchar()) 
    ; 

Vấn đề là loại (ví dụ:, int) phải theo dõi ngay lập tức sau dấu ngoặc đơn mở. Dấu ngoặc đơn phụ bạn có là những gì gây ra biên dịch thất bại. Vì vậy, nếu bạn thực sự muốn làm điều này, bạn sẽ cần phải nhận được một chút thông minh và sử dụng một cái gì đó như thế này:

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

này cho phép bạn có được sự sáng tạo và khởi tạo của ch thực hiện, sau đó sau phần đó của biểu thức hoàn tất, đặt trong dấu ngoặc đơn xung quanh ch=getchar() để ghi đè quyền ưu tiên của bài tập so với so sánh.

Lưu ý rằng &&|| thực hiện đánh giá ngắn mạch, vì vậy bạn cần phải cẩn thận với việc khởi tạo của mình. Bạn có thể sử dụng một trong hai:

if (char ch = 0 || ... 

... hoặc:

if (char ch = 1 && ... 

... nhưng nếu bạn cố gắng sử dụng if (ch = 1 || ... hoặc if (ch = 0 && ..., việc đánh giá ngắn mạch sẽ giữ cho toán hạng bên phải (phần bạn thực sự quan tâm) từ việc được đánh giá ở tất cả.

Bây giờ hãy báo trước: trong khi tôi chắc chắn mã này phù hợp với yêu cầu của tiêu chuẩn, và hầu hết (tất cả?) Trình biên dịch hiện tại sẽ chấp nhận nó, nó có khả năng gây ra phần lớn các lập trình viên đọc mã bạn đã làm và tại sao. Tôi sẽ cực kỳ do dự (tốt nhất) về việc sử dụng "kỹ thuật" này trong mã thực.

Chỉnh sửa: Đã được chỉ ra rằng kết quả từ điều này có thể còn gây hiểu lầm nhiều hơn so với dự kiến ​​ban đầu, vì vậy tôi sẽ cố gắng làm rõ tình hình. Điều gì xảy ra là một giá trị được đọc từ đầu vào. Giá trị đó được gán cho ch và được so sánh với 0x1. Càng xa càng tốt. Sau đó, kết quả của phép so sánh (được chuyển đổi thành số nguyên, do đó, 0 hoặc 1) sẽ được gán cho ch. Tôi tin rằng nó có đủ các điểm trình tự mà kết quả được xác định hành vi. Nhưng nó có thể không phải là thứ bạn, hoặc bất kỳ ai, muốn - vì thế lời khuyên mà bạn có thể không muốn sử dụng, và đề cập đến việc nó có thể khiến hầu hết các lập trình gãi đầu, tự hỏi bạn đang cố làm gì. Trong trường hợp rất cụ thể so với 0x1, giá trị của ch bên trong tuyên bố if sẽ là 1, nhưng ít nhiều là trùng hợp ngẫu nhiên. Nếu bạn so sánh với 0x2, giá trị của ch bên trong if vẫn sẽ là 1, không phải là 2.

+0

Bạn cũng không thể sử dụng dấu phẩy? – sje397

+0

@ sje397: Rất kỳ quặc, không - không được phép trong trường hợp này. –

+0

Phần '0 ||' làm gì? Có vẻ như 'ch = true' chắc chắn sẽ xảy ra sau' ch = getchar() '. – Potatoswatter

Các vấn đề liên quan