我试图创建一个格式化的打印功能并面对这个我不知道其原因的问题
使用 va_list 的强大功能,我创建了一个函数 pf() 在这个函数里面有一个 for 循环,用于在输入 for 循环之后导航越过字符串 _Str ' sa while 测试(*转化)和'%' 打印字符,直到遇到第一个&#39 ;%' ,在那里' 开关来处理参数
#include "base.h"
void pf(char* _Str, ...)
{
char* conversion;
//
u_int i;
char* S;
//Initializing arguments
//
va_list arg;
va_start(arg, _Str);
for(conversion = _Str; *conversion != '\0'; conversion++)
{
while( *conversion != '%' )
{
putchar(*conversion);
conversion++;
}//end while
conversion++;
//arguments
//
switch(*conversion)
{
case 'c' : i = va_arg(arg, int); //char argument
putchar(i);
break;
case 'd' : i = va_arg(arg, int); //Decimal/Integer argument
if(i < 0) { i = -i; putchar('-');}
puts(convert(i, 10));
break;
case 'o': i = va_arg(arg,u_int); //Octal representation
puts(convert(i, 8));
break;
case 's': S = va_arg(arg, char *); //string argument
puts(S);
break;
case 'x': i = va_arg(arg, u_int); //Hexadecimal representation
puts(convert(i, 16));
break;
}//end switch
}//end for
//
//
va_end(arg);
}// end pf()
int main(int argc, char** argv)
{
pf("test1\vtest2 %d %o %x %c%c",10,512,1024,'O','K');
return 0;
}
#ifndef BASE_H_
#define BASE_H_
#ifndef EOF // (EOF) - End Of File character. (-1)
#define EOF (-1)
#endif// EOF
#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
typedef unsigned int u_int;
void pf(char*, ...); // Our printf function
char* convert(u_int, int); // Convert integer number into octal, hex, etc.
#endif // BASE_H_
为 pf 提供参数时。上面的代码可以正常工作并且符合预期
使用参数
编译
[ar.lnx@host printf] $ make
Building objects..
gcc -c -o main.o main.c -I. -Wall
Building the application core..
gcc -o x main.o -I. -g
Finish.
[ar.lnx@host printf] $ ./x
test1
test2 10
1000
400
OK[ar.lnx@host printf]
但是当不对 pf 提出任何论据时,它会显示出意想不到的结果! 例如尝试测试
pf("test3\vtest4");
不使用参数(意外结果)
编译
[ar.lnx@host printf] $ make
Building objects..
gcc -c -o main.o main.c -I. -Wall
Building the application core..
gcc -o x main.o base.o -I. -g
Finish.
[ar.lnx@host printf] $ ./x
test3
test4 �@�@@@@@@@@@@@\@@@@�@@@@@���������h�����
��������X��� ����@ ����zRx
����*zRx
$���PF▒J
�?▒;*3$"D���
[ar.lnx@host printf] $
我不知道该程序是如何显示这些结果的,有人帮我理解了
答案 0 :(得分:3)
您的内部while
循环未检查空终止符,因此它可以循环遍历_Str
的末尾到周围的内存中。如果_Str
的末尾不存在格式说明符,则代码将失败(在您的示例中,您的失败字符串中根本没有任何%
个字符)。所以while
循环不会中断,除非发生在字符串之外的内存中遇到%
。在那之前,它只是打印出周围内存的字节,这是你在输出中看到的。
请改为尝试:
void pf(char* _Str, ...)
{
char* conversion;
//
int i;
u_int ui;
char* S;
//Initializing arguments
//
va_list arg;
va_start(arg, _Str);
for(conversion = _Str; *conversion != '\0'; conversion++)
{
while( (*conversion != '%') && (*conversion != '\0') )
{
putchar(*conversion);
conversion++;
}//end while
if (*conversion == '\0')
break;
conversion++; // skip '%'
//arguments
//
switch (*conversion)
{
case 'c' : i = va_arg(arg, int); //char argument
putchar(i);
break;
case 'd' : i = va_arg(arg, int); //Decimal/Integer argument
if (i < 0) { i = -i; putchar('-');}
puts(convert(i, 10));
break;
case 'o': ui = va_arg(arg, u_int); //Octal representation
puts(convert(ui, 8));
break;
case 's': S = va_arg(arg, char *); //string argument
puts(S);
break;
case 'x': ui = va_arg(arg, u_int); //Hexadecimal representation
puts(convert(ui, 16));
break;
case '%': putchar('%'); //percent literal
break;
default : putchar('%'); // anything else
putchar(*conversion);
break;
}//end switch
}//end for
va_end(arg);
}// end pf()
话虽如此,在此示例中无需手动实现格式化输出(特别是因为您没有实现格式化支持的所有选项)。你应该使用vprintf()
,让它为你付出艰苦的努力,例如:
void pf(char* _Str, ...)
{
va_list arg;
va_start(arg, _Str);
vprintf(_Str, arg);
va_end(arg);
}