2012-11-21 23 views
5

Tôi muốn tạo ra một chuỗi tĩnh của hình thức "example.cpp:34" với tiền xử lý, nhưng __FILE__ vĩ mô sẽ mở rộng để "lib/example/example.cpp"__LINE__ mở rộng để 34 là một số nguyên. Tôi có thể xây dựng chuỗi mong muốn bằng bộ tiền xử lý không? GCC là ok.Cpp Preprocessor và basename của tên tập tin, số dòng như chuỗi

Chỉnh sửa Phần quan trọng nhất ở đây là tôi muốn có một chuỗi kiểu C tĩnh, vì vậy tôi không thể sử dụng chức năng basename. Tôi đang tự hỏi nếu có một số cách trong preprocessor để nhân rộng chức năng đó, có thể với một phần mở rộng tăng?

+0

là C++ 11 ok? Phải chuỗi có thể sử dụng trong bộ tiền xử lý, hoặc chỉ trong thời gian biên dịch? – kennytm

+0

@KennyTM Không, tôi không thể sử dụng C++ 11. Tôi muốn nó ở thời gian biên dịch. Boost cũng tốt. –

+0

Hoặc không sử dụng '__FILE__', nhưng xác định chuỗi ký tự của riêng bạn ở đầu mỗi tệp quan tâm. – chill

Trả lời

0

Bạn sẽ có thể chỉ cần sử dụng basename() như __FILE__ mở rộng sang const C chuỗi

__FILE__ Macro này mở rộng đến tên của tập tin đầu vào hiện tại, dưới hình thức của một chuỗi C liên tục .

printf ("%s:%d\n", basename(__FILE__), __LINE__); 
+0

Tôi muốn có một chuỗi tĩnh, vì vậy nó không thể là đầu ra của một hàm. –

+0

@pythonicmetaphor ý của bạn là đầu ra của một hàm? bạn muốn trả lại từ một hàm? – iabdalkader

+0

Tôi có nghĩa là tôi muốn có một chuỗi tĩnh, vì vậy tôi không thể sử dụng bất kỳ chức năng nào, chỉ có bộ tiền xử lý để xây dựng nó. –

2

Bạn có thể tận dụng thực tế là xâu liền kề được nối:

#define STRINGIFY(s) #s 
#define FILELINE(line) __FILE__ ":" str(line) 

Sau đó, sử dụng nó như FILELINE(__LINE__). Tôi không làm điều này rất thường xuyên vì vậy có thể có một cách tốt hơn là phải vượt qua vĩ mô __LINE__. Nó làm việc cho tôi dù sao, thử nghiệm với:

#include <iostream> 

#define str(s) #s 
#define FILELINE(line) __FILE__ ":" str(line) 

int main(int argc, const char* argv[]) 
{ 
    std::cout << FILELINE(__LINE__) << std::endl; 
    return 0; 
} 

tôi nhận được:

main.cpp:9 
+0

Chắc chắn, vì vậy tôi đoán vấn đề thực sự là tên nền tảng. Bạn nhận main.cpp vì bạn không bao gồm một tệp trong một thư mục khác. –

0

Tôi không biết một cách để có được những basename, nhưng oyther hơn mà bạn có thể sử dụng các nhà điều hành tiền xử lý stringification '#', như:

#define M__(x,y) x ":" #y 
#define M_(x,y) M__(x, y) 
#define M M_(__FILE__, __LINE__) 

Bây giờ M sẽ mở rộng để "lib/example/example.cpp:34" (đưa cho bạn đặt nó trong tập tin đó trên dòng đó, OFC :))

0

Vâng, không chỉ bộ tiền xử lý phải được sử dụng - nhưng nó sẽ không được nhìn thấy đối với người dùng cuối.

Khi bạn muốn BASENAME() được sử dụng trong một số tập tin - sử dụng tập tin tiêu đề này basename.h:

// basename.h 
#include <string.h> 

static size_t basename_start_calc(const char* filename) 
{ 
    const char* base = strrchr(filename, '/'); 
    return base ? (base - filename + 1) : 0; 
} 
static inline size_t basename_start(const char* filename) 
{ 
    static size_t retval = basename_start_calc(filename); 
    return retval; 
} 
#define STR_(t) #t 
#define STR(t) STR_(t) 
#define BASENAME() ((__FILE__ ":" STR(__LINE__)) + basename_start(__FILE__)) 

Một ideone example here.

basename_start(__FILE__) sẽ chỉ được đánh giá một lần cho tệp nguồn đã cho. Rất tiếc, bạn không thể sử dụng giải pháp này trong các tệp tiêu đề - chỉ trong các tệp nguồn. Bạn có thể thay đổi nó, vì vậy nó có thể được sử dụng ở khắp mọi nơi - nhưng sau đó bắt đầu đường cơ sở cho tên tập tin đã cho sẽ được tính toán mỗi lần. Chỉ cần sử dụng trong BASENAME()basename_start_calc(__FILE__) thay vì basename_start(__FILE__) ...

Tôi tin rằng điều này là tốt nhất bạn có thể tự động.

Tất nhiên bạn có thể xác định bằng tay trong mỗi vĩ mô file:

#define BASENAME() ("somefile.cpp:" STR(__LINE__)) 

nhưng tôi không chắc chắn đây là những gì bạn muốn ....

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