CSC270 October 7 Tutorial: Useful C for Assignment 2




Multidimensional arrays

[ King 8.2 ] To create a two-dimensional array of type T: T array[dim1][dim2]; This array is stored in the variable `array' and has dimensions `dim1 x dim2'. You can think of the dimensions as - rows and columns, or - x and y, or - anything else To initialize an array: int arcs[ MAX_ROWS ][ MAX_COLS ]; for (i=0; i < MAX_ROWS; i++) for (j=0; j < MAX_COLS; j++) arcs[i][j] = -1; Note that the subscripts are separate like `arcs[i][j]'. Do not combine them like `arcs[i,j]'.

Arrays as function arguments

If you declare an array as int a[ DIM1 ][ DIM2 ]; then any function that takes it as a parameter should have a declaration in the parameter list like void f( int a[ DIM1 ][ DIM2 ] ) The array dimensions should be included in the parameter list! While this is not always necessary, it's easy to remember this rule and it doesn't hurt. For one-dimensional arrays, there are two methods of defining the parameters. If the array is declared as int a[ DIM ]; You can use either of these parameter forms: void f( int a[ DIM ] ) void f( int *a ) We'll talk next week about pointers (the *) and why the second form works.

Dynamic allocation of one-dimensional arrays

[ King 17.3 ] You'll need to allocate one-dimensional arrays dynamically when you convert between graph representations in Assignment 2. If you don't know the array size before the program starts, the array has to be allocated `dynamically'. Normally, you would define an array of KNOWN size as int nodes[ NUM_NODES ]; But if the `nodes' array is of unknown size you would define it as int *nodes; (This says that `nodes' is a `pointer to int'. We'll discuss pointers in the next tutorial. For now, use this as a template for dynamic array allocation.) If you find that the array has some size, say `n', then you can create an array of n ints as nodes = (int *) malloc( n * sizeof(int) ); Now `nodes' can be treated just like any array of n ints. For example, for (i=0; i < n; i++) nodes[i] = -1; WARNING: The elements of the array are not initialized to any particular values! They don't usually contain zeroes, so you have to initialize the array yourself. This is also true of arrays of known size defined before compilation.

Structs

[ King 16.1, 16.2, 16.3 ] An array is a collection of elements which are - all of the same type - referred to by an index A `structure' is a collection of elements which are - of possibly different types - referred to by a name A structure usually stores a collection of related items. A poor implementation of a string would store an array of characters and a length: struct { int length; char str[100]; } string1, string2; This statement defines two variables, `string1' and `string2'. Each variable contains two components called `length' and `str'. To refer to the components, we use the dot notation. In general, the form is variable_name.field_name Each component of the structure is called a `field'. For example, to initialize the strings (which don't have a terminating '\0' character, since the length field gives this information): string1.length = 2; string1.str[0] = 'x'; string1.str[1] = 'y'; for (i=0; i < NUM_BLANKS; i++) string2.str[i] = ' '; string2.length = NUM_BLANKS;

Arrays of structs

Note that an array can be a component of a structure. Similarly, we can have an array of structures: struct { int index; int num_adj_nodes; int adj_nodes[100]; } nodes[20]; This defines an array of 20 nodes, where each node is a structure with three fields: index, num_adj_nodes, and adj_nodes. This structure could store a node in a graph and the indices of adjacent nodes (`adj' stands for `adjacent'). In the code below, every node is made adjacent to node 0: for (i=0; i < 20; i++) { nodes[i].index = i; nodes[i].num_adj_nodes = 1; nodes[i].adj_nodes[0] = 0; }

Making your own structure types

It's tedious to type the whole structure definition every time you want to declare a new variable. C allows you to avoid this by defining a new type that is a structure: typedef struct { int index; int num_adj_nodes; int adj_nodes[100]; } NODE; This is a definition of a TYPE called `NODE'. It is NOT a declaration of a variable called `NODE'. Typically, people use uppercase letters or a Capitalized Word for their own type names. It helps when reading the program. After defining a new type, you can use it wherever you want: NODE a, b, c; NODE nodes[20]; These statements declare three variables -- a, b, and c -- of the NODE type, along with an array of 20 nodes. Much cleaner code is produced if you make the appropriate typedefs like this. Such variables are used in the normal way: a.index = 0; a.num_adj_nodes = 0; nodes[5].index = 5; nodes[5].num_adj_nodes = 1; nodes[5].adj_nodes[0] = 1;