Chapter 7: Arrays The variables used so far have all had a common characteristic: Each variable could only be used to store one value at a time. Frequently, we may have a set of values, all of the same data type, that form a logical group. A simple list containing individual items of the same scalar data type is called a onedimensional array. In this chapter, we will study how onedimensional arrays are declared, initialized, stored inside a computer, and used. 7.1 One-Dimensional Arrays A one-dimensional array(or a list, or a vector) is a group of related values with the same data type that is stored using a group name. The group name is referred to as the array name. The items in the list can be declared as a single unit and stored under a common variable name called the array name. For example, suppose that we would like to store five exam grades in an array, named grade, the declaration statement will be: int grade[5]; Other examples: char code[4]; //an array of four character values float prices[6]; double amount[100]; Each element in an array is called an element or component of the array. 1 Chapter 7: Arrays The individual elements stored in the array are stored sequentially, with the first array element stored in the first reserved location, the second element stored in the second reserved location, and so on. To access individual elements in an array, you use the name of the array and the element's position. This position is called the element's subscript or index value. For a single-dimensioned array the first element has a subscript of 0. The indices of an array are said to be zero relative. For example: int grade[5]; grade[0] refers to the first grade stored in the grade array. grade[1] refers to the second grade stored in the grade array. grade[0] grade[1] grade[2] grade[3] grade[4] an integer an integer an integer an integer an integer element 1 element 2 element 3 element 4 element 5 Internally, the computer uses the index as an offset from the array's starting position. The index tells the computer how many elements to skip over, starting from the beginning of the array, to get to the desired element. 2 Chapter 7: Arrays In-Class Exercise: 1. Write array declarations for the following: a. a list of 100 floating-point voltages b. a list of 30 characters, each representing a code c. a list of 100 integers Using Subscripted Variables Subscript variables can be used anywhere scalar variables are valid. For example: grade[0] = 98; grade[1] = grade[0] - 11; The subscript contained within the brackets need not be an integer constant. Any expression that evaluates to an integer may be used as a subscript. For example: grade[i] grade[2 * i] grade[j - 1] A for loop can be used to access the elements in an array. 3 Chapter 7: Arrays Example: Determine the maximum value in an array int prices [1000]; : : maximum = prices[0]; for (int i = 1; i <= 999; i++) if (prices[i] > maximum) maximum = prices [i]; In-Class Exercise: Write a for loop that can be used to display values for the complete array declared as: int grades [25]; 4 Chapter 7: Arrays Input and Output of Array Values Individual array elements can be assigned values interactively using cin object. For example: cin >> grade[0]; cin >> grade[1] >> grade[2] >> grade[3]; A for loop can also be used to cycle through the array for interactive data input. For example: for (int i = 0; i <= 4; i++) { cout << "Enter a grade: "; cin >> grade[i]; } Caution: C++ does not check the value of the index being used. For example, if an array has been declared as consisting of 10 elements, and you use an index of 12, C++ will not notify you of the error when the program is compiled. You will get a runtime error. During output, individual array elements can be displayed using the cout object. Again, a for loop can be used to display an array. for (int n = 5; n <= 20; n++) cout << n << " " << amount[n]; 5 Chapter 7: Arrays Example: Program 7-1 #include <iostream.h> int main( ) { int grade[5]; for (int i = 0; i <= 4; ++i) // Enter five grades { cout << "Enter a grade: "; cin >> grade[i]; } for (i = 0; i <= 4; i++) // Print five grades cout << "\ngrade[" << i << "] is " << grade[i]; cout << endl; return 0; } Sample Run: Enter a grade: 94 Enter a grade: 95 Enter a grade: 96 Enter a grade: 97 Enter a grade: 98 grade[0] is 94 grade[1] is 95 grade[2] is 96 grade[3] is 97 grade[4] is 98 6 Chapter 7: Arrays Example: Program 7-2 #include <iostream.h> int main( ) { int grade[5], total = 0; for (int i = 0; i <= 4; ++i) // Enter five grades { cout << "Enter a grade: "; cin >> grade[i]; } cout << "\nThe total of the grades "; for (i = 0; i <= 4; i++) // Print five grades { cout << grade[i] << " "; total = total + grade[i]; } cout << "is " << total; return 0; } In-Class Exercise: Write a program to input eight integer numbers into an array named temp. As each number is input, add the numbers into a total (accumulator). After all numbers are input, display the numbers and their average. 7 Chapter 7: Arrays 7.2 Array Initialization Array elements can be initialized within their declaration statements, enclosing their values within braces. For example: int grade[5] = { 95, 87, 92, 100, 80 }; If the number of initializers is less than the declared number of elements listed in square brackets, the initializers are applied starting with array element zero. For example: int grade[5] = { 98, 100, 80 }; will only initialize the first three elements. A unique feature of initializers is that the size of an array may be omitted when initializing values are included in the declaration statement. For example: int gallons [ ] = { 16, 12, 10, 15, 19 }; char code [4] ={ 'a', 'b', 'c', 'd' }; char code [ ] ={ 'a', 'b', 'c', 'd' }; An Interesting Simplification: In C and C++, an array of characters can be used to store a string value. Another method of initializing a character array: char code [ ] = "sample"; // no braces or commas 8 Chapter 7: Arrays This uses the string "sample" to initialize the char array, code. This creates an array named code with seven elements stored in it. (Why seven?) In-Class Exercise: Write a declaration to store the string “This is a test” into an array named strtest. Include the declaration in a program to display the message using the following loop: for (int i = 0; i < NUMDISPLAY; i++) cout << strtest[i]; where NUMDISPLAY is a named constant for the number 15. 7.3 Arrays as Arguments to Functions Individual array elements are passed to a called function in the same manner as individual scalar variables. For example: find_min(grades[2], grades[6]); find_max(grades) Passing a copy of the whole array to the function would be wasteful of computer storage, especially for larger arrays. To avoid this, the called function is given direct access to the array. On the receiving side, the called function must be alerted that an array is being passed. 9 Chapter 7: Arrays Let's look at an example: 10 Chapter 7: Arrays Program 7-4: #include <iostream.h> int find_max(int [5]); // function prototype int main( ) { int nums[5] = {2, 18, 1, 27, 16}; cout << "\nThe maximum value is " << find_max(nums) << endl; return 0; } int find_max(int vals[5]) { int i, max = vals[0]; // find the maximum value for (i = 1; i < 5; i++) if (max < vals[i]) max = vals[i]; return max; } 11 Chapter 7: Arrays The parameter declaration in find_max( ) header line actually contains extra information that is not required by the function. All that find_max( ) must know is that the parameter vals references an array of integers. Since the array has been created in main( ) and no additional storage space is needed in find_max( ), the declaration for vals can omit the size of the array. Thus, an alternative function header line is: int find_max(int vals[ ]) Note: When this array is being passed, only the address of the first element in the array is actually passed. You are passing a reference or pointer to the array. Once the function has the address of the first element, it calculates the location of the other elements based on the data type of the array. The more general form of the previous example follows: Program 7-5: #include <iostream.h> int find_max(int [], int); // function prototype int main( ) { int nums[5] = {2, 18, 1, 27, 16}; cout << "\nThe maximum value is " << find_max(nums, 5) << endl; return 0; } 12 Chapter 7: Arrays int find_max(int vals[], int num_els) { int i, max = vals[0]; for (i = 1; i < num_els; i++) if (max < vals[i]) max = vals[i]; return max; } In-Class Exercise: Given the following function definition: #include <iostream.h> bool sameArray(float a[], // IN: arrays to be compared float b[], const int size)// IN: size of the arrays { int i = 0; // Loop control variable/array subscript while ((i < size – 1) && (a[i] == b[i])) i++; return (a[i] == b[i]); } Write a main( ) function that declares and initializes two float arrays, then uses the above function to determine if the arrays are equal or not. 13 Chapter 7: Arrays Reading Part of an Array Sometimes the programmer does not know what the exact size of a particular array will be, because it is unknown how many values the user needs to enter. For example, if you are writing a program to process grades, one class section may have 15 students and another may have 25 students. As a programmer, you need to allocate enough storage to handle the maximum number of scores so that the program can process the largest expected array without error. When you read the array data into memory, you should begin filling the array starting at element 0 and keep track of the number of data items that are actually being stored in the array. The portion of the array that contains actual data is called the filled subarray. 14 Chapter 7: Arrays In-Class Exercise: Given the following code: #include <iostream.h> const int MAXSIZE = 14; // Add function prototypes here int main() { int grades[MAXSIZE]; int total; // Accumulates the total grades int numGrades; // Counts the number of grades entered float average; // Use reference parameter here for total and numGrades readGrades(grades, total, numGrades); displayGrades(grades); // Add code to calculate and display the average. return (0); } // Define functions here Complete the program so that it allows the user to enter the grades (use a sentinel to stop entry or stop at MAXSIZE), then display those grades, then calculates, and displays the average. 15 Chapter 7: Arrays 7.4 Two-Dimensional Arrays A two-dimensional array, which is also referred to as a table, consists of both rows and columns of elements. For example: 1 1 0 5 0 8 4 9 1 2 7 3 6 1 This array corresponds to: int val[3] [4]; Other examples: float prices [2] [10]; char code [4] [100]; Note: In order to identify an element in the array, you need to provide the row and column location of the element. For example: price = prices[2] [4]; newval = 4 * (val[1] [3] - 1); 8 0 Col. 0 5 8 Row 0 12 -1 Col. 1 Row 1 Col. 2 val [1] [2] NOTE: The row and column numbering starts from zero. 16 Chapter 7: Arrays Declaration and Processing As with single-dimensional arrays, two-dimensional arrays can be initialized from within their declaration statements. For example: int val [3] [2] = { {1, 0}, {2 , 1}, {5, 4} }; which is the same as: int val [3] [2] = { 1, 0, 2, 1, 5, 4 }; OR: int val [3] [2] = { 1, 0, 2, 1, 5, 4}; 17 Chapter 7: Arrays Program 7-6: #include <iostream.h> #include <iomanip.h> int main( ) { int i, j; int val[3][4] = {8, 16, 9, 52, 3, 15, 27, 6, 14, 25, 2, 10}; cout << "\nDisplay of val array by explicit element:" << '\n' << setw(4) << val[0][0] << setw(4) << val[0][1] << setw(4) << val[0][2] << setw(4) << val[0][3] << '\n' << setw(4) << val[1][0] << setw(4) << val[1][1] << setw(4) << val[1][2] << setw(4) << val[1][3] << '\n' << setw(4) << val[2][0] << setw(4) << val[2][1] << setw(4) << val[2][2] << setw(4) << val[2][3]; cout << "\n\nDisplay of val array using a nested for loop:"; for (i = 0; i < 3; i++) { cout << '\n'; // print a new line for each row for (j = 0; j < 4; j++) cout << setw(4) << val[i][j]; } return 0; } 18 Chapter 7: Arrays Typically, for loops are used to process two-dimensional arrays. In the following program, the nested for loop is used to multiply each element in the val array by the scalar number 10 and display the resulting value. Program 7-7: #include <iostream.h> #include <iomanip.h> int main ( ) { int i, j; int val [3][4] = { 8, 16, 9, 52, 3, 15, 27, 6, 14, 25, 2, 10 }; // multiply each element by 10 and display it cout << "\n\nDisplay of multiplied elements\n"; for (i = 0; i < 3; i++) { cout << '\n'; // start a new line for (j = 0; j < 4; j++) { val [i][j] = val [i][j] * 10; cout << setw(5) << val [i][j]; } // end of inner loop } // end of outer loop return 0; } 19 Chapter 7: Arrays In-Class Exercise: Write a C++ program that finds and displays the maximum value in a two-dimensional array of integers. The array should be declared as a 4 by 5 array of integers and initialized with the data: 16, 22, 99, 4, 18, -258, 4, 101, 5, 98, 105, 6, 15, 2, 45, 33, 88, 72, 16, 3 As Function arguments Passing two-dimensional arrays into functions is a process identical to passing single-dimensional arrays. The called function receives access to the entire array. Note: In the declaration, the row number can be omitted, but the column number must be included. For example: display (int [4] [5]) is the same as: display (int [ ] [5]) 20 Chapter 7: Arrays Example: Program 7-8: #include <iostream.h> #include <iomanip.h> void display (int [ ][4]); // function prototype int main( ) { int val[3][4] = { 8, 16, 9, 52, 3, 15, 27, 6, 14, 25, 2, 10 }; display (val); return 0; } void display (int nums[ ][4]) { int row_num, col_num; for (row_num = 0; row_num < 3; row_num++) { cout << '\n'; // start a new line for (col_num = 0; col_num < 4; col_num++) cout << setw(4) << nums[row_num][col_num]; } } 21 Chapter 7: Arrays Additional Examples: Array Declarations: int test [7] [9]; char code [26] [10]; and the following function calls: find_max(test); obtain (code); on the receiving side: int find_max (int nums[ ] [9]) char obtain (char key[] [10]) column 0 column 1 column 2 column 3 NOTE: If the array is a global one, there is no need to pass Row 0 the array because the function could reference the arval [1][2] ray by its global name. Row 1 Row 2 val [2][3] 22 Chapter 7: Arrays Larger-Dimensional Arrays This is done by listing the maximum size of all dimensions for the array. For example, the declaration int response [4][10][6]; declares a three-dimensional array. A three-dimensional array can be viewed as a book of data tables. The first subscript can be thought of as the page number of a selected table, the second subscript value as the desired row and the third subscript as the desired column. Similarly, a four dimensional array can be represented as a shelf of books, where the first dimension is used to declare a desired book on the self, and a five-dimensional array can be viewed as a bookcase filled with books where the first dimension refers to a selected shelf in the bookcase. 23 Chapter 7: Arrays 7.7 Sorting Methods Most programmers encounter the need to sort a list of data items at some time in their programming careers. For sorting data, two major categories of sorting techniques exist, called internal and external sorts. Internal sorts are used when the data list is not too large and the complete list can be stored within the computer's memory, usually in an array. External sorts are used for much larger data sets that are stored on a large external disk or in tape files and cannot be accommodated within the computer's memory as a complete unit. We will focus on two internal sort algorithms, the selection and exchange sorts. The exchange sort is also known as the "bubble sort." Selection Sort In a selection sort, the smallest (or largest) value is initially selected from the complete list of data and exchanged with the first element in the list. After this first selection and exchange, the next smallest (or largest) element in the revised list is selected and exchanged with the second element in the list. This second pass only need to consider the second through last elements. For a list of n elements this process is repeated n-1 times, with each pass through the list requiring one less comparison than the previous pass. 24 Chapter 7: Arrays Initial list 690 307 32 155 426 Pass 1 Pass 2 Pass 3 Pass 4 32 307 690 155 426 32 155 690 307 426 32 155 307 690 426 32 155 307 426 690 Example: Program 7-9 #include <iostream.h> #include <iomanip.h> void main(void) { int nums[10] = {22,5,67,98,45,32,101,99,73,10}; int i, j, temp, moves, min, minInd; moves = 0; for (i = 0; i < 10; i++) { min = nums[i]; minInd = i; // Search for minimum value for (j = i + 1; j < 10; j++) if (nums[j] < min) { min = nums[j]; minInd = j; } // perform the switch if (min < nums[i]) { temp = nums[i]; nums[i] = min; nums[minInd] = temp; ++moves; } } // end of outer for loop 25 Chapter 7: Arrays cout << "\nThe sorted list, in ascending order, " << "is:\n"; for (i = 0; i < 10; ++i) cout << setw(4) << nums[i]; cout << '\n' << moves << " moves were made to " << "sort this list\n"; } Exchange Sort In an exchange sort, successive values in the list are compared, beginning with the first two elements. If the list is to be sorted in ascending order, the smaller value of the two being compared is always placed before the larger value. For lists sorted in descending order, the smaller of the two values being compared is always placed after the larger value. Example: Program 7-10 #include <iostream.h> #include <iomanip.h> const TRUE = 1; const FALSE = 0; // the default is an integer type // the default is an integer type int main ( ) { int nums[10] = {22,5,67,98,45,32,101,99,73,10}; int i, temp, moves, npts, outOrd; moves = 0; npts = 10; outOrd = TRUE; 26 Chapter 7: Arrays while (outOrd && npts > 0) { outOrd = FALSE; for (i = 0; i < npts - 1; i++) if (nums[i] > nums[i+1]) { temp = nums[i+1]; nums[i+1] = nums[i]; nums[i] = temp; outOrd = TRUE; moves++; } npts--; } // end while loop cout << "\nThe sorted list, in ascending order, " << "is:\n"; for (i = 0; i < 10; ++i) cout << setw(4) << nums[i]; cout << '\n' << moves << " moves were made to " << "sort this list\n"; return 0; } 27 Chapter 7: Arrays In-Class Exercises: 1. Rewrite Program 7-10 to use a function called bubbleSort ( ) that accepts the array and the size of the array as its arguments. The function should return an integer which is the number of moves that were necessary to sort the array in ascending order. The function prototype should look like: int bubbleSort (int [ ], int); 2. Write a function called selectionSort( ) which accepts a one–dimensional array, and the size of the array as its arguments. The function should sort the array in descending order and return the number of moves that were necessary to complete the sort. The prototype should look like: int selectionSort(int [ ], int); Create a main( ) function to test your function. Declare an array of integers and initialize it with the data: 16, 22, 99, 4, 18, -258, 4, 101, 5, 98, 105, 6, 15, 2, 45, 33, 88, 72, 16, 3 28