2009-02-13 44 views
11
sscanf(input_str, "%5s", buf); //reads at max 5 characters from input_str to buf 

Nhưng tôi cần phải sử dụng một cái gì đó như% MACRO_SIZEs thay vì% 5sLàm thế nào để vượt qua độ dài biến chiều dài specifier trong sscanf?

Một giải pháp tầm thường là để tạo ra một chuỗi định dạng cho cùng

char fmt_str[100] = "";  
snprintf(fmt_str, 100, "%%%ds", MACRO_SIZE); 
sscanf(input_str, fmt_str, buf); 

Có cách nào tốt hơn để đạt được cùng ?

Trả lời

8

nếu MACRO_SIZE của bạn là const tại thời gian biên dịch, bạn có thể thử này:

#define MACRO_SIZE "5" 
snprintf(fmt_str, 100, "%" MACRO_SIZE "s", buf); 
+0

Ràng buộc không quá nhiều mà MACRO_SIZE đánh giá dưới dạng hằng số, nhưng định nghĩa của nó là một chữ đơn giản, đúng không? Ví dụ, định nghĩa (5 * 25 + 3) (đánh giá hằng số tại thời gian biên dịch) dẫn đến 'snprintf (fmt_str, 100,"% "(5 * 25 + 3)" s ", buf);' – jhfrontz

9

Giống như Stefan nói, nhưng đối với sscanf() để trả lời đúng nhiều câu hỏi, và với thủ đoạn gian trá vĩ mô hơn một chút:

#define MACRO_SIZE 5 

#define FORMAT(S) "%" #S "s" 
#define RESOLVE(S) FORMAT(S) 

char buf[MACRO_SIZE + 1]; 
sscanf(input_str, RESOLVE(MACRO_SIZE), buf); 

Điều này sử dụng sự tham gia tự động của C cùng với các chuỗi ký tự chuỗi liền kề, để tạo thành chuỗi định dạng bắt buộc tại thời gian biên dịch. Điều này chỉ hoạt động nếu MACRO_SIZE là một macro tiền xử lý, không phải nếu đó là biến thời gian chạy bình thường.

Cuộc gọi macro thêm thông qua RESOLVE() là cần thiết vì nếu không, đối số sẽ không được giải quyết thành giá trị #define d và chúng tôi sẽ kết thúc bằng một chuỗi định dạng "%MACRO_SIZEs", đó không phải là điều chúng tôi muốn.

+0

Bạn có mong đợi điều này sẽ hoạt động nếu 'MACRO_SIZE' là một biểu thức (ví dụ' (4 + 1) 'hoặc tham chiếu đến một macro khác (ví dụ' #define MACRO_SIZE (OTHER_MACRO - 1) ')? Khi tôi thử nó, với' gcc -E' để xem đầu ra hậu xử lý trước, nó không mở rộng đến giá trị cuối cùng – meowsqueak

+0

@meowsqueak Không, tất nhiên không phải vì nó dựa vào các chuỗi ký tự chuỗi liền kề được coi là chuỗi đơn. 'MACRO_SIZE' phải là một số. – unwind

1

Giải pháp "đúng" là những gì bạn gọi là giải pháp nhỏ. Tất cả các macro thông minh (tôi sẽ sử dụng m4 bản thân mình) chỉ là sẽ làm cho mã của bạn ít quản lý sau đó nếu bạn chỉ còn lại nó như là một hằng số.

Vấn đề bạn có ở đây là chuỗi không phải là cấu trúc dữ liệu lớp đầu tiên trong C. Chúng là một mảng byte. Do đó bạn phải xây dựng mảng mà bạn muốn có được ý nghĩa mà bạn muốn, và bạn xây dựng mảng đó với sprintf. Nó không đẹp, nhưng nó đúng.

Nếu bạn gặp sự cố về hiệu suất và bạn đã theo dõi nó xuống đây thì có, hãy loại bỏ các cuộc gọi chức năng. Nhưng trừ khi giá trị cho MACRO_SIZE được lặp lại một trăm lần hoặc trải ra trên nhiều tệp, tôi chỉ thay đổi chữ. Một macro chỉ là giả mạo có tính linh hoạt hơn, sử dụng sprintf thực sự mang đến cho bạn sự linh hoạt.

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