This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

a question for a function use va_list



HI

I want make a function similiar with printf;

code as follows:

#include <stdarg.h>
#include <string.h>
#include <assert.h>

#ifdef _DEBUG
#define ASSERT(_expr)  std::_assert((_expr) != 0,    \
  "ASSERT Failed, (" _STR(_expr) "), File: " __FILE__  \
  ", Line: " _STR(__LINE__) "\n")
#else
#define ASSERT(expr)
#endif/*DEBUG*/


typedef int BOOL;
typedef unsigned short WORD;
typedef unsigned long DWORD;

#define TRUE 1
#define FALSE 0


static const char * const g_pcHex = "0123456789abcdef";

char* StringWrite(char *pBuff,char* pCh,DWORD dwLen)
{
 for(DWORD i=0;i<dwLen;i++) *pBuff++ = *pCh++;
 *pBuff = 0;
 return pBuff;
}

char* IntToASCII(char *pBuff,DWORD dwValue,BOOL bNeg,DWORD dwBase,DWORD dwCount,char cFill)
{
 char pcBuf[16];
 DWORD dwPos = 0;
 DWORD i= 0;
 // Determine the number of digits in the string version of the value.
 for(i=1;(((i*dwBase)<=dwValue) && (((i*dwBase)/dwBase)==i));
 i*=dwBase,dwCount--) {}
 
 // If the value is negative, reduce the count of padding characters needed.
 if(bNeg) dwCount--;
 // If the value is negative and the value is padded with
 // zeros, then place the minus sign before the padding.
 if(bNeg && (cFill=='0'))
 {
  pcBuf[dwPos++] = '-';
  bNeg = FALSE;
 }
 
 // Provide additional padding at the beginning of the string conversion if needed.
 if((dwCount>1) && (dwCount<16))
 {
  for(dwCount--;dwCount;dwCount--) pcBuf[dwPos++] = cFill;
 }
 
 // If the value is negative, then place the minus sign before the number.
 if(bNeg) pcBuf[dwPos++] = '-';
 
 for(;i;i/=dwBase)   // Convert the value into a string.
 {
  pcBuf[dwPos++] = g_pcHex[(dwValue / i) %dwBase];
 }
 return StringWrite(pBuff,pcBuf,dwPos);
}

char* FormatStr(char* pcBuff,char *pcString,...)
{
 DWORD dwIdx,dwValue;
 WORD wBase,wDigits/*指定输出位数*/;
 BOOL bNeg,bDWORD;
 char *pcStr,cFill,*pBuff;
 va_list vaArgP;

 ASSERT(pcBuff!=0);    // Check the arguments.
 ASSERT(pcString!=0);   // Check the arguments.

 va_start(vaArgP, pcString);  // Start the varargs processing.

 pBuff = pcBuff;
 *pBuff = 0;

 while(*pcString)    // Loop while there are more characters in the string.
 {
  // Find the first non-% character, or the end of the string.
  for(dwIdx=0;(pcString[dwIdx]!='%')&&(pcString[dwIdx]!='\0');dwIdx++) {}
  pBuff = StringWrite(pBuff,pcString,dwIdx);
  pcString += dwIdx;     // Skip the portion of the string that was written.
  if(*pcString=='%')     // See if the next character is a %.
  {
   pcString++;      // Skip the %.
   wDigits = 0;
   cFill = ' ';
   while(*pcString>='0' && *pcString<='9')
   {
    if((*pcString=='0') && (wDigits==0)) cFill = '0';
    wDigits *= 10;    // Update the digit count.
    wDigits += *pcString++ - '0';
   }
   if(*pcString=='l')
   {
    bDWORD = TRUE;
    pcString++;
   }
   else bDWORD = FALSE;
   switch(*pcString++)
   {
   case 'c':      // Handle the %c command.
    dwValue = va_arg(vaArgP,char);
    pBuff = StringWrite(pBuff,(char*)&dwValue,1);
    break;
   case 'd':      // Handle the %d command.
    if(bDWORD) dwValue = va_arg(vaArgP,DWORD);
    else dwValue = va_arg(vaArgP,WORD);
    // If the value is negative, make it positive and indicate that a minus sign is needed.
    if((long)dwValue<0)
    {
     dwValue = -(long)dwValue;
     bNeg = TRUE;
    }
    else bNeg = FALSE;
    wBase = 10;    // Set the base to 10.
    pBuff = IntToASCII(pBuff,dwValue,bNeg,wBase,wDigits,cFill);
    break;
   case 's':      // Handle the %s command.
    pcStr = va_arg(vaArgP, char*);
    // Determine the length of the string.
    for(dwIdx=0;pcStr[dwIdx]!='\0';dwIdx++) {}
    pBuff = StringWrite(pBuff,pcStr,dwIdx);
    // Write any required padding spaces
    if(wDigits>dwIdx)
    {
     wDigits -= (WORD)dwIdx;
     while(wDigits--) pBuff = StringWrite(pBuff," ", 1);
    }
    break;
   case 'u':    // Handle the %u command.
    if(bDWORD) dwValue = va_arg(vaArgP,DWORD);
    else dwValue = va_arg(vaArgP,WORD);
    wBase = 10;  // Set the base to 10.
    // Indicate that the value is positive so that a minus sign
    // isn't inserted.
    bNeg = FALSE;
    pBuff = IntToASCII(pBuff,dwValue,bNeg,wBase,wDigits,cFill);
    break;
   // Handle the %x and %X commands.  Note that they are treated
   // identically; i.e. %X will use lower case letters for a-f
   // instead of the upper case letters is should use.  We also
   // alias %p to %x.
   case 'x':
   case 'X':
    if(bDWORD) dwValue = va_arg(vaArgP,DWORD);
    else dwValue = va_arg(vaArgP,WORD);
    wBase = 16;  // Set the base to 10.
    // Indicate that the value is positive so that a minus sign
    // isn't inserted.
    bNeg = FALSE;
    pBuff = IntToASCII(pBuff,dwValue,bNeg,wBase,wDigits,cFill);
    break;
   case 'p':
    dwValue = (DWORD)va_arg(vaArgP,DWORD);
    wBase = 16;  // Set the base to 10.
    // Indicate that the value is positive so that a minus sign
    // isn't inserted.
    bNeg = FALSE;
    pBuff = IntToASCII(pBuff,dwValue,bNeg,wBase,wDigits,cFill);
    break;
   case '%':    // Handle the %% command.
    pBuff = StringWrite(pBuff,pcString-1,1);  // Simply write a single %.
    break;
   default:
    pBuff = StringWrite(pBuff,"ERROR",5);
     break;
   }
  }
 }
 // End the varargs processing.
 va_end(vaArgP);

 return NULL;
}

Test code as follows:

char g_cString[500];
long* pP;

int main()
{
 long i = 100;
 pP = &i;
 long* pb = &i;
 FormatStr(g_cString,"jimmy is %ld",i);
}

The function seems running in right way, but all addrs of the the Temporary variables  in function main changed.

why it happened? where is the problem?

thanks

jimmy