Friday, August 24, 2012

Drawing in SDL

    Hopefully you have a working C and SDL setup by now and are ready to use more SDL functions.  First, we need a window that operates normally: exiting only when it is instructed rather than after a delay.  SDL has simple drawing, coloring, and updating functions which can be used with C to draw almost anything.

Window Setup:
    In order to instruct SDL to wait for an exit command, we must first understand how SDL handles input.  A structure called SDL_Event has data for many different types of input including mouse, keyboard, joystick, and exit commands.  To determine which type of event has occurred, the data field "type" of an SDL_Event variable can be compared against the enumerations SDL_MOUSEMOTION, SDL_KEYDOWN, SDL_JOYAXISMOTION, SDL_QUIT, and many more.

    If multiple events occur at the same time, they are given a priority and placed in order; this allows events to be processed one at a time.  For this example, only the quit event will be handled:
/*thanks to tohtml.com for syntax highlighting*/

#include <SDL/SDL.h>
#include <stdio.h>

/*holds data about the drawable surface*/
SDL_Surface *screen;

SDL_Event input; /*holds input*/
int loop = 1; /*set to zero to exit*/

int main(int argc, char** argv) {
    /*start up SDL and setup window*/
    SDL_Init(SDL_INIT_EVERYTHING);
    screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

    /*loop is needed to keep window open*/
    while (loop == 1) {
        /*read all events per cycle*/
        while (SDL_PollEvent(&input)) {
            if (input.type == SDL_QUIT) {
                printf("exiting...\n");
                loop = 0; /*exit if quit*/
            }
        }
    }

    /*perform final commands then exit*/
    SDL_Quit(); /*shutdown SDL*/
    fflush(stdout); /*update stdout*/
    return 0;
}
prompt/stdout:
exiting...
output inside window:
Still blank

    The variable screen is a pointer to the data type SDL_Surface.  It points to a structure which holds the information about a drawable surface in SDL; in this case, it is the background of the window.  You can find out the width, height, color depth, and even the color of individual pixels from the SDL_Surface structure, which makes it ideal for drawable surfaces and imported images.  It is assigned this information from the SDL_SetVideoMode function and will prove vital for drawing operations.

    The next variable is called input and is of type SDL_Event.  Note that screen and input are names I chose to use, you can use whichever titles you wish.  To give information about user input, the command SDL_PollEvent is given the address of our SDL_Event variable to change its data.  This function will become false once all input has been processed, so it is given its own loop within the program's loop to allow processing of any number of events.

    Integer variable loop is created to track the status of the program loop: when its value changes, the loop is broken and the final commands are called.  The value 0 is used to indicate no more looping because it usually means false, but the comparison "loop == 1" allows any value other than 1 to mean the same.

Rectangles:
    One shape SDL draws well is rectangles.  In fact, SDL has the SDL_Rect structure to describe rectangles based on position, width, and height.  The data fields for the struct are x, y, w, and h, which mean x coordinate, y coordinate, width, and height.  x and y are of type "Sint16" while w and h use the type "Uint16".

    These type names are not standard C: SDL simply gives different names to existing data types using a typedef command.  For Sint16 and Uint16, they are really the data types signed short and unsigned short respectively.  As for the int16 part, a short uses 16 bits and is an integer type of data.  SDL has titles for char (Sint8), unsigned char (Uint8), int (Sint32), unsigned int (Uint32), long (Sint64), and unsigned long (Uint64).

    Before we can draw the rectangle, two more functions are needed.  SDL_FillRect requires a pointer to an SDL_Surface struct, a pointer to an SDL_Rect struct, and a Uint32 to represent a color.  The SDL_Surface* parameter will be the screen variable since it is being drawn on and the SDL_Rect* parameter will be to an SDL_Rect we create.  For now, the Uint32 color will be given the value 0xFFFFFFFF (4,294,967,295 or the color white).

    The function SDL_Flip has a single SDL_Surface* and updates whichever surface is input.  This will be the screen for the following example:
/*thanks to tohtml.com for syntax highlighting*/

#include <SDL/SDL.h>
#include <stdio.h>

/*holds data about the drawable surface*/
SDL_Surface *screen;

SDL_Event input; /*holds input*/
int loop = 1; /*set to zero to exit*/

int main(int argc, char** argv) {
    SDL_Rect block;
    block.x = 200; /*200 pixels from left*/
    block.y = 100; /*100 pixels from top*/
    block.w = 400; /*400 pixels wide*/
    block.h = 300; /*300 pixels tall*/

    /*start up SDL and setup window*/
    SDL_Init(SDL_INIT_EVERYTHING);
    screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

    /*print out the properties of block variable*/
    printf("position: (%d, %d)\n", block.x, block.y);
    printf("dimensions: %u x %u\n", block.w, block.h);

    /*loop is needed to keep window open*/
    while (loop == 1) {
        /*draw block rectangle on screen*/
        SDL_FillRect(screen, &block, 0xFFFFFFFF);

        /*read all events per cycle*/
        while (SDL_PollEvent(&input)) {
            if (input.type == SDL_QUIT) {
                loop = 0; /*exit if quit*/
            }
        }

        SDL_Delay(20); /*wait 20ms*/
        SDL_Flip(screen); /*update the screen*/
    }

    /*perform final commands then exit*/
    SDL_Quit(); /*shutdown SDL*/
    fflush(stdout); /*update stdout*/
    return 0;
}
prompt/stdout:
position: (200, 100)
dimensions: 400 x 300
output inside window:
A White Rectangle

    For this example, multiples of 100 are used to set the properties of a rectangle, but any numbers may be used.  Once the position and dimensions of the rectangle are set, we can draw it giving SDL_FillRect our variables screen and block and an integer value used to indicate a color.

    The SDL_FillRect and SDL_Flip commands are executed every cycle of the program loop.  Since the rectangle does not move, drawing and updating could both be performed before "while (loop == 1)" to get the same result.  For later, interactive examples, this will not be the case.

    The command "SDL_Delay(20)" was added; this was to allow the computer to rest 20 milliseconds (for a maximum of 50 cycles or "frames" per second) before updating the screen.  By letting the computer rest, less effort is put towards drawing frames we may not notice.  Since video games attempt 60 frames per second, a delay of 16ms or less may be more ideal.

Colors:
    The only 32-bit value of a color we can know without doubt is the one used for white: 0xFFFFFFFF.  This is because within this value are the lesser values used for alpha (opacity), red, green, and blue (which are all maximum for white).  The format of a surface determines how these lesser values combine to form a 32-bit value.

    Since 32 bits are divided among 4 components, each component uses 8 bits like the char data type.  The most common format is (alpha << 24) + (red << 16) | (green << 8) | blue.  This means the 8 alpha bits shifted just left of the 8 red bits, which are left of the 8 green, and green is left of blue bits.  Luckily, hexadecimal shows this pattern nicely: for a number like 0x89ABCDEF, 0x89 is alpha, 0xAB is red, 0xCD is green, and 0xEF is blue (but only if the common format is in use).

    For other formats, the red and blue bits may be swapped or alpha may be on the other end.  To account for these possibilities, the function SDL_MapRGB requires a pointer to an SDL_PixelFormat struct in addition to Uint8 values for red, green, and blue.  Luckily, the screen variable has this information under its "format" data field.

    Another function is SDL_MapRGBA, which allows input for alpha.  For more information about this function (and SDL_MapRGB) visit http://sdl.beuc.net/sdl.wiki/SDL_MapRGBA.  However, alpha values are often ignored when drawing rectangles, so we can say alpha = 0 and still have an opaque rectangle drawn.  Also, 0x00FFFFFF is equal to 0xFFFFFF, allowing for colors of only three components (alpha ignored).  Here are some rectangles with color:
/*thanks to tohtml.com for syntax highlighting*/

#include <SDL/SDL.h>
#include <stdio.h>

/*holds data about the drawable surface*/
SDL_Surface *screen;

SDL_Event input; /*holds input*/
int loop = 1; /*set to zero to exit*/

int main(int argc, char** argv) {
    SDL_Rect magenta_block; /*three rectangles*/
    SDL_Rect yellow_block, cyan_block;

    Uint32 magenta, yellow, cyan; /*colors*/
    Uint8 red, green, blue; /*components*/

    /*setup block positions and dimensions*/
    magenta_block.x = 50;
    magenta_block.y = 75;
    magenta_block.w = 200;
    magenta_block.h = 150;

    yellow_block.x = 100;
    yellow_block.y = 200;
    yellow_block.w = 150;
    yellow_block.h = 200;

    cyan_block.x = 200;
    cyan_block.y = 100;
    cyan_block.w = 200;
    cyan_block.h = 200;

    /*start up SDL and setup window*/
    SDL_Init(SDL_INIT_EVERYTHING);
    screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

    /*setup colors after screen initialized*/
    magenta = SDL_MapRGB(screen->format, 255, 0, 255);
    yellow = 0xFFFF00; /*red and green*/
    cyan = SDL_MapRGB(screen->format, 0, 255, 255);

    /*Get and print yellow components*/
    SDL_GetRGB(yellow, screen->format, &red, &green, &blue);
    printf("yellow: RGB(%u, %u, %u)\n", red, green, blue);

    /*loop is needed to keep window open*/
    while (loop == 1) {
        /*draw rectangles on screen*/
        SDL_FillRect(screen, &magenta_block, magenta);
        SDL_FillRect(screen, &yellow_block, yellow);
        SDL_FillRect(screen, &cyan_block, cyan);

        /*read all events per cycle*/
        while (SDL_PollEvent(&input)) {
            if (input.type == SDL_QUIT) {
                loop = 0; /*exit if quit*/
            }
        }

        SDL_Delay(20); /*wait 20ms*/
        SDL_Flip(screen); /*update the screen*/
    }

    /*perform final commands then exit*/
    SDL_Quit(); /*shutdown SDL*/
    fflush(stdout); /*update stdout*/
    return 0;
}
prompt/stdout:
yellow: RGB(255, 255, 0)
output inside window:
3 Rectangles with Color

    Here we see three rectangles of different colors.  The three colors used are the secondary colors of light: magenta, yellow, and cyan, which are the basic ink colors for printers.  We can break down a color into its red, green, and blue components with the function SDL_GetRGB by giving it the Uint32 color, format, and addresses of three Uint8 variables to write to.  This is how the components of yellow were determined.

    The order of the drawing makes a difference: note that magenta is drawn first and cyan last.  In the final picture, the magenta block is obscured by the yellow and cyan blocks because every new draw command will overwrite the previous commands.  Here, several pixels are colored magenta, then yellow, and finally stop at cyan.

    To wrap up this post, some references are needed.  For information about RGB color, wikipedia has the page http://en.wikipedia.org/wiki/RGB_color_model.  For color ideas, here is a table of hexadecimal colors used with websites: http://www.tayloredmktg.com/rgb/.  For more documentation about SDL_FillRect, the page http://www.libsdl.org/docs/html/sdlfillrect.html is helpful, and the page http://www.libsdl.org/docs/html/index.html for SDL in general.

    Thank you for reading, the next post will cover keyboard interaction.

Saturday, August 18, 2012

SDL setup

    Simple DirectMedia Layer, or SDL for short, is a great library for building applications which run outside the terminal or command prompt in their own window.  Although the program does not require a prompt to run, I believe it helps to have something simple to print values to, so the following posts will use a mixture of output from the prompt and graphics in the window.

Setup:
    To prepare the SDL library (and most other libraries), we need header files and library files.  Header files have a .h extension and are used to access the functions and structures found in the library.  Library files have several extensions: .lib, .a, .la, .dll, and possible others; and contain the code necessary for the library functions to work.  Library files must be linked into a program during its transition from C code to machine language.
To learn more about this transition, an informative video can be found at http://www.youtube.com/watch?v=gUKXew-0L1I and an in-depth page at http://www.tenouk.com/ModuleW.html.

    I will attempt to cover setup for multiple systems, but please review the pages http://lazyfoo.net/SDL_tutorials/lesson01/index.php and http://content.gpwiki.org/index.php/SDL:Tutorials:Setup because they will be much more insightful.  To obtain the header and library files for your system, visit the SDL 1.2 download page at http://www.libsdl.org/download-1.2.php.  Unfortunately, I have not found a working online compiler with SDL support.

For Linux:
    Downloading from the site is optional because you can use package managers.  There are the packages "libsdl1.2-dev" or "SDL-devel-1.2" for SDL and "build-essentials" or "Development Tools" if one of them is not already installed.  These should place the necessary header and library files in the "include" and "lib" folders.  Otherwise, try running the RPM file from the site.

    To link the libraries to the program with GCC, add -l(library name) after the usual compile command.  For example, "gcc (file name).c -o (program name) -lSDLmain -lSDL" will link the basic SDL library to the created program.

For Mac:
    Currently, there does not appear to be a link under "development libraries" as seen in the Lazy Foo Tutorial pages.  Hopefully, the page http://macemulators.wordpress.com/2009/11/05/how-to-install-sdl/ will provide better assistance.

    I believe the GPwiki link will be more thorough explaining how to setup a working SDL project in xcode.  I apologize for not knowing much about SDL on Mac OSX :(.

For Windows:
    If you use visual studio, download the VC package under "development libraries" and extract the contents.  There should be an "include" and "lib" folder as well as some DLL's in "bin".  To get the include and library files to visual studio, you can add the lib and include folder locations to Tools->options->VC++ Directories.  Alternatively, you can take the contents of these folders and add them to the existing include and lib folders where visual studio is installed (usually C:/Program Files/Microsoft Visual Studio/VC).  Also, in linker settings, specify the subsystem to be "console" preferably, or "windows" if that does not work.

    If you use MinGW without a compiler, place the lib and include folder contents in MinGW's lib and include folders.  This can usually be found in C:/MinGW/.  To link libraries, see the above instructions for GCC under For Linux.  If you downloaded the vc package, the .lib libraries can be linked with -l:(library file with extension).  For example, "gcc (file name).c -o (program name) -lmingw32 -l:SDLmain.lib -l:SDL.lib" will link the basic SDL library to the program.

    The DLL's are not needed during compilation, but must be present when your program is run.  This means they can be placed right next to the program or in the system32 or syswow64 folder in C:/windows/.  For portability, it is recommended you place the DLL's in the same folder as your program.

Linking libraries in IDE's:
    Most IDE's, like Code::Blocks, Eclipse, Visual Studio, and Xcode, have features to help link libraries called linker options.  This usually allows you to find the library files manually and add them to a project.  For IDE's running the GCC/MinGW compiler (Xcode, Code::Blocks, or Eclipse) link the library files "libSDL.la" and "libSDLmain.a" or the .lib files "SDL.lib" and "SDLmain.lib".  For Visual Studio, simply link the .lib files from the VC package.

Sample Program:
    To test whether SDL is now working with your C compiler, here is a simple C program with SDL integrated:
/*thanks to tohtml.com for syntax highlighting*/

#include <SDL/SDL.h>
#include <stdio.h>

/*parameters of main are command-line arguments*/
int main(int argc, char** argv) {
    SDL_Init(SDL_INIT_EVERYTHING); /*initialize SDL*/
    SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE); /*window setup*/

    printf("C running with SDL!\n");

    SDL_Delay(3000); /*wait 3 seconds*/
    SDL_Quit(); /*close SDL*/
    fflush(stdout); /*update stdout*/
    return 0;
}
prompt/stdout:
C running with SDL!
output inside window:
Blank SDL window

    This short program starts by including the header file "SDL.h", which is all that is required for the basic SDL library.  The function main has two parameters used to read from a prompt when starting a program: the first parameter is the number of inputs and the second is an array of strings representing the input.  For example, if you run the program with the command "program_name", where program_name is the name of your program, argc will be 1 and argv[0] will be the string "program_name".  You can add command-line arguments by typing "program_name argument1 argument2" which makes argc 3 and argv[1] and argv[2] "argument1" and "argument2" respctively.

    These posts will rarely use this feature, but it is required to work with c++ programs under visual studio.  Next, SDL_Init is given the flag SDL_INIT_EVERYTHING (the value 65535 or 0x0000FFFF), which starts up all parts of the SDL library.  SDL_SetVideoMode sets the properties of the window created: here we use a 640 pixels wide, 480 pixels tall, 32-bit color window with software (or processor) rendering, as indicated by the SDL_SWSURFACE flag (value of 0).  Finally, a message is printed to the prompt, the program waits 3000 milliseconds, then shuts down the SDL library and terminates.

Text Output:
    In order to test the value of variables, it is recommended that printf be able to print to a prompt.  For most cases, this will not be a problem, but for instances where the prompt is not visible, check the folder containing the program for a file called "stdout" (with possible extension) after testing the program.  This file should contain the text that normally prints to the prompt.

    The command "fflush(stdout);" writes any text currently in memory into the file stdout.  However, this does not mean changing the input from stdout to file_name_here will create a file called "file_name_here"; stdout is a built-in file for C which refers to the standard output.  Without the command, sometimes text output can remain in memory and not be written to the stdout file.

    That's all for this post, the next post will cover events and drawing in SDL.  For more SDL tutorials, check out http://lazyfoo.net/SDL_tutorials/ and http://content.gpwiki.org/index.php/SDL:Tutorials.  Thank you for reading.

Monday, July 30, 2012

C Enumeration

    Enumerated data types in C allow us to assign names to a set of integer values.  This new data type can be given its own name as well.  This post will discuss basic enumeration, the #define statement, values in hexadecimal, and using single bits as flags.

Enumeration:
    If you have a list of possible choices which are not necessarily numbers, then enumeration can help the code show these possibilities.  As an example, if you want to select only one color from a set of defined colors, then you can create an enumeration called color.  Then give names like red, yellow, green, and blue to values like 0, 1, 2, and 3.

    Here is an example function which has a color type as a parameter:
#include <stdio.h>

//use color in place of enum color
typedef enum color color;

enum color {
    red, //is given value 0
    yellow, // == 1
    green, // 2
    blue // 3
};

//a function that prints the chosen color
void choose_color(color selection) {
    switch(selection) {
    case red: //if (selection == red)
        printf("red selected\n");
        break;
    case yellow: //else if (selection == yellow)
        printf("yellow selected\n");
        break;
    case green:
        printf("green selected\n");
        break;
    case 3:
        printf("blue selected\n");
        break;
    default: //else
        printf("unknown selection\n");
        break;
    }
}

int main() { //select three colors
    choose_color(red);
    choose_color(1); //could put yellow instead
    choose_color(blue);

    getchar();
    return 0;
}
output in prompt:
red selected
yellow selected
blue selected


    By creating the enum color and using typedef, color is now a unique type of data.  The function choose_color creates the variable selection of type color using input and compares its value to those found in the enum color list.  Notice that the term red is now interchangeable with the value 0, which means no variable should be named red.

    Although colors are used in this example, enumerations can be used for many sets of choices: directions, months, locations, shapes, etc.  Usually, each individual choice excludes the others; one cannot be in two locations or in two months at the same time.  Luckily, whole numbers work the same way in that each value is unique.

    There is also an alternative to creating an enum which is to use #define.  The #define statement is similar to the find and replace option found in text editors because it will replace the first parameter with the second.  If you wanted to replaced the name red with 0, you would use "#define red 0".

    Here is an alternative to the previous example:
#include <stdio.h>

#define red 0 //replace all red with 0
#define yellow 1 //yellow becomes 1
#define green 2 //green becomes 2
#define blue 3 //blue becomes 3

//a function that prints the chosen color
void choose_color(int selection) {
    switch(selection) {
    case red: //if (selection == red)
        printf("red selected\n");
        break;
    case yellow: //else if (selection == yellow)
        printf("yellow selected\n");
        break;
    case green:
        printf("green selected\n");
        break;
    case 3:
        printf("blue selected\n");
        break;
    default: //else
        printf("unknown selection\n");
        break;
    }
}

int main() { //select three colors
    choose_color(red);
    choose_color(1);
    choose_color(blue);

    getchar();
    return 0;
}
output in prompt:
red selected
yellow selected
blue selected


    Since there is no enum called color this time, the variable selection (in function choose_color) is of type int.  Also, there is no need for the typedef statement from before.  While this is mostly positive, the one negative side effect is that NO variable can be named red, yellow, green, or blue because it will be replaced with 0, 1, 2, or 3.  One way around this is to make the color names look less "variable-ish", like using all capital letters and possibly adding a prefix like COLOR_ to each choice.

Flags:
    Unlike enumerations that exclude each other, flags use bits to allow for more possibilities.  Each bit can be used to determine whether a choice is selected or not, but each selection does not exclude others.  One way to access individual bits easily is to use hexadecimal values.

    Where decimal uses 0-9 and binary only uses 0 and 1, hexadecimal uses 0-9 as well as a-f.  The hexadecimal value a equals 10 in decimal and f is 15 in decimal.  To translate a hexadecimal value into decimal, multiply each number by a power of sixteen.  For example, hexadecimal c5 = c * 16^1 + 5 * 16^0 = 12 * 16 + 5 * 1 = decimal 197.

    For flags, you need to use powers of two for each choice.  This allows the use of individual bits (1 = 00000001, 2 = 00000010, 4 = 00000100, etc.) which can then be added together.  The reason hexadecimal is helpful is because its powers of sixteen are divisible by several powers of two, and are also a power of two themselves.  This allows for easier setting of bits, as seen in the following table:

decimal valuebinary (8 bits)hexadecimal
10000000101
20000001002
40000010004
80000100008
15000011110f
160001000010
320010000020
640100000040
1281000000080
24011110000f0
25511111111ff

    This table assumes that the value is unsigned (for signed, the last three would be -128, -16, and -1).  While there are patterns in the binary and decimal numbers, there is an easier to see pattern in the hexadecimal and binary numbers: each hexadecimal number affects 4 bits.  We only have to remember 1, 2, 4, and 8 as powers of two.

    If each choice is assigned a power of two, we can add the selected choices (or use bitwise or) and get a set of bits which correspond to the selections.  To retrieve the choices from the bits, we can use bitwise and.  Here is an example with some possible choices one may find in an application:
#include <stdio.h>

//features and enum features synonymous
typedef enum features features;

//for hexadecimal values, 0x is placed in front
enum features { //manually assign values
    subtitles = 0x01,
    music = 0x02,
    sound_effects = 0x04,
    multiplayer = 0x08
};

/* input a set of bits (in int form)
   and the function says which features
   are selected (by checking bits).
*/
void select_features(int flags) {
    printf("Features selected:\n");

    if ((flags & subtitles) != 0) {
        printf("-subtitles\n");
    }

    if ((flags & music) != 0) {
        printf("-music\n");
    }

    if ((flags & 0x04) != 0) {
        printf("-sound effects\n");
    }

    if ((flags & multiplayer) != 0) {
        printf("-multiplayer\n");
    }

    printf("\n");
}

int main() {
    /*make three selections of multiple
      choices, zero being none*/
    select_features(music | subtitles);
    select_features(multiplayer + music);
    select_features(0x0f);

    getchar();
    return 0;
}
output in prompt:
Features selected:
-subtitles
-music

Features selected:
-music
-multiplayer

Features selected:
-subtitles
-music
-sound effects
-multiplayer



    The first change you may notice is that values can be assigned to the list of enumerated values.  This is useful since we must use powers of two, which are in hexadecimal for this example.  The hexadecimal is not exactly useful in this case, but if another feature is added, the next hexadecimal value would be 0x10.  Also, since an int is usually 32 bits, you can replace 0x10 with 0x00000010 (8 hexadecimal places, each of which control 4 bits).

    Each select_features call in the main function allows us to simply list which features we want to use.  We can use bitwise or (|), addition(+), or even a number to  indicate the selected features.  This type of input will be common in libraries like SDL, OpenGL, and OpenAL.

    The input for the function select_features is not of the variable type features.  An integer is used to allow operations like addition and bitwise or unlike created data types.  Also, the resulting number may not be one of the power-of-two elements in the enum list.  Since this is not a great use of enumeration, most libraries will use #define for flags.

    Here is a similar example using #define:
#include <stdio.h>

/* will replace the following names
   with integer values */
#define FEAT_SUBS 0x01 //8-bit hexadecimal
#define FEAT_MUSIC 2 //decimal
#define FEAT_SOUNDFX 0x04
#define FEAT_MULTI 0x00000008 //32-bit

//tell which features are selected
void select_features(int flags) {
    printf("Features selected:\n");

    if ((flags & FEAT_SUBS) != 0) {
        printf("-subtitles\n");
    }

    if ((flags & FEAT_MUSIC) != 0) {
        printf("-music\n");
    }

    if ((flags & FEAT_SOUNDFX) != 0) {
        printf("-sound effects\n");
    }

    if ((flags & FEAT_MULTI) != 0) {
        printf("-multiplayer\n");
    }

    printf("\n");
}

int main() {
    /*make three selections of multiple
      choices, zero being none*/
    select_features(FEAT_MUSIC | FEAT_SUBS);
    select_features(FEAT_MULTI + FEAT_MUSIC);
    select_features(0x0f);

    getchar();
    return 0;
}
output in prompt:
Features selected:
-subtitles
-music

Features selected:
-music
-multiplayer

Features selected:
-subtitles
-music
-sound effects
-multiplayer



    The names in the program have been changed to reflect the style a library like SDL uses.  The features are still given the same values: 1, 2, 4, and 8, the first four powers of two.  The same selections from the previous program are made and the same results occur, however the code is slightly shorter and no new data types are introduced.

    For more information about enumerated types, go to http://cplus.about.com/od/introductiontoprogramming/p/enumeration.htm and http://www.cprogramming.com/tutorial/enum.html.  For a guide to hexadecimal, the page http://www.myhome.org/pg/numbers.html should help.

    Thank you for reading, the next post will begin the SDL posts!  This does not mean the end of the C posts, but they will be less frequent.  For more C, there are the pages http://www.acm.uiuc.edu/webmonkeys/book/c_guide/, http://beej.us/guide/bgc/output/html/multipage/index.html, and http://www.cprogramming.com/tutorial/c-tutorial.html.

Thursday, July 19, 2012

Strings in C

    One popular use of pointers is strings, the data type for text.  Until now, all data and commands have dealt with numbers, but strings allow storage of messages and names.  This is accomplished with an array of characters, or char variables.  This post will discuss the char data type and char arrays.

The char type:
    A char is a whole number with the range of values -128 to 127 if it is signed or 0 to 255 if unsigned.  This value can be used as a number as well as a single letter.  ASCII is used to convert a number into a letter or symbol: 65-90 become upper case A-Z and 97-122 become a-z.  A full table can be found at http://www.asciitable.com/.

    To print the symbol or letter form of a character, use the %c marker with printf.  The ASCII values 48-57 are used for the number symbols 0-9, so be careful not to confuse this output with the numeric value of the character.  Also, the symbols with values outside the range 0-127 will depend upon the standard used by a country.

    If you don't want to memorize the ASCII values of a symbol, C allows us to assign symbols straight to chars.  Here is a demonstration.
#include <stdio.h>

int main() {
    char letter = 'g';
    char symbol = 47; //no single-quotes
    char number = '3'; //single quotes

    //%c for the symbol, %d or %u for its value
    printf("%c in ASCII: %d\n", letter, letter);
    printf("%c in ASCII: %d\n", symbol, symbol);
    printf("%c in ASCII: %d\n", number, number);

    getchar();
    return 0;
}

output in prompt:
g in ASCII: 103
/ in ASCII: 47
3 in ASCII: 51


    The char letter is assigned the value 103, or the ASCII value of the lower-case letter g.  By placing single quotes around a keyboard symbol, C will convert the symbol into its ASCII code automatically.  Notice that the symbol 3 has a numeric value of 51: it is best to remember which is the ASCII code and which is the symbol.

Strings:
    By placing a collection of these characters into an array, we can create a string.  This can hold a word, a sentence, a sequence of numbers, and anything else you can type into a text editor.  Strings can be placed in either static or dynamic arrays.

    Since strings can be placed in dynamic arrays, there exists a way to track their length.  Every C string ends with an additional null character to indicate there is no more data.  A null character has the numeric value 0 and can be represented as '\0' in symbol form.  The \ in front is the same used by the character '\n'.

    Once you have a sequence of characters in an array ending with the null character, you can print the string.  Use the %s marker in printf to print the string, but it only stops at the end if there is a null character.  Also, an additional string library (string.h) contains the strlen function which finds length of a string.  It too stops at the null character, but does not count it.

    Now, to demonstrate how strings can be created and printed, here are three ways to say hello:

#include <stdio.h>
#include <stdlib.h>
#include <string.h> //full of string functions

char* quotes = "hello";
char static_array[] = {'h','e','l','l','o','\0'};
char* dynamic; //will copy from static

int main() {
    int index;
    int size = strlen(static_array);

    printf("string length = %d\n", size);
    size += 1; //size to include null char

    dynamic = (char*)malloc(size * sizeof(char));

    for (index = 0; index < size; ++index) {
        dynamic[index] = static_array[index];
    }

    //print all forms of hello
    printf("quotes: %s\n", quotes);
    printf("static: %s\n", static_array);
    printf("dynamic: %s\n", dynamic);

    //remove dynamic from memory
    free(dynamic);

    getchar();
    return 0;
}

output in prompt:
string length = 5
quotes: hello
static: hello
dynamic: hello


    The static array is assigned a set of values.  This method of assigning values does not require us to specify a size and only works for statically allocated arrays.  Elements are between { and } and separated by commas.  Basically, static_array is given the character symbols h, e, l, l, o, and null, making it six elements long.  No additional work is needed and static_array is ready to print.

    The elements of the dynamic array are given the characters in the static array.  First, we find the size of the static_array string (which could be found with "sizeof(static_array) / sizeof(*static_array)", but strlen works too).  Then, we allocate memory and copy over each character, including the null character.  Finally, dynamic is ready to print and must be removed from memory before exiting.

    The quotes are used to create a statically allocated array ending with '\0', which means the quotes array is ready to print.  The quotes also make the array unmodifiable.  Unlike static_array whose elements can be changed and used, the quotes array elements can only be read, not assigned values to.  For example, the value quotes[3] can be assigned to another variable, but "quotes[3] = 'i';" is not valid.

    This type of array is placed in a different part of memory which can only be read from.  It is referred to as a non-volatile, or const, array.  By placing variables in 'const' memory, you allow them to only be given a value once, but that value can be used at any time.  For more information on const variables, check out the page http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html.  Remember that this is a property of the array itself, the variable quotes just happens to point to this array.

    The quotes array is also ready to print without much work.  In fact, the same type of strings are used as the first parameter in the printf commands above because of their easy setup.  The const array strings can also be used in the strlen function to find their length (as well as strings in dynamic arrays).  Like the statically allocated arrays, we do not need to remove them from memory.

    For the final example, here is a program that merges two strings together with sprintf:

#include <stdio.h>  //printf and sprintf
#include <stdlib.h> //malloc and free
#include <string.h> //strlen

//for multiple pointers, each needs an *
char *hello = "hello ", *world = "world!";
char* text; //message to print

int main() {
    int size = strlen(hello);
    size += strlen(world);
    size += 1; //for the null character

    text = (char*)malloc(size * sizeof(char));

    //output goes to string, not prompt
    sprintf(text, "%s%s", hello, world);

    printf(text); //output message
    free(text); //remove from memory

    getchar();
    return 0;
}

output in prompt:
hello world!


    The sprintf function allows us to place a string which would normally print in the prompt and place it into a string array.  Here, the strings hello and world are printed side-by-side and put into the text array.  The sprintf function places a null character at the end automatically, just be sure the array has enough space.

    For more information about C strings, you can read the page http://www.cprogramming.com/tutorial/lesson9.html and see a reference of the functions found in string.h at http://www.cplusplus.com/reference/clibrary/cstring/.  The next post will be about enumerated types and flags, then onto SDL!

Wednesday, July 11, 2012

Pointers in C

    All forms of data in C are assigned an address in memory.  This address allows access to the value or values stored inside which may be read or overwritten with new values.  This concept is key for understanding C, so please check out the pages http://pw1.netcom.com/~tjensen/ptr/pointers.htm, http://boredzo.org/pointers/, and http://www.cprogramming.com/tutorial/c/lesson6.html for truly well-done tutorials.  This tutorial will attempt to demonstrate references and arrays, both of which use pointers.

Reference:
    One way to use pointers is to refer to data stored somewhere in memory.  Each memory address has a numeric value and each variable initialized in C is placed in a numbered address.  You can determine the address of a variable by using the reference operator(&) and assigning the numeric address to a variable called a pointer.

    A pointer can have several types: int*, float*, unsigned short*, char*, etc. all of which are the address of the type and not the type itself.  The following example shows how to use pointers to change variables stored in memory:
#include <stdio.h>

//wait_key prototype
int wait_key();

int main() {
    int a = 5; //int a
    int *b; //int pointer b

    b = &a; //b is given address of a
    *b = 3; //address at b given value

    printf("a = %d\n", a); //a changed

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
a = 3



    The int a is given a value of 5 and the int pointer b is given the address, or reference, of a.  The * in front of b is called the de-reference operator and gives access to the value at the pointer's address.  For this example, 3 is assigned to the value where a is stored, which overwrites the 5 value to 3.

    Pointers can also be input for functions.  Any changes made to the value of a pointer in a function can be seen in other functions, similar to a global variable.  Here is an alternative version of the make_rectangle function from the previous post:
#include <stdio.h>

//alternative name for struct rectangle
typedef struct rectangle rectangle;

//wait_key prototype
int wait_key();

//definition of rectangle data type
struct rectangle {
    int width, height;
};

/* pointer p recieves value of r, set inner
variables found at address p */
void make_rectangle(rectangle* p, int w, int h) {
    (*p).width = w;
    p->height = h; // p-> == (*p).
}

//get inner variables at address p, multiply
int get_area(rectangle* p) {
    int area = p->width;
    area *= (*p).height;
    return area;
}

int main() {
    rectangle r;
    int area;

    //use reference of r as input
    make_rectangle(&r, 4, 5);
    //print changed r
    printf("r: %d x %d\n", r.width, r.height);

    area = get_area(&r);
    printf("area = %d\n", area);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
r: 4 x 5
area = 20


    The function make_rectangle no longer creates and returns a rectangle, instead it modifies an existing rectangle.  A more appropriate name for this version may be set_rectangle, and the name get_area works for the second function since it still returns an integer representing the rectangle area.

    Even though the rectangle r was created in main, its members can be accessed by other functions with the use of a pointer.  This access allows make_rectangle to set the width and height of r, and get_area to use its width and height.

 Array:
    While pointers can be used to access a single value or data type, they can also refer to a collection of many values called an array.  The pointer will refer to the first element of the array and you can access the other elements from it.  Arrays can either be statically or dynamically placed in memory.

    A statically allocated array will remain the same size until the program quits.  The following example will create an array of 5 integers:
#include <stdio.h>

//wait_key prototype
int wait_key();

int main() {
    int index, size;
    int numbers[5]; //five integers

    //assign each integer a value
    for (index = 0; index < 5; index += 1) {
        numbers[index] = 2 * index + 1;
    }

    //make specific changes
    numbers[3] = 6;
    numbers[2] = numbers[3];

    //print values
    for (index = 0; index < 5; index += 1) {
        printf("numbers[%d] = %d\n",
            index, numbers[index]);
    }

    //size of the static array
    size = sizeof(numbers) / sizeof(*numbers);
    printf("# of elements = %d\n", size);

    //numbers points to the first element
    printf("*numbers = %d\n", *numbers);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
numbers[0] = 1
numbers[1] = 3
numbers[2] = 6
numbers[3] = 6
numbers[4] = 9
# of elements = 5
*numbers = 1


    When created, the variable 'numbers' is an array of five integers with five unspecified values.  A simple for loop from 0 to 4 allows us to initialize each element's value using [ and ] around a number.  This index number is how many spaces from the first element you wish to move: 0 is still the first element and moving 4 over gives us the fifth and final element.

    A quick warning: always track how big your array is and avoid using an index number outside the range 0 to (number of elements - 1).  An index beyond these bounds can access other, irrelevant parts in memory and even change them.  Newer operating systems tend to prevent pointers accessing the memory of other programs, but you want to avoid corrupting your own program's data.  One nice feature of static arrays is the ability to find their size.

    The expression "sizeof(numbers) / sizeof(*numbers)" tells us the number of integers in the array variable 'numbers'.  First, we find the size of the entire array in bytes (the sizeof command).  Since integers require 4 bytes, we also divide by the number of bytes a single element requires.  We could also divide by sizeof(int), but the original expression also finds the number of elements for other types of arrays (double, short, etc.).

    Dynamically allocated arrays require an additional header file called stdlib.h (the C standard library).  This additional library includes the commands malloc and free to enable creating and removing arrays at any point during the program.  Aside from these commands, the syntax is similar to static arrays:
#include <stdio.h>
#include <stdlib.h> //malloc and free

//wait_key prototype
int wait_key();

int main() {
    int index, size;
    int *numbers; //pointer to integer

    numbers = (int*)malloc(5 * sizeof(int));
    size = 5;

    //assign each integer a value
    for (index = 0; index < 5; index += 1) {
        numbers[index] = 2 * index + 1;
    }

    //make specific changes
    numbers[3] = 6;
    numbers[2] = numbers[3];

    //print values
    for (index = 0; index < 5; index += 1) {
        printf("numbers[%d] = %d\n",
            index, numbers[index]);
    }

    //numbers points to the first element
    printf("*numbers = %d\n", *numbers);

    //remove old array from memory
    printf("\nfreeing old memory\n");
    free(numbers);

    //create new array in memory
    printf("using new memory\n");
    size = 7;
    numbers = (int*)malloc(size * sizeof(int));

    //create and print values
    for (index = 0; index < size; index += 1) {
        *(numbers + index) = 3 * index - 7;
        printf("numbers[%d] = %d\n", index,
            numbers[index]);
    } //a[b] == *(a + b)

    free(numbers); //free before exiting

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
numbers[0] = 1
numbers[1] = 3
numbers[2] = 6
numbers[3] = 6
numbers[4] = 9
*numbers = 1

freeing old memory
using new memory
numbers[0] = -7
numbers[1] = -4
numbers[2] = -1
numbers[3] = 2
numbers[4] = 5
numbers[5] = 8
numbers[6] = 11

    This version of the numbers array allows you to create an array during any point in the program, but requires more maintenance.  Unfortunately, the size of this type of array cannot be calculated with the sizeof operation.  The sizeof operation will most likely return 4 or 8 which is the number of bytes required to point to a location in memory, not the number of bytes the data occupies.

    Also, the malloc and free commands must be used.  The malloc command is written as "(data type*)malloc(size * sizeof(data type))" where size is the number of elements and data type can be int, double, etc.  malloc checks for and fills available memory and returns a pointer to the first element.  This memory is not initialized though, so assigning values to each element is recommended.

    Once this memory is allocated with malloc, it remains in memory until free is called.  Using the same pointer malloc returns, free will remove an array and make its memory available for other uses.  If free is not called, the array can remain in memory until the computer is restarted.  It is recommended to compliment any malloc calls with a corresponding free call.

    For this example, the numbers array starts with five elements, but is later removed from memory.  Next, it is given seven new elements and finally removed from memory before the program stops.  Aside from malloc and free, the syntax is very similar to static arrays.  Notice that "*(numbers + index)" works similar to "numbers[index]"; this is because the pointer numbers points to the first element while numbers+1 points to the second element.  These written styles can be used interchangeably.

    Pointers can also be used for strings, which will be the next post.  Thank you for reading!