对C/C++可变参数表的深层探索2

来源:互联网 发布:网易房地产交易数据 编辑:程序博客网 时间:2024/05/14 14:15
高级应用

  下面这个程序是我们为某嵌入式系统(该系统中CPU的字长为16位)编写的在屏幕上显示格式字符串的函数DrawText,它的用法类似于int printf ( const char *format, ... )函数,但其输出的目标为嵌入式系统的液晶显示屏幕(LED)。

///////////////////////////////////////////////////////////////////////////////
// 函数名称: DrawText
// 功能说明: 在显示屏上绘制文字
// 参数说明: xPos ---横坐标的位置 [0 .. 30]
// yPos ---纵坐标的位置 [0 .. 64]
// ... 可以同数字一起显示,需设置标志(%d、%l、%x、%s)
///////////////////////////////////////////////////////////////////////////////
extern void DrawText ( BYTE xPos, BYTE yPos, LPBYTE lpStr, ... )
{
 BYTE lpData[100]; //缓冲区
 BYTE byIndex;
 BYTE byLen;
 DWORD dwTemp;
 WORD wTemp;
 int i;
 va_list lpParam;

 memset( lpData, 0, 100);
 byLen = strlen( lpStr );
 byIndex = 0;
 va_start ( lpParam, lpStr );

 for ( i = 0; i < byLen; i++ )
 {
  if( lpStr[i] != ’%’ ) //不是格式符开始
  {
   lpData[byIndex++] = lpStr[i];
  }
  else
  {
   switch (lpStr[i+1])
   {
    //整型
    case ’d’:
    case ’D’:
     wTemp = va_arg ( lpParam, int );
     byIndex += IntToStr( lpData+byIndex, (DWORD)wTemp );
     i++;
     break;
     //长整型
    case ’l’:
    case ’L’:
     dwTemp = va_arg ( lpParam, long );
     byIndex += IntToStr ( lpData+byIndex, (DWORD)dwTemp );
     i++;
     break;
     //16进制(长整型)
    case ’x’:
    case ’X’:
     dwTemp = va_arg ( lpParam, long );
     byIndex += HexToStr ( lpData+byIndex, (DWORD)dwTemp );
     i++;
     break;
    default:
     lpData[byIndex++] = lpStr[i];
     break;
   }
  }
 }
 va_end ( lpParam );
 lpData[byIndex] = ’/0’;
 DisplayString ( xPos, yPos, lpData, TRUE); //在屏幕上显示字符串lpData
}
  在这个函数中,需通过对传入的格式字符串(首地址为lpStr)进行识别来获知可变参数个数及各个可变参数的类型,具体实现体现在for循环中。譬如,在识别为%d后,做的是va_arg ( lpParam, int ),而获知为%l和%x后则进行的是va_arg ( lpParam, long )。格式字符串识别完成后,可变参数也就处理完了。

  在项目的最初,我们一直苦于不能找到一个好的办法来混合输出字符串和数字,我们采用了分别显示数字和字符串的方法,并分别指定坐标,程序条理被破坏。而且,在混合显示的时候,要给各类数据分别人工计算坐标,我们感觉头疼不已。以前的函数为:

//显示字符串
showString ( BYTE xPos, BYTE yPos, LPBYTE lpStr )
//显示数字
showNum ( BYTE xPos, BYTE yPos, int num )
//以16进制方式显示数字
showHexNum ( BYTE xPos, BYTE yPos, int num )
  最终,我们用DrawText ( BYTE xPos, BYTE yPos, LPBYTE lpStr, ... )函数代替了原先所有的输出函数,程序得到了简化。就这样,兄弟们用得爽翻了。