Initializing, Indexing, and Passing Arrays

First, let’s review how to declare and define arrays. An array must be declared and defined before it can be used. The size of the array is a constant.

#include <stdio.h>

int main(void){

    //each element in the array
    //must be of the same type
    int testScores[10];
    double gpa[30];

    char name[50];

    //use an index of zero
    //to access the first element
    testScores[0] = 1138;

    printf("%d\n", testScores[0]);

    return 0;
}

The declaration and definition of an array tells the compiler the name of the array, the type of each element, and the number of elements in the array. Since an array depends on having its elements occupy consecutive memory locations, once the array size has been set in cannot be resized, as memory immediately following the location of the last element may have already been allocated.

It is possible to use a variable or an expression as the index of an array.

#include <stdio.h>

int main(void){

int i = 0;
double nums[10];

for(i = 0; i < 10; i++){
nums[i] = i + 1;
nums[i] += i / 7.0;
}

i = 0;

while(i < 10){
printf("%f\t", nums[i++]);
}

return 0;

}//end main()

An array’s name is functionally a symbolic reference to the memory location of the first element in the array. The index represents an offset from the first element in the array to the element being referred to; thus, the first element is at index 0, not 1.

Initialization of all elements in an array can be done at the time of declaration, just as with variables. Our initialization values must be placed within curly braces and, if there is more than one, separated by commas.  If the number of values provided is less than the number of elements in the array, the unassigned elements are filled with zeros.

#include <stdio.h>

int main(void){

    int i = 0;
    int intExmp[10] = {5, 9, 14, 23, 37};

    for(i = 0; i < 10; i++){
        printf("%d\n", intExmp[i]);
    }

    return 0;

}

Note that while we can assign individual elements using the assignment operator, we cannot assign entire arrays in one step. Instead, we must copy arrays by looping through each element. It is also quite common to exchanged array elements; this is a major part of sorting algorithms.

We can pass individual elements to function like any other variable. Of course, the element will be passed by value, not by reference, unless we use pointers.

#include <stdio.h>


void switchValues(int *a, int *b);

int main(void){

    int array01[10];
    int array02[10];

    int i = 0;
    int j = 0;
    int k = 0;

    for(i = 0; i < 10; i++){
        array01[i] = i * 2;
    }

    for(i = 0; i < 10; i++){
        array02[i] = array01[i] + 1;
    }

    for(i = 0; i < 10; i++){
        printf("%3d %3d\n", array01[i], array02[i]);
    }

    //move value stored at beginning of the array
    //down the array to the last element
    for(i = 0; i < 9; i++){
        switchValues(&array02[i], &array02[i+1]);
    }

    for(i = 0; i < 10; i++){
        printf("%5d", array02[i]);
        putchar('\n');
    }

    //reverses the values in the array
    for(i = 0, j = 9; i < 9; i++, j--){
        //each loop we shift the value stored
        //in the first element, 0,
        //to the last element in the array
        //minus one for each time we have looped
        for(k = 0; k < j; k++){
            switchValues(&array01[k], &array01[k+1]);
        }
        int x = 0;
        //print out changes to array so far
        for(x = 0; x < 10; x++){
            printf("%5d", array01[x]);
        }
        putchar('\n');
    } //end outer for loop



    putchar('\n');

    return 0;

}//end main()

void switchValues(int *a, int *b){
    int temp; //temp value to store

    temp = *a;
    *a = *b;
    *b = temp;

}//end switchValues()

Bear in mind that the C language does not check the boundary of an array. Is is our job to ensure that all references to indexed elements are valid and within the boundaries of the array.

#include <stdio.h>

#define ARRAY_MAX 50

int main(void){
    
    int i = 0;
    int numToRead = 0;
    int numbers[ARRAY_MAX];
    
    
    printf("You can enter up to %d whole numbers:\n", ARRAY_MAX);
    printf("How many would you like to enter?\t");
    scanf(" %d", &numToRead);
    
    if(numToRead > 50 || numToRead < 0){
        numToRead = 50;
    }
    
    while(i < numToRead){
        printf("Enter value for element %d:\t", i);
        scanf(" %d", &numbers[i++]);
    }
    
    printf("Printing these numbers backwards:\n");
    
    for(i = numToRead-1; i >= 0; i--){
        printf("%5d ", numbers[i]);
    }
    
    
    
}//end main()

Unlike when passing an array element, when we pass the whole array we pass the array automatically by reference, due to the fact that the array name devolves to a pointer to the initial array element. All we need to do is use the array name as the function’s argument.

 

 

 

Advertisements

Two-Dimensional Arrays in C

Arrays can be initialized on their declaration. This initialization takes place when the program is loaded.  The list of initializers should be enclosed in curly braces, and each element must be separated by commas.

#include <stdio.h>


int main(void){
    
    int i;
    
    short smallNums[] = {1, 5, 11, 13, 17, 23};
    int largerNums[7] = {42, 47, 73, 404, 808, 2600, 40000};    
    //shorthand for string array
    char aString[] = "I can't do that, Dave.";
    
    printf("%s\n", aString);
    
    
    //use sizeof() to get array size
    for(i = 0; i < sizeof(smallNums)/sizeof(smallNums[0]); i++){
            printf("%d\t", smallNums[i]);
    }
    
    return 0;
}

Note that if no size of the array is given when initializing the array, the bound is taken to be the number of initializers.

Two-dimensional arrays are often called rectangular arrays, as their structure resembles that of a two-dimensional grid such as seen on a spreadsheet.

#include <stdio.h>


int main(void){
    
    //number of horizontal rows
    const int Row_Size = 10;
    //number of vertical columns
    const int Column_Size = 5;
    
    int twoDimArray[Row_Size][Column_Size];
    
    //sizeof() returns unsigned long
    printf("Size of twoDimArray = %lu\n", sizeof(twoDimArray));
    
    int size = Row_Size * Column_Size * sizeof(int);
    
    printf("Size of twoDimArray = %d\n", size);
    
    printf("Size of one row in twoDimArray = %lu\n", sizeof(twoDimArray[0]));
    
    size = Column_Size * sizeof(int);
    
    printf("Size of one row in twoDimArray = %d\n", size);
    
    return 0;
}

Note that the elements in a two-dimensional array are stored in row-major order, meaning that each row forms an array of elements in memory. Technically speaking, each row is itself a one-dimensional array, and can be used as such.

#include <stdio.h>


int main(void){
    
    int intArray[3][5];
    
    int i, j;
    
    //use nested for loop
    //to assign values to each
    //array element
    for(i = 0; i < 3; i++){
        for(j = 0; j < 5; j++){
            intArray[i][j] = 1 + i + j;    
        }
    }
    
    //print out last row of array
    for(i = 0; i < 5; i++){
        printf("%d\t", intArray[2][i]);
    }
    
    return 0;
}

We can use arrays to recreate the famous Towers of Hanoi puzzle. In this puzzle there are three vertical pegs onto which are placed disks of varying sizes. At the start of the puzzle, all of the disks are placed in hierarchical order from largest to smallest on the leftmost peg. We can move a disk onto another peg only if every disk on that peg is larger than it. The goal is to move all of the disks to the rightmost peg.

This puzzle is typically used in computer science courses as a visual aid to thinking of how the stack data structure works. Each stack of disks is like a programming stack, since items can only be removed or added to the top of the stack.

#include <stdio.h>

const int num_disks = 3;

int pop(int i, int pegs[3][num_disks], int numDisks[]);
void push(int i, int disk, int pegs[3][num_disks], int numDisks[]);
void dumpPegs(int pegs[3][num_disks], int numDisks[]);
void moveDisk(int source, int destination, int pegs[3][num_disks], int numDisks[]);

int main(void){
    
    int pegs[3][num_disks] = {0};

    //number of disks on each peg
    int numDisks[3] = {0};
    
    push(0, 3, pegs, numDisks);
    push(0, 2, pegs, numDisks);
    push(0, 1, pegs, numDisks);
    
    dumpPegs(pegs, numDisks);
    
    moveDisk(0, 2, pegs, numDisks);
    
    dumpPegs(pegs, numDisks);
    
    moveDisk(0, 1, pegs, numDisks);
    
    dumpPegs(pegs, numDisks);
    
    moveDisk(2, 1, pegs, numDisks);
    
    dumpPegs(pegs, numDisks);
    
    moveDisk(0, 2, pegs, numDisks);
    
    dumpPegs(pegs, numDisks);
    
    moveDisk(1, 0, pegs, numDisks);
    
    dumpPegs(pegs, numDisks);
    
    moveDisk(1, 2, pegs, numDisks);
    
    dumpPegs(pegs, numDisks);
    
    moveDisk(0, 2, pegs, numDisks);
    
    dumpPegs(pegs, numDisks);
    
    return 0;
}


void moveDisk(int source, int destination, int pegs[3][num_disks], int numDisks[]){
    int disk = pop(source, pegs, numDisks);
    push(destination, disk, pegs, numDisks);
}

void push(int i, int disk, int pegs[3][num_disks], int numDisks[]){
    if(i >= 0 && i <= 2){
        pegs[i][numDisks[i]++] = disk;
    }
}

int pop(int i, int pegs[3][num_disks], int numDisks[]){
    if(i >= 0 && i <= 2){
        if(numDisks[i] >= 1){
            return (pegs[i][--numDisks[i]]);
        }
    }
    return -1;
}

void dumpPegs(int pegs[3][num_disks], int numDisks[]){
    int i,j;
    
    for(i = 0; i < 3; i++){
        for(j = 0; j < num_disks; j++){
            if(j < numDisks[i]){
                printf("%d", pegs[i][j]);
            } else {
                putchar(' ');
            }
        }
        putchar('\t');
    }
    putchar('\n');
}

This example above provides a brute-force solution to the puzzle if there are three disks. But what if there are four disks? Or five? In that case, we should use a recursive function. But that is for another time.

 

Arrays and Strings in C

An array is an indexed list of variables of the same type that are referred to by a shared name. A specific variable in the array is accessed via its index number. In C, all arrays consist of contiguous memory locations, which means that we can also access array elements via pointer arithmetic. The lowest address stores the first array element, and the highest address stores the last element. Suffice to say, arrays and pointers are closely related.

One common type of array is the string, which is a char array terminated by the null character.

As with other variables, arrays must be declared so that the compiler can allocate space for them in memory.

#include <stdio.h>

int main(void){
    
    
    //declare double type array
    double bubble[10];
    
    //declare int type array
    int intArray[50];
    
    bubble[0] = 7.976;
    bubble[1] = 2.352;
    
    printf("bubble[0] = %f\n", bubble[0]);
    printf("bubble[1] = %f\n", bubble[1]);
    
    return 0;
    
}

As we have seen, an element is accessed by indexing the array name, which is done by placing the number of the element’s location in the array within square brackets after the name of the array. Note that in C, all arrays have 0 as the index of their first element.

#include <stdio.h>

int main(void){
    
    int ints[50];
    
    int i;
    
    //assign values to
    //every element in ints array
    for(i = 0; i < 50; i++){
        ints[i]=i+1;
    }
    
    //display contents of array
    for(i=0; i < 50; i++){
        printf("%d\t", ints[i]);
    }
    
    putchar('\n');
    
    return 0;
    
}

Note that C has no bounds checking on arrays.

The amount of memory required to hold an array is directly related to its type and size. For a single-dimension array, the total size in bytes is the length of the array multiplied by the size of the base type of the array.

We can create a pointer to the first element in an array by specifying the array name without any sort of index.

#include <stdio.h>

int main(void){
    
    int i = 0;
    int *ptr;
    int sample[25];
    
    ptr = sample;
    
    sample[0] = 1;
    for(i = 1; i < 25; i++){
        sample[i] = i + sample[i-1];
    }
    
    i = 0;
    
    //use pointer arithmetic
    //to access array elements
    while(i++ < 25){
        printf("%d\n", *ptr++);
    }
    
    return 0;
}

We cannot pass an entire array as an argument to a function. We can, however, pass a pointer to an array by specifying the array’s name without an index. We can declare the array as a function parameter in three different ways: as a pointer, as a  sized array, or as an unsized array.

#include <stdio.h>
#define SIZE 50

//two void functions
//one to assign values
//one to print values
void assignValues(double array[SIZE]);
void printValues(double *arrayPtr);

//one void function to modify values
void modifyValues(double array[]);

int main(void){
    
    double trouble[SIZE];
          
    assignValues(trouble);
    
    printValues(trouble);
    
    printf("\nafter modifying values in array...\n");
                
    modifyValues(trouble);
    
    printValues(trouble);
    
    return 0;
    
}

void assignValues(double array[SIZE]){
    
    int i;
    double var = 0.0;
    
    for(i = 0; i < SIZE; i++){
            var = i / 1000.0;
            array[i] = (i-(SIZE/2)) + var;
        }
}

void printValues(double *arrayPtr){
    int i = 0;
    while(i < SIZE){
        printf("%.8f\n", *(arrayPtr + i));
        i++;
    }
}

void modifyValues(double array[]){
    int i;
    for(i = 0; i < SIZE; i++){
        array[i] = array[i] / (i+1) + i;
    }
}

One dimensional arrays are often used as strings. A string is a null-terminated character array. Note that when declaring a character array that will hold a string, we must declare it to be one character longer than the largest string that it will hold.

#include <stdio.h>


int main(void){
    
    int i;
    char lowerCase[27];
    char upperCase[27];
    
    lowerCase[0] = 'a';
    upperCase[0] = 'A';
    
    for(i = 1; i < 26; i++){
        lowerCase[i] =  lowerCase[0] + i;
        upperCase[i] = upperCase[i-1] + 1;
    }
    
    //assign null terminator
    //to ends of the string
    lowerCase[26] = '';
    upperCase[26] = '';
    
    //print strings using
    // %s conversion specifier
    printf("Lower Case Letters: %s\n", lowerCase);
    printf("Upper Case Letters: %s\n", upperCase);
    
    
    return 0;
}

We can use the fgets() function to acquire a string from standard input. The fgets() function takes three arguments: the char array, the size of the char array, and where to get the input from. Since we will be taking the input from the user, we will specify stdin as the source of input.

#include <stdio.h>

int main(void){
    
    const int buffer = 256;
    
    char string1[buffer];
    char string2[buffer];
    
    printf("Enter a string: ");
    
    fgets(string1, buffer, stdin);
    
    printf("Enter another string: ");
    
    fgets(string2, buffer, stdin);
    
    printf("%s", string1);
    
    printf("%s", string2);

    return 0;
    
}

Interested in learning more?

Take a look at this book on C: http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M/

Arrays as Arguments to Functions

Passing an argument to a function becomes more complicated when the argument is an array.  When we pass an array as an argument, the argument does not receive the contents of the array. Instead, the address of the initial element of the array is passed.

#include <stdio.h>
#define ARRAYSIZE 5

void printArray(int array[]);

int main(void){
    
    int array[ARRAYSIZE] = {3, 9, 27, 81, 243};
    
    printArray(array);
    
    return 0;
    
}

void printArray(int array[]){
    int i = 0;
    while(i < ARRAYSIZE){
        printf("element %d = %d\n", i, array[i]);
        i++;
    }
}

The value of strings lies in the fact that a string, which is really a char array, has a terminating character. Therefore, we do not need to pass the length of the array to a called function.

#include <stdio.h>

int stringLength(char s[]);

int main(void){
    char string1[]="Is that a real poncho or a Sear's poncho?";
    char string2[]="You are technically correct - the best kind of correct.";
    
    printf("%s has %d characters\n",
            string1, stringLength(string1));
    
    printf("%s has %d characters\n", string2, stringLength(string2));
    
    return 0;
}


int stringLength(char s[]){
    int i = 0;
    
    /*
     * search for terminating null
     */
    for(i; s[i]!='';i++){;}
    
    /*
     * i is now the lenth of the string
     */
    return i;
    
}

The crucial point is to not think of the parameter inside the called function as an array of characters, but as a variable that holds the address of the initial element in the array. The technical term for such a variable is a character pointer.

#include <stdio.h>

#define STRLENGTH 100
void stringCopy(char *targString, char *srcString);

int main(void){

    char string1[STRLENGTH] = "I solemnly swear that I am up to no good.";
    char string2[STRLENGTH];
    
    stringCopy(string2, string1);
    
    printf("%s\n", string2);
    printf("%s\n", string1);
    return 0;
    
}

void stringCopy(char *targString, char *srcString){
    
    while(*srcString){
        /*
         * parentheses in expression below
         * not actually necessary, but...
         */
        *(targString++) = *(srcString++);
    }
    *targString = '';
}

The stringCopy() function above copies the characters from one char array to another.

Interested in learning C? Take a look at my book, that contains over 200 all-new sample programs: http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M/

Arrays and Pointers in C

Pointers and arrays are closely related; an array name without an index is functionally a pointer to the first element in the array.

#include <stdio.h>


int main(void){
 
  char arrayEmp[10];
 
  printf("&arrayEmp[0] = %p\n", &arrayEmp[0]);
  printf("arrayEmp = %p\n", arrayEmp);
 
 
  return 0;
 
}

As we have seen above, an array identifier without an index generates a pointer. Likewise, we can use offsets to index a pointer to an array.

#include <stdio.h>

int main(void){
 
  int i;
 
  int arrayEmp[5];
  int *arrayPtr;
  arrayPtr = arrayEmp;
 
  *(arrayPtr+0) = 42;
  *(arrayPtr+1) = 73;
  *(arrayPtr+2) = 1138;
  *(arrayPtr+3) = 1701;
  *(arrayPtr+4) = 8086;
 
 
  for(i=0;i<5;i++){
    printf("arrayEmp[%d] = %d\n", i, arrayEmp[i]);
  }
 
 
  return 0;
 
}

Remember, arrays start at zero. To access the fifth element, we must use the index number 4. Thanks to pointer arithmetic, we have two different ways to access an array element.

#include <stdio.h>

void printString1(const char *str);
void printString2(const char *str);
void printString3(const char *str);

int main(void){
 
 
  char str[30]={'T','h','e',' ','c','a','k','e',' ','i','s',' ','a',' ','l','i','e','\n',''};

 
  printString1(str);
  printString2(str);
   printString3(str);
  return 0;
 
}


void printString1(const char *str){
  int i;
  for(i=0; str[i]; i++){
    putchar(str[i]);
  }
}


void printString2(const char *str){
  while(*str){
    putchar(*str++);
  }
}

void printString3(const char *str){
  int i = 0;
  while(*(str+i)){
    putchar(*(str+i));
    i++;
  }
}

C allows for arrays of more than two dimensions; although, arrays of more than three dimensions are relatively rare. In multidimensional arrays, it takes the computer time to compute each index. This means that accessing an element in an multidimensional array can be slower than accessing an element in a single-dimension array.

When passing multidimensional arrays into functions, we must declare all but the leftmost dimension.

Pointers are sometimes used to access array elements because pointer arithmetic is faster than array indexing.

#include <stdio.h>

#define LINELENGTH 5

void printLine(int *intArray, int size);

void printArray(int *intArray, int size);

int main(void){
 
  int intArray[3][LINELENGTH];
 
  int *arrayPtr;
 
  int i, j;
 
  for(i=0; i<3; i++){
   for(j=0; j<5; j++){
     intArray[i][j]=i+j;
   }
  }
 
  printLine(intArray[0], LINELENGTH);
 
  putchar('\n');
 
  printLine(intArray[1], LINELENGTH);
 
  putchar('\n');
 
  printLine(intArray[2], LINELENGTH);
 
  printf("\n\n");
 
  arrayPtr = &intArray[0][0];
 
  printArray(arrayPtr, 3*LINELENGTH);
   
  putchar('\n');
 
  return 0;
 
}



void printLine(int *intArray, int size){
  while(size-->0){
      printf("%d\t", *intArray++);
  }
}


void printArray(int *intArray, int size){
  while(size-->0){
    printf("%d\t", *intArray++);
  }
}

A two dimensional array can be reduced to a pointer to an array of one-dimensional arrays. We can use a separate pointer variable as a way to use pointers to access elements within a row of a two-dimensional array.

#include <stdio.h>


int main(void){
 
  int intArray[5][7];
 
  int i = 0;
  int j = 0;
  int *ptr;
 
  //set pointer to second row
  ptr = &intArray[2][0];
 
  for(i=0; i<7; i++){
    *(ptr+i) = i * 2;
  }
 
 
  for(i=2, j=0; j<7; j++){
    printf("%d\t", *(intArray[i]+j));
  }
 
  putchar('\n');
 
  for(i=0; i<5; i++){
      ptr = &intArray[i][0];
      for(j=0; j<7; j++){
    *ptr++ = i + j;
      }
  }
 
  //set pointer to fourth row
  ptr = &intArray[4][0];
 
  for(i=0; i<7; i++){
    printf("%d\t", *(ptr+i));
  }
 
  putchar('\n');
 
  for(i=0; i<7; i++){
    printf("%d\t", *ptr++);
  }
 
  return 0;
 
}

For a more thorough look at pointers and the C language, check out my book http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M/

 

 

 

 

 

Introduction to Arrays in C

An array is a list of more than one variable having the same name.  Each variable in an array is known as an array element. We differentiate array elements by a subscript, which is  a number inside brackets. All array subscripts begin at zero, not one.

We can control individual elements in an array by their subscripts.

#include <stdio.h>

int main(void){

    int intArray[5];

    intArray[0] = 42;
    intArray[1] = 73;
    intArray[2] = 90210;
    intArray[3] = 64111;
    intArray[4] = 1138;


    printf("intArray[2] = %d\n", intArray[2]);
    printf("intArray[4] = %d\n", intArray[4]);


    return 0;

}

We can define an array as any data type in C. We can have integer arrays, long integer arrays, double arrays, char arrays, and so on. The compiler recognizes that we are defining an array, and not a single non-array variable, when we put brackets after the array’s name.

#include <stdio.h>

int main(void){

    
    char arrayChar[6];
    
    arrayChar[0]='H';
    arrayChar[1]='e';
    arrayChar[2]='l';
    arrayChar[3]='l';
    arrayChar[4]='o';
    arrayChar[5]='!';


    int i = 0;

    while(i<7){
        putchar(arrayChar[i++]);
    }



    return 0;

}


When we define an array, we tell the compiler to reserve a specific number of memory locations for that array by setting how many elements are in the array. Each element in an array uses the same amount of storage as a variable of the same type. C stores all array elements in a contiguous block.

#include <stdio.h>

int main(void){
 
  int n;
  int intArray[5];
 
  double j;
  double dubArray[5];
 
  printf("Size of a single int variable: %lu\n",
     sizeof(n));
 
  printf("Size of the intArray: %lu\n", sizeof(intArray));
 
  printf("Size of a single double variable: %lu\n",
     sizeof(j));
  printf("Size of a the dubArray: %lu\n", sizeof(dubArray));
 
  return 0;
 
}

We need to be sure to keep our subscript values within the range that we set when we declared the array.

We can create a string by initializing a char array with a character string. Note that with a string, we need an extra array element to hold the null zero at the end of the quoted string. A string is really just a char array where the last element is a null zero.

#include <stdio.h>

int main(void){
 
  char state1[15]="Missouri";
  char state2[15]="Nebraska";
 
  printf("%s and %s",
     state1, state2);
 
  char state3[15]={'K', 'a', 'n', 's', 'a', 's', ''};
 
  printf("\nand %s\n", state3);
 
  return 0;
 
}

We should always define an array with the maximum number of desired elements indicated in the subscript, unless we initialize the array at the same time.

#include <stdio.h>

int main(void){
 
  int nums[] = {1,3,5,7,11,13,17};
  long long bigNums[] = {8675309, 6647276};
 
  printf("%lld\n", bigNums[0]);
  printf("%d\n", nums[3]);
 
 
  return 0;
 
}

Our final example is a program to calculate the average of a set of grades given as double float values.

#include <stdio.h>

void printScores(double array[], int size);

int main(void){
 
  char uName[] = "Camden College";
 
  double grades[7] = {97.0, 81.3, 100.0, 89.9, 75.8, 88.5, 93.9};
 
  double averageGrade=0.0;
 
  int i;
 
 
  printScores(grades, 7);
 
  for(i=0; i<7; i++){
    averageGrade+=grades[i];
  }
 
  averageGrade/=7.0;
 
 
  printf("At %s, your average is %.1f\n",
     uName, averageGrade);
 
  return 0;
 
}

void printScores(double array[], int size){
  printf("Here are your grades:\n");
 
  int i;
  for(i=0;i<size;i++){
    printf("%.1f\n", array[i]);
  }
 
}

Note that to pass an array to a function, we need to specify only its name. In the function’s parameter list, we need to state the array type and include brackets after the array name.