Nếu bạn có mã log_out()
, hãy viết lại nó. Rất có thể, bạn có thể làm:
static FILE *logfp = ...;
void log_out(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(logfp, fmt, args);
va_end(args);
}
Nếu cần thêm thông tin ghi nhật ký, thông tin đó có thể được in trước hoặc sau khi thông báo hiển thị. Điều này giúp tiết kiệm phân bổ bộ nhớ và kích thước bộ đệm không rõ ràng, v.v. Bạn có thể cần khởi tạo logfp
bằng 0 (con trỏ null) và kiểm tra xem nó có phải là null hay không và mở tệp nhật ký nếu thích hợp - nhưng mã trong hiện tại vẫn log_out()
phải xử lý điều đó.
Ưu điểm của giải pháp này là bạn có thể đơn giản gọi nó như thể nó là một biến thể của printf()
; thực sự, nó là một biến thể nhỏ trên printf()
.
Nếu bạn không có mã log_out()
, hãy xem xét liệu bạn có thể thay thế nó bằng một biến thể chẳng hạn như biến thể được nêu ở trên hay không. Việc bạn có thể sử dụng cùng một tên hay không sẽ phụ thuộc vào khung ứng dụng của bạn và nguồn cuối cùng của log_out()
hàm hiện tại . Nếu nó nằm trong cùng một tệp đối tượng với một hàm không thể thiếu khác, bạn sẽ phải sử dụng một tên mới. Nếu bạn không thể tìm ra cách sao chép chính xác, bạn sẽ phải sử dụng một số biến thể giống như những biến thể được đưa ra trong các câu trả lời khác để phân bổ một lượng bộ nhớ thích hợp.
void log_out_wrapper(const char *fmt, ...)
{
va_list args;
size_t len;
char *space;
va_start(args, fmt);
len = vsnprintf(0, 0, fmt, args);
va_end(args);
if ((space = malloc(len + 1)) != 0)
{
va_start(args, fmt);
vsnprintf(space, len+1, fmt, args);
va_end(args);
log_out(space);
free(space);
}
/* else - what to do if memory allocation fails? */
}
Rõ ràng, bây giờ bạn gọi log_out_wrapper()
thay vì log_out()
- nhưng việc phân bổ bộ nhớ, v.v. được thực hiện một lần. Tôi bảo lưu quyền được phân bổ quá mức không gian bởi một byte không cần thiết - Tôi đã không kiểm tra lại xem độ dài được trả về vsnprintf()
có bao gồm giá trị null kết thúc hay không.