vsnprintf字符串格式化输出实例:日志中打印程序名和行号

vsnprintf字符串格式化输出实例:日志中打印程序名和行号

在Linux C/C++程序中打印日志时,可能会由于需要打印未知个数的变量参数,那么vsnprintf函数就排上用场了。这里使用一个简单的C程序例子,演示在打印源程序文件名和该打印函数所在的行号的同时,使用vsnprintf函数打印个数未知的参数变量。

1 完整程序

代码比较简单,如果需要把内容打印在日志文件中的话,还需要调用文件处理函数。为了便于理解,这里直接把内容输出到控制台上了。需要说明的三个地方:

1

2

3静态全局变量 c_FileName 和 i_FileLineNum 分别用于存储源程序文件名和打印函数所在的行号;

自定义标识符 PRINT 先调用源程序文件名和行号的赋值函数 Get_File_Line ,然后调用个数未知的参数的处理函数 F_vsnprintf;

类似于sprintf和snprintf这两个函数,相比vsprintf函数,vsnprintf加了最大字节( MAXBYTES )的限制,防止内存溢出。

具体代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59/**

* @FileName vsnprintf_name_line.c

* @Describe A simple example for using vsnprintf to print the name and line-num of source file in linux.

* @Author vfhky 2016-03-13 23:28 https://typecodes.com/cseries/vsnprintffilenameline.html

* @Compile gcc vsnprintf_name_line.c -o vsnprintf_name_line

*/

#include

#include

#include

#define FILENAME_LEN 100

#define MAXLINE 1024

#define MAXBYTES 50

static char c_FileName[FILENAME_LEN];

static int i_FileLineNum;

//Self-define a function which can print the name and line-number of the source file calling it.

#define PRINT Get_File_Line( __FILE__, __LINE__ );\

F_vsnprintf

/**

* Get the linenum and filename of the source file.

* @Para-in: p_FileName: The name of the source file.

* @Para-in: i_FileLine: The line-number of the source file.

*/

void Get_File_Line( char *p_FileName, int i_FileLine )

{

strcpy( c_FileName, p_FileName );

i_FileLineNum = i_FileLine;

return;

}

/**

* Print the arguments according to the first argument, name as fmt.

*/

void F_vsnprintf( char *fmt, ... )

{

char buf[MAXLINE] = {0x00};

snprintf( buf, MAXBYTES, "[%s:%d] ", c_FileName, i_FileLineNum );

va_list ap;

va_start( ap, fmt );

vsnprintf( buf+strlen(buf), MAXLINE, fmt, ap );

va_end( ap );

strcat( buf, "\n" );

fflush( stdout );

fputs( buf, stderr );

fflush( NULL );

return;

}

int main( int argc, char **argv )

{

PRINT( "[%s]", "Hello." );

PRINT( "[%s %s]", "Hello", "world." );

return 0;

}

2 编译执行

使用《Linux C/C++工程中可生成ELF、动/静态库文件的通用Makefile》一文中的Makefile文件进行程序编译(当然也可以使用命令进行编译gcc vsnprintf_name_line.c -o vsnprintf_name_line),接着执行该程序,得到如下图所示的结果:

相关推荐

上海一加店铺有哪些(上海一加官方店在哪里)
bet体育365官网正规平台

上海一加店铺有哪些(上海一加官方店在哪里)

📅 08-26 👁️ 9277
上帝之手 (1986年)
bet体育365官网正规平台

上帝之手 (1986年)

📅 08-16 👁️ 6303
铁路12306怎么开通会员 铁路12306开通会员方法【详细步骤】
bet体育365官网正规平台

铁路12306怎么开通会员 铁路12306开通会员方法【详细步骤】

📅 07-14 👁️ 8350
NAT0至NAT4详解:不同类型网络地址转换的特点、优势、劣势及应用场景全解析
柠檬可以放多久?如何保存并制作美味佳肴
365平台是做什么的

柠檬可以放多久?如何保存并制作美味佳肴

📅 09-01 👁️ 2994
哪个国家的域名是.tv
365平台是做什么的

哪个国家的域名是.tv

📅 09-20 👁️ 4024