2009-11-03 39 views
6

Tôi tạo ra một dự án mới với đoạn mã sau:Ký tự meta không xác định trong chuỗi ký tự C/C++?

char* strange = "(Strange??)"; 
cout << strange << endl; 

kết quả đầu ra sau đây:

(Strange]

Như vậy dịch '??)' -> ']'

Gỡ lỗi cho thấy rằng ký tự char * string của tôi thực sự là giá trị đó và nó không phải là bản dịch luồng. Đây rõ ràng không phải là chuỗi ký tự meta mà tôi từng thấy. Một số loại Unicode hoặc chuỗi char rộng có lẽ? Tôi không nghĩ như vậy tuy nhiên ... Tôi đã cố gắng vô hiệu hóa tất cả các thiết lập dự án liên quan để avail không có.

Mọi người đều có giải thích?

  • tìm kiếm: 'dấu hỏi, dấu chấm hỏi gần cú đúp' c C++ chuỗi chữ
+0

Câu hỏi này có thể giúp bạn: http://stackoverflow.com/questions/1234582/purpose-of-trigraph-sequences-in-c –

+0

cảm ơn ... Tôi đã thêm tìm kiếm ở cuối bài đăng của tôi với hy vọng rằng các tìm kiếm trong tương lai sẽ khớp với dấu hai chấm câu hỏi. Quyết định thiết kế này (bằng cách bật nó theo mặc định) là một từ: 'điên'. Để lại dấu vết cho OS/UI tôi nói. – Marius

+1

Trigraphs được bổ sung cụ thể cho các trường hợp OS/UI không đủ. Hãy nhớ rằng C ngày từ một thời điểm khi giao diện người dùng là một kết nối thiết bị đầu cuối baud 9600 và ASCII là xa phổ quát. – caf

Trả lời

18

Những gì bạn đang nhìn thấy được gọi là một trigraph.

Bằng ngôn ngữ viết bởi người lớn, một dấu hỏi là đủ cho mọi tình huống. Không sử dụng nhiều lần tại một thời điểm và bạn sẽ không bao giờ thấy điều này một lần nữa.

GCC bỏ qua các dấu phẩy theo mặc định vì hầu như không ai sử dụng chúng một cách có chủ ý. Bật chúng với tùy chọn -trigraph hoặc yêu cầu trình biên dịch cảnh báo bạn về tùy chọn -Wtrigraphs.

Visual C++ 2010 cũng tắt theo mặc định và cung cấp /Zc:trigraphs để bật chúng. Tôi không thể tìm thấy bất kỳ điều gì về cách bật hoặc tắt chúng trong các phiên bản trước.

+0

+1, nhưng nó thực sự là một dấu vết http://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C. –

+0

Bạn đã nhận xét nhanh chóng. Tôi đã sửa nó khi tôi nhận thấy có ba nhân vật ở đó. Cảm ơn. –

+8

Có phải sự lăng mạ xúc phạm đến nỗi Marius không phải là một người trưởng thành thực sự cần thiết? Tôi đang nắm giữ phiếu bầu trên giả định nó có nghĩa là hài hước tốt, nhưng nó thực sự khá belittling và hoàn toàn không cần thiết. –

3

Trigraphs là lý do. Cuộc nói chuyện về C trong bài viết cũng áp dụng cho C++

4

Đó là hỗ trợ trigraph. Bạn có thể ngăn chặn việc diễn giải bằng cách thoát khỏi bất kỳ nhân vật nào trong số các ký tự:

char* strange = "(Strange?\?)"; 
6

Cách dễ dàng để tránh trigraph bất ngờ: chia nhỏ "??"Chuỗi chữ trong hai:

char* strange = "(Strange??)"; 
char* strange2 = "(Strange?" "?)"; 
/*       ^^^ no punctuation */ 

Sửa
gcc có một tùy chọn để cảnh báo về trigraphs: -Wtrigraphs (kích hoạt với -Wall cũng)
cuối chỉnh sửa

Quotes từ Standard

 
    5.2.1.1 Trigraph sequences 
1 Before any other processing takes place, each occurrence of one of the 
    following sequences of three characters (called trigraph sequences13)) 
    is replaced with the corresponding single character. 
      ??=  #    ??)  ]    ??!  | 
      ??(  [    ??' ^    ??>  } 
      ??/  \    ??<  {    ??-  ~ 
    No other trigraph sequences exist. Each ? that does not begin one of 
    the trigraphs listed above is not changed. 
 
    5.1.1.2 Translation phases 
1 The precedence among the syntax rules of translation is specified by 
    the following phases. 
     1. Physical source file multibyte characters are mapped, in an 
       implementation-defined manner, to the source character set 
       (introducing new-line characters for end-of-line indicators) 
       if necessary. Trigraph sequences are replaced by corresponding 
       single-character internal representations. 
2

Như đã đề cập nhiều lần, bạn đang bị một con đường bị cắn. Xem câu hỏi SO trước này để biết thêm thông tin:

Bạn có thể khắc phục vấn đề bằng cách sử dụng các '\?' trình tự thoát cho '?' ký tự:

char* strange = "(Strange\?\?)"; 

Thực tế, đây là lý do cho chuỗi thoát đó, có phần bí ẩn nếu bạn không biết về những dấu vết chết tiệt đó.

+0

Cảm ơn bạn đã trả lời ... do tính chất của lỗi này, không thể tìm kiếm câu trả lời trừ khi người ta biết đó là một dấu vết. Vấn đề với việc sửa lỗi theo cách đó là tôi đang sử dụng C được sinh ra từ trình tạo trình phân tích cú pháp lex/yacc. Tôi đã sử dụng và tạo ra trigraphs của riêng tôi trên máy Mac của tôi và tôi cảm thấy đó là nơi của hệ điều hành để xử lý chuỗi bàn phím trigraph và không phải là trình biên dịch. Thực tế chỉ trong VS 2010, họ sẽ thay đổi hành vi mặc định này. – Marius

+0

Có - Tôi có thể tưởng tượng rằng tìm kiếm sự giúp đỡ về điều này mà không biết những gì một trigraph là trình bày một vấn đề gà và trứng nghiêm trọng. Nếu bạn không thể thay đổi đầu ra lex/yacc và phải sử dụng một trình biên dịch sẽ không bỏ qua các dấu vết (VS2010 hoặc GCC), thì tôi nghĩ bạn đang mắc kẹt với việc phải chạy đầu ra lex/tacc thông qua một bộ lọc thay đổi trigraphs thành vô hại không trigraphs. –

+0

Nếu yacc thực sự xuất ra không chính xác C ("không chính xác" vì nó không phân tích cú pháp ngữ pháp được chỉ định nếu ngữ pháp đó chứa các ký tự dấu chấm hỏi liên tiếp), điều đó khá kém. OK, do đó, nó chỉ không chính xác vì một sự không hài lòng của C, nhưng nếu bạn định viết các công cụ tạo mã, tôi nghĩ bạn tự mình xử lý cả hai tính năng và tính thỏa mãn của ngôn ngữ đích của bạn. Nhưng nếu nó chỉ đi sai bởi vì một dấu vết xuất hiện trong một hành động yacc, đó là sai lầm của người dùng để đặt nó ở đó. –

1

Trong khi cố gắng để cross-biên dịch trên GCC nó nhặt chuỗi của tôi lên như một trigraph:

Vì vậy, tất cả những gì cần phải làm bây giờ là tìm ra cách để vô hiệu hóa này trong các dự án theo mặc định kể từ khi tôi chỉ có thể nhìn thấy nó tạo vấn đề cho tôi. (Tôi đang sử dụng bố cục bàn phím Hoa Kỳ)

Hành vi mặc định trên GCC là bỏ qua nhưng đưa ra cảnh báo, điều này là lành mạnh hơn và thực sự là những gì Visual Studio 2010 sẽ áp dụng làm tiêu chuẩn theo như tôi biết .

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