CAD專案相關知識集合

raindayinrain發表於2018-01-20

1.va_arg, va_copy, va_end, va_start

// returns the current argument
type va_arg(
   // Pointer to the list of arguments
   va_list arg_ptr,
   // Type of argument to be retrieved
   type 
);

void va_copy(
   // Pointer to the list of arguments to be initialized from src
   va_list dest,
   // Pointer to the initialized list of arguments to copy to dest
   va_list src
); // (ISO C99 and later)

void va_end(
   va_list arg_ptr 
);

void va_start(
   va_list arg_ptr,
   // Parameter that precedes the first optional argument.
   prev_param 
); // (ANSI C89 and later)

void va_start(
   arg_ptr 
);  // (Pre-ANSI C89 standardization version)

va_start/va_copy初始化va_list 物件
va_arg遍歷處理va_list 物件
va_end重置va_list 物件

#include <stdio.h>
#include <stdarg.h>

void testit (int i, ...)
{
    va_list argptr;
    va_start(argptr, i);

    if (i == 0)
    {
        int n = va_arg(argptr, int);
        printf("%d\n", n);
    }
    else
    {
        char *s = va_arg(argptr, char*);
        printf("%s\n", s);
    }
}

int main()
{
    testit(0, 0xFFFFFFFF); // 1st problem: 0xffffffff is not an int
    testit(1, NULL);       // 2nd problem: NULL is not a char*
}

When the program is compiled for native code, it produces this output:
-1
(null)
However, when the program is compiled by using /clr:pure,
the type mismatches cause it to generate an exception.
The solution is to use explicit casts:

int main()
{
   testit( 0, (int)0xFFFFFFFF ); // cast unsigned to int
   testit( 1, (char*)NULL );     // cast int to char*
}
/* Compile with: cl /W3 /Tc crt_va.c
 * The program below illustrates passing a variable
 * number of arguments using the following macros:
 *      va_start            va_arg              va_copy
 *      va_end              va_list
 */
#include <stdio.h>
#include <stdarg.h>
#include <math.h>

double deviation(int first, ...);

int main( void )
{
    /* Call with 3 integers (-1 is used as terminator). */
    printf("Deviation is: %f\n", deviation(2, 3, 4, -1 ));

    /* Call with 4 integers. */
    printf("Deviation is: %f\n", deviation(5, 7, 9, 11, -1));

    /* Call with just -1 terminator. */
    printf("Deviation is: %f\n", deviation(-1));
}

/* Returns the standard deviation of a variable list of integers. */
double deviation(int first, ...)
{
    int count = 0, i = first;
    double mean = 0.0, sum = 0.0;
    va_list marker;
    va_list copy;

    va_start(marker, first);     /* Initialize variable arguments. */
    va_copy(copy, marker);       /* Copy list for the second pass */
    while (i != -1)
    {
        sum += i;
        count++;
        i = va_arg(marker, int);
    }
    va_end(marker);              /* Reset variable argument list. */
    mean = sum ? (sum / count) : 0.0;

    i = first;                  /* reset to calculate deviation */
    sum = 0.0;
    while (i != -1)
    {
        sum += (i - mean)*(i - mean);
        i = va_arg(copy, int);
    }
    va_end(copy);               /* Reset copy of argument list. */
    return count ? sqrt(sum / count) : 0.0;
}

2.vfprintf, _vfprintf_l, vfwprintf, _vfwprintf_l
Write formatted output using a pointer to a list of arguments

int vfprintf(
   // Pointer to FILE structure
   FILE *stream,
   // Format specification
   const char *format,
   // Pointer to list of arguments
   va_list argptr 
);

int _vfprintf_l(
   FILE *stream,
   const char *format,
   // The locale to use
   locale_t locale,
   va_list argptr 
);

int vfwprintf(
   FILE *stream,
   const wchar_t *format,
   va_list argptr 
);

int _vfwprintf_l(
   FILE *stream,
   const wchar_t *format,
   // The locale to use
   locale_t locale,
   va_list argptr 
);

vfprintf and vfwprintf return the number of characters written,
not including the terminating null character,
or a negative value if an output error occurs

the two functions behave identically if the stream is opened in ANSI mode
vfprintf doesn’t currently support output into a UNICODE stream.

The versions of these functions with the _l suffix are identical except that
they use the locale parameter passed in instead of the current thread locale.

TCHAR版:_vftprintf/_vftprintf_l

3._vscprintf, _vscprintf_l, _vscwprintf, _vscwprintf_l
Returns the number of characters in the formatted string using a pointer to a list of arguments.

int _vscprintf(
   // Format-control string
   const char *format,
   // Pointer to list of arguments
   va_list argptr 
);

int _vscprintf_l(
   const char *format,
   // The locale to use.
   locale_t locale,
   va_list argptr 
);

int _vscwprintf(
   const wchar_t *format,
   va_list argptr 
);

int _vscwprintf_l(
   const wchar_t *format,
   locale_t locale,
   va_list argptr 
);

_vscprintf returns the number of characters
that would be generated
if the string pointed to by the list of arguments was printed or sent to a file or buffer
using the specified formatting codes

TCHAR版本:_vsctprintf,_vsctprintf_l

///////////////////////////////////////////////////////////////
1.sscanf_s, _sscanf_s_l, swscanf_s, _swscanf_s_l

int sscanf_s(
   const char *buffer,
   const char *format [,
   argument ] ...
);

int _sscanf_s_l(
   const char *buffer,
   const char *format,
   locale_t locale [,
   argument ] ...
);

int swscanf_s(
   const wchar_t *buffer,
   const wchar_t *format [,
   argument ] ...
);

int _swscanf_s_l(
   const wchar_t *buffer,
   const wchar_t *format,
   locale_t locale [,
   argument ] ...
);

// 示例程式

// crt_sscanf_s.c
// This program uses sscanf_s to read data items
// from a string named tokenstring, then displays them.

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
   char  tokenstring[] = "15 12 14...";
   char  s[81];
   char  c;
   int   i;
   float fp;

   // Input various data from tokenstring:
   // max 80 character string plus NULL terminator
   sscanf_s( tokenstring, "%s", s, _countof(s) );
   sscanf_s( tokenstring, "%c", &c, sizeof(char) );
   sscanf_s( tokenstring, "%d", &i );
   sscanf_s( tokenstring, "%f", &fp );

   // Output the data read
   printf_s( "String    = %s\n", s );
   printf_s( "Character = %c\n", c );
   printf_s( "Integer:  = %d\n", i );
   printf_s( "Real:     = %f\n", fp );
}

// 輸出
String = 15
Character = 1
Integer: = 15
Real: = 15.000000