Tagged: va_start Toggle Comment Threads | Keyboard Shortcuts

  • Ali BaderEddin 6:35 pm on March 27, 2010 Permalink | Reply
    Tags: avg, INT_MIN, max, maximum, min, minimum, standard deviation, stdev, sum, var, variance, va_arg, , , va_start   

    SQL Aggregates in C 


    For fun, I would like to implement some of the SQL aggregates in C: SUM (sum), AVG (average), MIN (minimum), MAX (maximum), STDEV (standard deviation), VAR (variance).

    To do this in C, I’ll use functions with variable number of arguments instead of a function with an array and a count of the elements in that array. To do this, I need to have a special value for the last parameter in the variable list of arguments to know when to stop getting arguments in the list. For that, I’m going to use the INT_MIN macro in the <climits> C library. For example, to get the average of the numbers 6, 3, and 19, the call would look like AVG(6, 3, 19, INT_MIN).

    SUM

    Implementing this in C is lame, but I’ll use it as the starting point before getting to the other functions. I would definitely prefer to write 1 + 2 + 3 in C instead of SUM(1, 2, 3, INT_MIN).

    Definition

    int sum (int first, ...)
    {
        register int i = first;
        int sum = 0;
       
        //  declare a variable argument list
        va_list arg_list;
       
        //  initialize the arglist
        va_start (arg_list, first);
       
        //  Sum all arguments
        while(i != INT_MIN)
        {
            sum += i;
            i = va_arg (arg_list, int);
        }
       
        //  End the argument list
        va_end(arg_list);
       
        return sum;
    }

    Usage

    printf ("Sum of (1, 2, 3, 4, 5) = %d\n", sum (1, 2, 3 , 4, 5, INT_MIN));

    Output

    15

    AVG

    Instead of writing something like (1+2+3+4)/4 or (4 + 3 + 6 + 1 + 5 + 11 + 19 + 25 + 111 + 55 + 32 + 57)/ 12, I’d rather write AVG(1, 2, 3, 4, INT_MIN) or AVG(4, 3, 6, 1, 5, 11, 19, 25, 111, 55 , 32, 57, INT_MIN) without having to count the number of numbers I’m calculating the average for.

    Definition

    double avg (int first, ...)
    {
        register int i = first;
        int sum = 0, count = 0;
       
        va_list arg_list;
        va_start (arg_list, first);
       
        //  sum and count all arguments
        while(i != INT_MIN)
        {
            sum += i;
            count++;
            i = va_arg (arg_list, int);
        }
       
        va_end(arg_list);
       
        return (double) sum / count;
    }

    Usage

    printf ("Average of (1, 2, 3, 4, 5) = %.2f\n", avg (1, 2, 3 , 4, 5, INT_MIN));

    Output

    3.00

    MIN

    Instead of implementing MIN by passing an array and the count of numbers in that array , I’d rather just pass all the numbers to the function without having to worry about creating an array and counting the number of elements inside it.

    Definition

    int min (int first, ...)
    {
        register int i = first;
        int min = first;
       
        va_list arg_list;
        va_start(arg_list, first);
       
        //  Search for any other argument that is less than the first
        //  If you find one, then assign it to min
        while(i != INT_MIN)
        {
            if(i < min)
                min = i;
    
            i = va_arg(arg_list, int);
        }
       
        va_end(arg_list);
       
        return min;
    }

    Usage

    printf ("Minimum of (10, 23, 3, 41, 15) = %d\n", min (10, 23, 3, 41, 15, INT_MIN));

    Output

    3

    MAX

    Gets the maximum number in a set.

    Definition

    int max (int first, ...)
    {
        register int i = first;
        int max = first;
       
        va_list arg_list;
        va_start(arg_list, first);
       
        //  Search for any other argument that is greater than the first
        //  If you find one, then assign it to max
        while(i != INT_MIN)
        {
            if(i > max)
                max = i;
    
            i = va_arg(arg_list, int);
        }
       
        va_end(arg_list);
       
        return max;
    }

    Usage

    printf ("Maximum of (10, 23, 3, 41, 15) = %d\n", max (10, 23, 3, 41, 15, INT_MIN));

    Output

    41

    STDEV

    Calculates the standard deviation for a set of numbers.

    Definition

    double stdev (int first, ...)
    {
        register int i = first;
        int count = 0;
        int sum = 0;
        double mean = 0;
        double deviation = 0;
        va_list arg_list;
    
        //  Calculate the mean (average)
        va_start(arg_list, first);
       
        while(i != INT_MIN)
        {
            sum += i;
            count++;
            i = va_arg (arg_list, int);
        }
       
        va_end(arg_list);
        mean = (float) sum / count;
    
        //  Calculate the standard deviation
        i = first;
        va_start(arg_list, first);
       
        while(i != INT_MIN)
        {
            deviation += pow((i - mean), 2);
            i = va_arg (arg_list, int);
        }
    
        deviation /= count;
        deviation = sqrt(deviation);
    
        va_end(arg_list);
       
        return deviation;
    }

    Usage

    printf ("Standard Deviation of (2, 4, 4, 4, 5, 5, 7, 9) = %.2f\n", stdev (2, 4, 4, 4, 5, 5, 7, 9, INT_MIN));

    Output

    2.00

    VAR

    Calculates the variance for a set of numbers.

    Definition

    double var (int first, ...)
    {
        register int i = first;
        int count = 0;
        int sum = 0;
        double mean = 0;
        double variance = 0;
        va_list arg_list;
    
        //  Calculate the mean (average)
        va_start(arg_list, first);
       
        while(i != INT_MIN)
        {
            sum += i;
            count++;
            i = va_arg (arg_list, int);
        }
       
        va_end(arg_list);
        mean = (float) sum / count;
    
        //  Calculate the variance
        i = first;
        va_start(arg_list, first);
       
        while(i != INT_MIN)
        {
            variance += pow((i - mean), 2);
            i = va_arg (arg_list, int);
        }
    
        variance /= (count - 1);
    
        va_end(arg_list);
       
        return variance;
    }

    Usage

    printf ("Variance of (1, 2, 3, 4, 5, 6) = %.2f\n", var (1, 2, 3, 4, 5, 6, INT_MIN));

    Output

    3.50


    Full source code is available here.

     
  • Ali BaderEddin 12:05 am on March 23, 2010 Permalink | Reply
    Tags: glRasterPos, glutBitmapCharacter, GLUT_BITMAP_HELVETICA, GLUT_BITMAP_TIMES_ROMAN, OpenGL string, OpenGL Text, printw, , , va_start, vsprintf_s, _vscprintf   

    OpenGL String (printw) 


    There are many ways for displaying text in OpenGL. In this post, I’ll use the glutBitmapCharacter function to draw characters, and then will extend it to a more generic function (printw), which will make drawing a string in OpenGL as simple as using printf.

    First, I will start by defining the font to be used by the glutBitmapCharacter function. I will choose a 24-point proportional spaced Times Roman font as shown below:

    //  A pointer to a font style..
    //  Fonts supported by GLUT are: GLUT_BITMAP_8_BY_13,
    //  GLUT_BITMAP_9_BY_15, GLUT_BITMAP_TIMES_ROMAN_10,
    //  GLUT_BITMAP_TIMES_ROMAN_24, GLUT_BITMAP_HELVETICA_10,
    //  GLUT_BITMAP_HELVETICA_12, and GLUT_BITMAP_HELVETICA_18.
    GLvoid *font_style = GLUT_BITMAP_TIMES_ROMAN_24;

    To draw a character, simply define the raster position using glRasterPos3f (x, y, z), then draw it using glutBitmapCharacter(font_style, character). To extend this to drawing a string at certain coordinates, loop over each character in the string and draw it with glutBitmapCharacter. The additional logic that goes below is in making this as pretty as printf.

    This can be done by using C’s va_list type, which is C’s approach to defining functions with variables number of arguments.

    • In the function prototype, place ellipsis (…) as the last argument
    • Define a variable argument list: va_list args;
    • Call va_start on the args list and the first real argument in the function prototype preceding the ellipsis: va_start(args, format);
    • Use _vscprintf to get the number of characters that would be generated if the string pointed to by the list of arguments was printed using the specified format
    • Allocate memory for a string with the specified number of characters
    • Call vsprintf_s to build the string we want from the list of arguments
    • Call va_end to end the use of the variables argument list
    • Draw our beautified string
    • Free allocated memory

    Function implementation with full comments shown below:

    //-------------------------------------------------------------------------
    //  Draws a string at the specified coordinates.
    //-------------------------------------------------------------------------
    void printw (float x, float y, float z, char* format, ...)
    {
        va_list args;   //  Variable argument list
        int len;        // String length
        int i;          //  Iterator
        char * text;    // Text
    
        //  Initialize a variable argument list
        va_start(args, format);
    
        //  Return the number of characters in the string referenced the list of arguments.
        // _vscprintf doesn't count terminating '\0' (that's why +1)
        len = _vscprintf(format, args) + 1;
    
        //  Allocate memory for a string of the specified size
        text = malloc(len * sizeof(char));
    
        //  Write formatted output using a pointer to the list of arguments
        vsprintf_s(text, len, format, args);
    
        //  End using variable argument list
        va_end(args);
    
        //  Specify the raster position for pixel operations.
        glRasterPos3f (x, y, z);
    
        //  Draw the characters one by one
        for (i = 0; text[i] != '\0'; i++)
        glutBitmapCharacter(font_style, text[i]);
    
        //  Free the allocated memory for the string
        free(text);
    }

    Now that printw is defined, using it is similar to printf:

    printf(         "char: %c, decimal: %d, float: %f, string: %s", 'X', 1618, 1.618, "text");
    printw(x, y, z, "char: %c, decimal: %d, float: %f, string: %s", 'X', 1618, 1.618, "text");

    Libraries to include before copying the function ;)

    #include <stdio.h>    //  Standard Input\Output C Library
    #include <stdarg.h>   //  To use functions with variables arguments
    #include <stdlib.h>   //  for malloc
    #include <gl/glut.h>  //  Include GLUT, OpenGL, and GLU libraries

    Here is a sample source code that contains the printw function. If you have any issues compiling or running the app, check out this section for details about compiling and running an OpenGL app that uses the GLUT library. Below is a screen shot of the demo app:

     
    • Vitalie 9:59 pm on September 17, 2010 Permalink | Reply

      Hi, im getting a simple error when compiling, this even happens when i use the link to the ‘many ways’

      There is a

      error C3861: ‘printw': identifier not found

      It does not say what identifier, and i have no idea what its talking about, all identifiers are there. Im compiling with Visual Studio 2010, any ideas?

    • Ali BaderEddin 11:08 pm on September 17, 2010 Permalink | Reply

      Can you share your code? Is the file extension .c or .cpp? Make sure the printw function is defined before you call it (i.e. placed in source file before its called).

    • Anajrob 12:05 pm on January 24, 2011 Permalink | Reply

      Hello, I am getting an error in Visual Studio on

      // Allocate memory for a string of the specified size
      text = malloc(len * sizeof(char));

      It says that a value of type “void*” cannot be assigned to an entity of type “char*”.

      • axy 8:42 am on March 28, 2011 Permalink | Reply

        use
        text = (char*) malloc(len * sizeof(char));

    • Jalal 9:51 am on July 28, 2011 Permalink | Reply

      Thanks

    • Cecil 2:29 pm on November 24, 2011 Permalink | Reply

      Easiest way I’ve seen how to do simple text for my scene using keyboard controls to move throughout it.

      -Computer Graphics Student

    • em 9:59 am on January 4, 2012 Permalink | Reply

      How did you make the color of the text white?

      • Zatoichi 8:00 pm on June 16, 2013 Permalink | Reply

        glcolor3f(1,1,1) ;; is white color and you can set the values as you want.

    • Sharaf 12:51 pm on February 28, 2013 Permalink | Reply

      Thanks for sharing this function, I’m facing little problem, I can’t find drawn text :D
      Is that because you are using center of the window as origin, and i’m using top left ?

    • bird12358 11:56 am on December 11, 2013 Permalink | Reply

      Hello,

      I would like to use the printw function. In my program I display a image thanks to glDrawPixels function. I try to display text with printw function but it seems that the images is troncate and is not display fully.

      How can I do this?

      Best regard

    • Santosh Desai 5:07 am on April 18, 2015 Permalink | Reply

      Hey Mr. Ali, can I share this code in my project in agreement with GNU GPL license?

    • Ali BaderEddin 2:11 pm on April 18, 2015 Permalink | Reply

      Santosh, sure, use it as you like

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: