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!

Sunday, June 3, 2012

C Structures

    Interactive applications tend to use a lot of variables.  Functions work as a way to organize commands, but data needs something similar.  Structures in C give you the ability to put several variables of different names in one variable.  This tutorial will cover how to create and use structures.

Creating:
    The written style for creating a structure is "struct name_of_struct {variable declarations;};" where name_of_struct can be replaced with any name you want.  In order to use a structure, we can declare and initialize a variable of the type "struct name_of_struct".  Once this variable is created, it has all the variables from the structure declaration.  Here is an example which creates a structure called circle:
#include <stdio.h>

//wait_key prototype
int wait_key();

//definition of circle variable type
struct circle {
    int x, y;
    double radius;
};

int main() {
    //declaring variables of type circle
    struct circle circle_A;
    struct circle circle_B;

    //set the variables within circle_A
    circle_A.x = 3;
    circle_A.y = 4;
    circle_A.radius = 5;

    //print variables within circle_A
    printf("circle A:\n");
    printf(" x position = %d\n", circle_A.x);
    printf(" y position = %d\n", circle_A.y);
    printf(" radius = %lg\n", circle_A.radius);

    printf("\n");

    //set variables within circle_B
    circle_B.x = 0;
    circle_B.y = 6;
    circle_B.radius = 3;

    //print circle_B variables
    printf("circle B:\n");
    printf(" (x, y) = (%d, ", circle_B.x);
    printf("%d)\n", circle_B.y);
    printf(" radius = %lg\n", circle_B.radius);
  
    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
circle A:
 x position = 3
 y position = 4
 radius = 5

circle B:
 (x, y) = (0, 6)
 radius = 3


    The struct circle declares the integers x and y as well as the double radius.  The variables circle_A and circle_B are of type struct circle, which means they both have x and y integers as well as a radius double.  The amount of variables and their names can be changed, but for this example circle_A and circle_B are used.

    Now that the circle variables are created, we must initialize all of their inside variables (x, y, and radius).  You can access the inside variables of a circle variable with circle_name.variable_name (circle_A.x for example).  This allows you to assign values to them and access their current values.  This example gives them values and prints them.

    In order to create a variable of type circle, we use struct circle variable_name; but the struct in front may seem redundant or unnecessary.  Many C programmers will use a work-around to avoid using struct which requires the typedef command.

Typedef'ing:
    The typedef command in C lets you invent new names for existing data structures.  For example, if you wanted to use the term uint for unsigned int, the command typedef unsigned int uint; would make this possible.  For structures, you can use typedef to remove the struct term in front of struct circle variables:
#include <stdio.h>

//create alternative names for data types
typedef struct circle circle;
typedef double real;

//wait_key prototype
int wait_key();

//definition of circle variable type
struct circle {
    int x, y;
    real radius; //is really a double
};

int main() {
    //declare circle_A of type circle
    circle circle_A;

    //assign values to inner variables
    circle_A.x = 0;
    circle_A.y = 2;
    circle_A.radius = 1;

    //print inner variables
    printf("circle_A:\n");
    printf(" centered at (%d, ", circle_A.x);
    printf("%d)\n", circle_A.y);
    printf(" radius of %lg\n", circle_A.radius);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
circle_A:
 centered at (0,2)
 radius of 1


    Now the variable circle_A only needs the type circle in front of it.  This was accomplished with the typedef struct circle circle; command which made the term "circle" the equivalent of "struct circle".  The "struct circle" term can still be used, but this example should demonstrate the ease of using just "circle".

    Double has also been given a synonym of "real" for this example since doubles are real numbers.  The radius of type double can now be given the type real due to the command typedef double real;.

Structures in functions:
    Custom data types like circle can be used in functions.  Structures can be both the input and output of a function, which means a function can technically return more than one number if a structure is used.  The following example has functions which use a rectangle struct:
#include <stdio.h>

typedef struct rectangle rectangle;

//wait_key prototype
int wait_key();

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

//a function which initializes inner variables
rectangle make_rectangle(int width, int height) {
    rectangle output;
  
    output.width = width;
    output.height = height;

    return output;
}

//returns the area of a rectangle
int get_area(rectangle input) {
    int area = input.width * input.height;

    return area;
}

int main() {
    //create two rectangles
    rectangle A = make_rectangle(2, 1);
    rectangle B = make_rectangle(1, 1);

    //get their areas
    int area_A = get_area(A);
    int area_B = get_area(B);

    //print the areas
    printf("Area of A = %d\n", area_A);
    printf("Area of B = %d\n", area_B);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
area of A = 2
area of B = 1

    This rectangle struct is simpler than the circle struct; it can be improved by adding x and y coordinates and possibly a rotation angle.  The function make_rectangle requires a width and height for input and returns a rectangle with inner variables set to the input.  The function get_area uses a rectangle input and calculates its area based on the inner variables.

    You are free to create all sorts of structures which may not necessarily be shapes.  For more information on structures, the page http://roseindia.net/c-tutorials/c-structure.shtml provides a student structure and http://www.cprogramming.com/tutorial/lesson7.html has a database example.

    The next post will cover pointers, arrays, and strings.

Saturday, May 26, 2012

Loops in C

    We've discussed conditional commands, which may or may not be performed, but loops allow commands to be repeated many times.  Interactive applications wait for user input, process the input, output the results, and repeat in a loop until the user quits.  Three types of loops found in C are the while loop, the do-while loop, and the for loop.

While loop:
    The syntax for this loop is the simplest and allows the other loops to be built from it.  The syntax is "while (logic test) {commands;}", where logic test and commands are replaced by real code.  If the logic test is true, the commands are executed and the logic test is again tested.  This continues until the logic test is false.

    The following example should print a statement three times, wait for user input, then exit:
#include <stdio.h>

//wait_key prototype
int wait_key();

int main() {
    int cycles_performed = 0;
    int cycles_to_do = 3;

    while (cycles_performed < cycles_to_do) {
        printf("cycle %d\n", cycles_performed);
        cycles_performed = cycles_performed + 1;
        //go back to logic test
    }

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
cycle 0
cycle 1
cycle 2

    To demonstrate how this works, let's run through the code.  The variable cycles_performed starts at 0 and we enter the while loop.  0 < 3, so we print and add 1 to cycles_performed. 1 < 3 also, so we print again and add 1 to cycles_performed.  Finally, 2 < 3 so we print and add 1 to arrive at the logic test 3 < 3.  Since 3 < 3 is false, the loop is done and the next statement is return wait_key();.

    Were you to switch the order of the printing and adding one commands, the output would start from cycle 1 and go to cycle 3.  The print command is still called three times, but the variable can be updated before the print in that case.  One loop that demonstrates the order of commands well is the do-while loop.

Do-while loop:
    Similar to the written style of the while loop, the do-while loop requires commands and a logic test.  The syntax is "do {commands;} while (logic test);" and has one key difference when compared to the while loop: the test is performed after the commands.

    If the logic test for a while loop is false, the commands will not be performed.  However, a do-while loop guarantees that the commands will be performed at least once.  The following example shows a possible side-effect of this command order:
#include <stdio.h>

//wait_key prototype
int wait_key();

int main() {
    int number = 4;

    while (number == 5) { //test first
        printf("while loop cycle\n");
        number = number + 1;
    }

    do { //test after a cycle
        number = number + 1;
        printf("do-while loop cycle\n");
    } while (number == 5);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
do-while loop cycle
do-while loop cycle

    The commands in the while loop are never called because 4 != 5.  For the do-while loop though, one cycle is performed and number is increased to 5.  Since 5 == 5, another cycle is performed and the loop ends because number is now 6 and 6 != 5.

    The do-while loop is the only loop which tests after a first cycle through the commands.  The equivalent for a while loop would be "commands; while(logic test) {commands;}", so the do-while loop can save some typing if you want to ensure the commands run once.

for loop:
    The final loop to discuss is the for loop.  The syntax requires more than a logic test: "for (initial command; logic test; cycle command) {commands;}".  The initial command is run once before the loop starts and the cycle command is run at the end of each loop, before the logic test.

    In previous examples, variable = variable + 1 was used to make the logic test false after a number of cycles.  This command is often used in the for loop as the cycle command, and setting the variable's value before the loop can be done in the initial command.

    For example, for (number = 0; number < 3; number = number + 1) {printf("hello\n";} will set the integer number to zero once, print "hello" and a newline, add one to number, then try the logic test.  If the logic test is true, it will print "hello" again, add 1 to number, and try the logic test again.

    The following example shows a for loop with some additional features:
#include <stdio.h>

//wait_key prototype
int wait_key();

int main() {
    int number;

    /*without break or continue, this loop
    would print 20 times*/
    for (number = 0; number < 20; number += 1) {
        if (number == 5) continue;
        printf("cycle #%d\n", number);
        if (number == 10) break;
    }

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
cycle #0
cycle #1
cycle #2
cycle #3
cycle #4
cycle #6
cycle #7
cycle #8
cycle #9
cycle #10


    This example attempts to show the commands continue and break.  The break command was used in switch statements to exit the switch statement.  For loops, break does the same thing; in this case, when number is 10, the loop is broken and the return wait_key(); command is called.  While loops and do-while loops can also use the break statement to exit.

    The continue command in a for loop means commands from that point are no longer called, the cycle command number += 1 is called, and the logic test is run.  Notice that cycle #5 is not printed: this is because continue is called before the print statement.  However, cycle #10 is present because break is called after the print command when number is 10.

    The command number += 1; is a shortened version of number = number + 1.  This applies to subtraction(-=), multiplication(*=), division(/=), modulo(%=), and bitwise operators.  If number == 7, then number *= 5 changes the value of number to 35 since this is the equivalent of number = number * 5 (or 7 * 5).

    For loops can be converted into while loops with the form "initial command; while(logic test) {commands; cycle command;}".  However, if you call continue in this while loop, the cycle command is not called because it is a while loop.

    For more information about loops in C, check the pages http://www.codingunit.com/c-tutorial-for-loop-while-loop-break-and-continue and http://www.cprogramming.com/tutorial/c/lesson3.html.

    The next post will be about structures and custom data types.  Thank you for reading :)

Sunday, May 20, 2012

Logic and Conditions in C

    In C, logic allow your commands to change if certain conditions are met, making them a bit smarter.  This tutorial will attempt to discuss how to use the logic found in C.  It will cover the if statement, logic operators, and the switch statement.

If and else statements:
    The most common way to use logic is the if statement.  This is present in other languages as well, but the syntax in C is "if (logic test) {commands;}".  The terms "logic test" and "commands" are replaced with your own code in this case.  Commands can be functions, arithmetic, printing, waiting, etc.

    The logic test will be either true or false.  If is is true, the commands will be executed; but if it is false, the commands are skipped entirely.  In order to create a statement which is true or false for numbers, use the following comparison tests: is equal to, is not equal to, is less than, is greater than, is less than or equal to, is greater than or equal to.

    These are comparison operators in C: ==, !=, <, >, <=, >= (listed in same order as mentioned before).  They require a number on both sides and give a true or false result.  For example, 5 == 7 gives us false, but 5 != 7 is true.  The following example shows how to use the if statement:
#include <stdio.h>

//wait_key prototype
int wait_key();

int main() {
    int x = 7, y = 5;

    if (x > y) {
        printf("x > y");
    }
    else {
        printf("x <= y");
    }

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
x > y

    Here, x is greater than y and the command printf("x > y"); is performed.  However, the command printf("x <= y"); does not occur because the comparison test was true.  This is not all to this example though; if you were change the value of x to 3 and y to 8, the output would say x <= y.

    Else means the opposite of the comparison test.  If x is not greater than y, x can only be less than or equal to y.  In this case, else could have been replaced with if (x <= y) since > and <= are opposite tests.  < and >= are opposites tests too, as well as the == and != operators.

    If and else allow commands for two cases: the comparison and its opposite, but what about functions where three or more possibilities can occur?  For example, what about a function that says if input is 3 or 7 or another number?  The following example shows a function that does just that:
#include <stdio.h>

//wait_key prototype
int wait_key();

void checkInt(int input) {
    if (input == 3) {
        printf("input is 3\n");
    }
    else if (input == 7) {
        printf("input is 7\n");
    }
    else {printf("input not 3 nor 7\n");}
}

int main() {
    int a = 3, b = 5, c = 7;

    checkInt(a);
    checkInt(b);
    checkInt(c);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
input is 3
input not 3 nor 7
input is 7


    The keyword "else if" is the equivalent of another if statement.  The reason I do not just use if is that "else if" affects else: now else is for cases where input != 3 and input != 7.  The else statement has become more complex, but can still be replaced with an if statement.

Logical operators:
    To make logic more interesting, C has operators which use comparison tests as input and output true or false.  They can be placed inside an if statement to account for more possibilities.  The operators are logical and(&&), logical or(||), and logical not(!).

    The logical and and or operators use symbols similar to bitwise and and or.  This is no coincidence: the logical operators treat true as a 1 bit and false as 0.  Here is a table to show how logical or and and work:
comparison testcomparison testlogical and(&&)logical or(||)
(5 == 7) false(5 == 7) falsefalsefalse
(5 == 7) false(5 == 5) truefalsetrue
(5 == 5) true(5 == 7) falsefalsetrue
(5 == 5) true(5 == 5) truetruetrue


    To clarify, the commands within if ((5 == 7) && (5 == 5)) { will never be executed.  This table is very similar to the bitwise table from the operators post, http://multimediaprogram.blogspot.com/2012/05/c-operators.html, except that there is no logical xor.

    Logical not works much like bitwise not: !(5 == 5) is false and !(5 == 7) is true.  In fact, !(5 == 5) is the equivalent of (5 != 5).  The comparison test becomes the opposite, so !(x > y) becomes (x <= y).

    Here is an example of how to use these operators effectively: if ((x != 3) && (x != 7)) { can replace the else statement from the previous code example.  This is not limited to equalities though, you can also test if a number is within a certain range:
#include <stdio.h>

//wait_key prototype
int wait_key();

void checkRange(int input) {
    if (input > 0 && input <= 10) {
        printf("input is 1 to 10\n");
    }
    else {
        printf("input is not 1 to 10\n");
    }
}

int main() {
    int a = -1, b = 5, c = 7;

    checkRange(a);
    checkRange(b);
    checkRange(c);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
input is not 1 to 10
input is 1 to 10
input is 1 to 10


    The function checkRange will tell us whether a number is within the range 1 to 10.  This is accomplished with two comparison tests and logical and.  The else statement for this example would be if (!(input > 0 && input <= 10)) { which can also be if (input <= 0 || input > 10) { since these two are logically the same.

Switch statement:
    The last concept of logic to discuss is a switch statement.  The logic is pretty tame, but the written style can be messy.  The format starts with switch (variable) {, where variable is any variable you choose.  Next, there is case value:, where value is any value, which is followed by commands.

    One way to use this statement is to revisit the checkInt function, which checks for input equal to 3 or 7 or something else:
#include <stdio.h>

//wait_key prototype
int wait_key();

void checkInt(int input) {
    switch (input) {
    case 3: //if (input == 3)
        printf("input is 3\n");
        break;
    case 7: //else if (input == 7)
        printf("input is 7\n");
        break;
    default: //else
        printf("input not 3 nor 7\n");
        break;
    }
}

int main() {
    int a = 3, b = 5, c = 7;

    checkInt(a);
    checkInt(b);
    checkInt(c);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
input is 3
input not 3 nor 7
input is 7



    The goal of this example is to show that this checkInt and the previous version perform the same task.  The if, else if, and else are included as comments here, so they are not part of the switch statement.  These comments attempt show that the first case is basically the if statement if (variable == value) {.  Any additional cases are the else if statement else if (variable == value) {.

    Finally, default is the equivalent of else.  Each case performs similar commands found in the original checkInt, but with the added break command.  Break is a command which exits the switch statement after the commands of a case are performed and is necessary for a proper switch statement.

    For more information about the switch statement, check out the C programming tutorial http://www.cprogramming.com/tutorial/lesson5.html.  For more about if and logic, try the page http://www.cs.utah.edu/~zachary/computing/lessons/uces-11/uces-11/node9.html.

    The next tutorial will cover loops (with more examples of break).

Thursday, May 17, 2012

C Functions

    I imagine your programs will need much more code than used so far, especially for a working game.  However, one problem we face is a larger and unorganized main function.  Also, some commands must be performed outside of main, so custom functions will help a lot.  We will talk about output, input, and prototypes of functions.

output:
    You may remember from the C basics post, http://multimediaprogram.blogspot.com/2012/05/c-basics.html, a talk of how to declare functions.  To reiterate, the syntax to create a function which returns an integer and has no parameters is int functionName(), which is followed by a {, commands, and a closing }.

    Like in main, a function which returns an integer needs a return statement.  For main, return 0; indicates the end of main with a success (or the 0 code).  Here is an example of a custom function which returns five:
#include <stdio.h>

int five() {
    return 5;
}

int wait_key() {
    getchar();
    return 0;
}

int main() {
    int x = five();
    printf("x = %d\n", x);

    return wait_key();
}
output in prompt:
x = 5

    The function five shown above returns 5.  By changing the command return 5; to return 10; the function's output would become 10, but the function would still be named five.  The wait_key function has also been brought back and updated; here, it returns the exit code to main, which then returns the output of wait_key.

Input:
    As you have learned in math class, functions also have input.  Think of y = f(x), y is assigned the output of the function f and x is the input of the function.  To begin creating f, start with double f() { since real numbers are often used in mathematics.  Now that input is required, the declaration of the function will change: double f (double x) {.

    The added double x tells C that the function f requires one double as input.  When calling the function f, you do not need to initialize x, since this has already been done in the declaration; all that is required is a value to pass to x.  Here is an example of the function f declared and called:
#include <stdio.h>

/*function f requires one double
as input and returns one double*/
double f (double x) {
    double output;
    output = 2 * x + 1;
    return output;
}

//no input required, returns int 0
int wait_key() {
    getchar();
    return 0;
}

//the main function
int main() {
    double x = 7, y;
    y = f(x); //call function f

    printf("f(%lg) = %lg\n", x, y);

    //call wait_key and return output
    return wait_key();
}
output in prompt:
f(7) = 15


    There are two variables named x in this example: while C does not allow two variables of the same name, this only applies to variables of a given function.  The function main has variables x and y while f uses x and output, so x can exist in two different functions.

    Modifying x in f does not modify x in main, since they are two different variables.  In fact, passing the value of main's x to f's x and vice versa is also acceptable.  But what if we want one x that can be modified everywhere, without passing through functions?  We would use global variables.

    The following example is the same code above with a global variable called x:
#include <stdio.h>

//x is now recognized by all functions
double x;

double f () { //no need to pass a value
    double output;
    output = 2 * x + 1;
    return output;
}

int wait_key() {
    getchar();
    return 0;
}

int main() {
    double y;

    x = 7; //set value of x
    y = f();

    printf("f(%lg) = %lg\n", x, y);

    return wait_key();
}
output in prompt:
f(7) = 15


    Global variables are declared underneath the #include commands and before function declarations.  Some changes to the example include no initializing x in main or passing its value to f (which now has no parameters).  Since x is recognized by all functions, we cannot name a variable x in any functions.

    Optionally, the function f could modify the global variable x and the effect could be seen in the main function.  If the statement x = x + 1; were placed in f, main would recognize the change in x from 7 to 8 after the function f is called.

Prototypes:
    All of the functions so far have been declared before the main function.  This is because a function must be defined first before being used.  However, one work-around is to create a function prototype which is the output type, name, and input of a function without any of the commands (which are added later).

    The following example shows a few prototypes in action:
#include <stdio.h>

//function prototypes
double add (double, double);
int wait_key();

/*prototypes do not need names for the
input, just types.  The names can be
provided in the definition*/

int main () {
    double x = 5, y = 8;
    double z = add(x,y);

    printf("%lg + %lg = %lg\n", x, y, z);

    return wait_key();
}

//now functions can be defined after main

double add(double a, double b) {
    return a + b;
}

int wait_key() {
    getchar();
    return 0;
}  
output in prompt:
5 + 8 = 13


    The function add is first defined in the form of a prototype which uses variable types without names, then with a regular function definition.  The key difference between this example and previous ones is that function definitions for add and wait_key can be placed anywhere in relation to main.

    Also, the function add accepts two parameters which are separated by a comma.  You are free to define a function with any arbitrary number of parameters and commands, but there can only be one type of output (unless you count modifying global variables).

    For more information about functions, the link http://www.tutorialspoint.com/ansi_c/c_using_functions.htm can provide some insight.

    The next post will discuss conditions and logic.