利用va_list,vfprintf等定义自己的文件输出函数

最近在做项目的时候,经常需要打印日志文件,其实这是最好的调试方式之一,能很好的解释和检验我们的逻辑思维是否正确。为了以后能方便自己在项目中使用打印日志的函数模块,同时也方便大家理解,特意写出比较简单的打印日志的函数(在实际的项目中可以根据自己的需要任意修改),供大家参考,和大家一起进步。

在函数模块中主要用到的知识点是VA_LIST ,VA_LIST 是在C语言中解决变参问题的一组宏,在<stdarg.h>头文件下。VA_LIST的用法:      
      (1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针
      (2)然后用VA_START宏初始化变量刚定义的VA_LIST变量,这个宏的第二个参数是第一个可变参数的前一个参数,是一个固定的参数。
      (3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型。
      (4)最后用VA_END宏结束可变参数的获取。然后你就可以在函数里使用第二个参数了。如果函数有多个可变参数的,依次调用VA_ARG获取各个参数。

同时还用到文件打印输出函数vfprintf,当然,事先应该对文件的操作有一定的理解,不理解的童鞋最好还是看下msdn这个可是好东西,在windows下编程,真的离不开这个东东。

函数主要实现的功能,是一定的字符串打印输出到文件当中,编译环境是vs2010,具体的代码如下:

// printf_t.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdarg.h"
#include "stdio.h"
#include "stdlib.h"

char buffer[256];
void printf_t(FILE *m_file,const char *fmt ...)
{
	va_list vp;
	va_start(vp,fmt);
	//vsprintf(buffer,fmt,vp);
	vfprintf(m_file,fmt,vp);
	va_end(vp);
	fflush(m_file);
}

int _tmain(int argc, _TCHAR* argv[])
{
	int a = 10;
	char *b = "F:\\rer\\print_t.ceshi";
	FILE *m_filel;
	m_filel = fopen("F:\\rer\\print_t.ceshi","a+");
	//printf_t("%d%s\n",a,b);
	//printf("%s",buffer);
	printf_t(m_filel,"wenjiande weizhi is%d %s\n",a,b);
	fclose( m_filel );
	return 0;
}

在代码中主要利用fopen打开f盘下的文件,当然,"a+"的标志说明如果文件不存在可以自己创建问价,将a,b字符串打印到指定的文件中,最后将文件句柄关闭。代码实现的方式比较简单,条理比较清晰,在指定的盘符下将会看到指定的文件。

今天立冬了吐舌头,天气真的有点冷了,祝愿大家每一天能进步一点,每一天能快快乐乐,一天比一天幸福。转载的话请注明出处哟!!!




  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
__vfprintf_internal 是一个内部函数,用于实现 printf 和 fprintf函数的底层输出功能。以下是 __vfprintf_internal 函数的源代码: ```c int __vfprintf_internal(FILE *stream, const char *format, va_list ap, int *writelen) { int ret; unsigned int len; unsigned char flags = 0; unsigned char prec = 0; unsigned char width = 0; unsigned char type = 0; unsigned char sign = 0; unsigned char prefix = 0; unsigned char base = 0; unsigned char *p; int n; int count = 0; char buf[BUF_SIZE]; char *s; unsigned long long value; const char *digits; const char *prefix_str; char pad_char = ' '; char prefix_char = '\0'; /* ... */ /* 根据格式字符串逐个处理输出 */ for (p = (unsigned char *)format; *p; p++) { /* 处理格式控制指示符 */ if (*p == '%') { flags = 0; prec = 0; width = 0; type = 0; sign = 0; prefix = 0; base = 10; prefix_str = ""; pad_char = ' '; prefix_char = '\0'; /* 处理标志位 */ p++; while (*p == '-' || *p == '+' || *p == ' ' || *p == '#' || *p == '0') { switch (*p) { case '-': flags |= LEFT_ADJUSTMENT; break; case '+': flags |= PLUS_SIGN; break; case ' ': flags |= SPACE; break; case '#': flags |= ALTERNATE_FORM; break; case '0': flags |= ZERO_PAD; break; } p++; } /* 处理字段宽度 */ if (*p >= '0' && *p <= '9') { while (*p >= '0' && *p <= '9') { width = width * 10 + (*p - '0'); p++; } } else if (*p == '*') { width = va_arg(ap, int); if (width < 0) { width = -width; flags |= LEFT_ADJUSTMENT; } p++; } /* 处理精度 */ if (*p == '.') { p++; prec = 0; if (*p >= '0' && *p <= '9') { while (*p >= '0' && *p <= '9') { prec = prec * 10 + (*p - '0'); p++; } } else if (*p == '*') { prec = va_arg(ap, int); p++; } flags |= PRECISION; } /* 处理长度修饰符 */ switch (*p) { case 'h': if (*(p + 1) == 'h') { p++; flags |= CHAR_SHORT; } else { flags |= SHORT; } p++; break; case 'l': if (*(p + 1) == 'l') { p++; flags |= LLONG; } else { flags |= LONG; } p++; break; case 'j': flags |= INTMAX_T; p++; break; case 'z': flags |= SIZE_T; p++; break; case 't': flags |= PTRDIFF_T; p++; break; case 'L': flags |= LONG_DOUBLE; p++; break; default: break; } /* 处理转换类型 */ type = *p; switch (type) { case 'd': case 'i': if (flags & LLONG) { value = va_arg(ap, long long); } else if (flags & LONG) { value = va_arg(ap, long); } else if (flags & SHORT) { value = (short)va_arg(ap, int); } else if (flags & CHAR_SHORT) { value = (signed char)va_arg(ap, int); } else { value = va_arg(ap, int); } if (value < 0) { sign = '-'; value = -value; } else if (flags & PLUS_SIGN) { sign = '+'; } else if (flags & SPACE) { sign = ' '; } base = 10; digits = "0123456789"; break; case 'o': if (flags & LLONG) { value = va_arg(ap, unsigned long long); } else if (flags & LONG) { value = va_arg(ap, unsigned long); } else if (flags & SHORT) { value = (unsigned short)va_arg(ap, unsigned int); } else if (flags & CHAR_SHORT) { value = (unsigned char)va_arg(ap, unsigned int); } else { value = va_arg(ap, unsigned int); } base = 8; digits = "01234567"; if (flags & ALTERNATE_FORM && value != 0) { prefix_str = "0"; prefix_char = '0'; prefix = 1; } break; case 'u': if (flags & LLONG) { value = va_arg(ap, unsigned long long); } else if (flags & LONG) { value = va_arg(ap, unsigned long); } else if (flags & SHORT) { value = (unsigned short)va_arg(ap, unsigned int); } else if (flags & CHAR_SHORT) { value = (unsigned char)va_arg(ap, unsigned int); } else { value = va_arg(ap, unsigned int); } base = 10; digits = "0123456789"; break; case 'x': case 'X': if (flags & LLONG) { value = va_arg(ap, unsigned long long); } else if (flags & LONG) { value = va_arg(ap, unsigned long); } else if (flags & SHORT) { value = (unsigned short)va_arg(ap, unsigned int); } else if (flags & CHAR_SHORT) { value = (unsigned char)va_arg(ap, unsigned int); } else { value = va_arg(ap, unsigned int); } base = 16; digits = (type == 'X') ? "0123456789ABCDEF" : "0123456789abcdef"; if (flags & ALTERNATE_FORM && value != 0) { prefix_str = (type == 'X') ? "0X" : "0x"; prefix_char = (type == 'X') ? 'X' : 'x'; prefix = 2; } break; case 'p': value = (uintptr_t)va_arg(ap, void *); base = 16; digits = "0123456789abcdef"; prefix_str = "0x"; prefix_char = 'x'; prefix = 2; break; case 'c': n = va_arg(ap, int); buf[0] = n; s = buf; len = 1; break; case 's': s = va_arg(ap, char *); if (s == NULL) { s = "(null)"; } len = strlen(s); if (flags & PRECISION && len > prec) { len = prec; } break; case '%': buf[0] = '%'; s = buf; len = 1; break; default: buf[0] = '%'; buf[1] = type; s = buf; len = 2; break; } /* 计算输出长度 */ if (type == 's') { count += len; } else { if (value == 0 && (flags & PRECISION) && prec == 0) { len = 0; } else { len = calc_digits(value, base); } if (sign || prefix) { len++; } count += (len < width) ? width : len; } /* 输出前导空格或零 */ if (!(flags & LEFT_ADJUSTMENT)) { if (flags & ZERO_PAD) { pad_char = '0'; } while (count < width) { fputc(pad_char, stream); count++; } } /* 输出符号或前缀 */ if (sign) { fputc(sign, stream); count++; } else if (prefix) { fputs(prefix_str, stream); count += prefix; } /* 输出数字或字符串 */ if (type == 's') { fwrite(s, len, 1, stream); } else { output_number(value, base, digits, prefix_char, stream, len); } /* 输出后缀空格 */ if (flags & LEFT_ADJUSTMENT) { while (count < width) { fputc(' ', stream); count++; } } } else { /* 处理普通字符 */ fputc(*p, stream); count++; } } /* 返回输出字符数 */ if (writelen) { *writelen = count; } ret = ferror(stream) ? EOF : count; return ret; } ``` 该函数首先解析格式字符串,然后根据格式字符串逐个处理输出。具体而言,它会根据格式字符串中的格式控制指示符,处理标志位、字段宽度、精度、长度修饰符和转换类型等信息,并据此输出相应的内容。输出时会考虑前导空格、符号或前缀、数字或字符串以及后缀空格等因素。最后,该函数会返回输出字符数,并将其写入指针 `writelen` 所指向的变量中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值