Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual....

25
Lab 6: Arrays Graham Northup

Transcript of Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual....

Page 1: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Lab 6:

ArraysGraham Northup

Page 2: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Objective

● To be able to use arrays for contiguous,sequential storage

● To understand the operations on arrays, andthe errors that may result

● To gain a partial understanding of how thecompiler allocates memory for use by aprogram

Page 3: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Review: Variables#include <iostream>using namespace std;

int main() { int i, low, high;

cout << "Enter start: "; cin >> low; cout << "Enter end: "; cin >> high;

for(i = low; i <= high; i++) { cout << i << "\n"; }

return 0;}

We’ve been declaring variables for awhile now, but it’s important tounderstand what happens when thecompiler encounters this...

Simplifying things slightly, it makessome space, large enough to holdthose variables.

i ?

low ?

high ?

01000101000101011100001010000101110110

i low high

Memory (not to scale)

In effect, the compiler (at its discretion)chooses a place in memory to store yourvariables, and knows to reference thatlocation when you use them in yourprogram.

Page 4: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

“Scalar” Values

intcharfloatdoublebool

1‘f’5.2f3.14159true

So far, we’ve (mostly) only introduced types thathave constant storage and can only hold onediscrete value at a time. (We’ll come back to theexception later in the presentation.) Such values are“scalar”.

This is fine and all, but it is frequently useful toalso represent sequences or vectors of values.

5 ints3 chars2 floats4 doubles6 bools

1, 2, 3, 4, 5‘f’, ‘o’, ‘o’5.2f, 10.4f3.14159, 0.0, -3.14159, 0.0true, false, false, true, true, false

Page 5: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Arrays

int seq[5] = {1, 2, 3, 4, 5};char disp[3] = {'f', 'o', 'o'};float coord[2] = {5.2f, 10.4f};double crit_pts[4] = {3.14159, 0.0, -3.14159, 0.0};bool assn[6] = {true, false, false, true, true, false};

...and, in fact, this is the basis for arrays!These are the corresponding definitions forthe prior sequences in C.

Page 6: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Declaring Arrays

int seq[5] = {1, 2, 3, 4, 5};

Type of the array. All elements are of thistype.

Name of thevariable, as usual.

Number ofelements in thearray.

Initializer list—contains thestarting values in the array.Programs can get and setthese values later.

Page 7: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Using Arrays

seq[0] = 7;seq[4] = 9;

ivar = seq[2] + seq[3];

Once declared, arrays may be indexed byfollowing their name with an integer (orinteger expression) in square brackets,much like how they are declared. Notethat the first element is at index zero.

The result is an expression whose type isthe same as the base type of the array,and can be used anywhere that typecould normally be used. Assignmentschange the value in the array.

PC

1 2 3 4 5

0 1 2 3 4

seq

i

7 9ivar ?7

Page 8: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Arrays and Memory

0 1 2

0 1 2

Arrays have the unique property thatthey are laid out contiguously inmemory; each element is after theelement with the preceding index, andbefore the element with the followingindex, regardless of the size of theunderlying type. We’ll come back to whythis is important in a second.

char[3]

short int[3]

Lower addresses Higher addresses

Page 9: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Aside: Intrinsic TypesThere’s a particular array that is worthmentioning, but first I must digress: everyexpression in the compiler, including literals—the values that you type into your program—have an associated or intrinsic type thatthe compiler assumes them to have. Forexample:

1 := int1 + 2 := int2.0 := double3.2f := float“foo” := ?

What’s the type of a quoted string?

Page 10: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Aside: Intrinsic TypesIf you guessed std::string, you werepretty close, but not quite; instead, it is a(read-only) array of characters.

1 := int1 + 2 := int2.0 := double3.2f := float“foo” := char[]

Page 11: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Character ArraysThese two definitions are equivalent:

char foo1[] = "foo";char foo2[] = {'f', 'o', 'o', '\0'};

Note the ‘\0’ at the end; this is a special characterknown as the sentinel or NUL terminator. It’s value isthe integer 0, and it must be at the end of a characterarray so that things that deal with them know whenthey end.

It’s worth mentioning that std::string doesn’t havethis limitation; it instead remembers the actual numberof characters.

Page 12: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Character Arrays

char foo1[4] = "foo";char foo2[4] = {'f', 'o', 'o', '\0'};

...naturally, because of that “hidden” character, the length ofthese character arrays or C-strings is 4 characters.

‘f’ ‘o’ ‘o’ 0

foo[0]

foo[2]foo[1

]foo[3]

Page 13: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Array Length

int seq1[] = {1, 2, 3, 4, 5};int seq2[5] = {1, 2, 3, 4, 5};

On occasion, I have been taking the number out of the [squarebrackets] in the declaration; this is a shorthand to the compiler for twopurposes. The first must be used with an initializer list, and thecompiler will just count the number of items for you:

In this case, the two definitions above are equivalent.

The second is often used for parameters, and we’ll get to that in asecond.

Page 14: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Zero FillingIf you specify too many items in your initializer list, thecompiler will, as usual, complain. What if you specify toofew?

int seq[5] = {1, 2};

In this particular case, the compiler fills themissing entries with zeroes. It is equivalentto the following:

int seq[5] = {1, 2, 0, 0, 0};

The compiler will insert as many as neededto get up to the length of the array.

Page 15: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Zero Filling

int seq[5] = {};

Continuing along with the previousexample, the following:

...will give you an array of size 5 (5elements), all of which are initially zero.Note that this is very different from thefollowing:

int seq[5];...which tells the compiler to notinitialize the values at all!

Page 16: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Iterating Over ArraysRemember the for loop?

int seq[5] = {1, 2, 3, 4, 5};int i;

for(i = 0; i < 5; i++) { cout << seq[i] << "\n";}

Page 17: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Iterating Over ArraysBut what if we have 10 elements, you ask?

int seq[10] = {2, 4, 6, 8, 10, 1, 3, 5, 7, 9};int i;

for(i = 0; i < 10; i++) { cout << seq[i] << "\n";}

There are ways to avoid being so redundant, butwe haven’t covered them (yet). For now, justremember that you should count from 0 up to(but not including) the size of the array.Remember to change the bounds whenever youchange the size of the array—the compiler willnot help you!

Page 18: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Bounds ErrorsWe’re getting one step closer to some of the moredangerous (and fun) parts of C and C++. Naturally,like all humans, you’re bound to make mistakes.Here’s an artificial example of a common mistakewith arrays: accessing them outside of their bounds(0 <= idx < size):

#include <iostream>using namespace std;

int main() { int vars[5];

vars[7] = 302948;

return 0;}

Page 19: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Bounds ErrorsWhen I run this, I get this:

The errors you get may ormay not be the same, andmay be as benign asappearing to work correctly,to as insidious as giving thewrong results, to as blatantas crashing like this. Checkand double check yourbounds!

Page 20: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Activity: Computing Totals

#include <iostream>using namespace std;

int main() { int seq[5] = {4, 3, 7, 5, 1}; int i; int sum = 0;

for(i = 0; i < 5; i++) { sum += seq[i]; }

cout << "Total: " << sum << "\n";

return 0;}

Feel free to experimentwith the values in here!

Page 21: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Arrays of ArraysWhile not always strictly necessary, it’s useful to note that thebase type of an array can, itself, be an array. For example:

double matrix[3][2];

...declares an (uninitialized) array of size 3 with a base type ofdouble[2]--an array of doubles, size 2. Note that the sizes areread left-to-right.

Accessing the values in a so-called multidimensional array isfairly straightforward:

matrix[0][0] = 3;matrix[2][1] = 7;

Arbitrary dimensions can be achieved, but in practice, few arrayshave more than two or three dimensions. A common case is anarray of C strings—which is an array containing character arrays.

Page 22: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Aside: main’s ParametersMost of the time, I’ve been ignoring function main’s parameters.

#include <iostream>using namespace std;

int main() { int seq[5] = {4, 3, 7, 5, 1}; int i; int sum = 0;

However, in most systems, main does (optionally) take someparameters, and we’re particularly interested in the first two…

Page 23: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Aside: main’s Parameters

int main(int argc, char *argv[]) {

This is closer to main’s proper signature:

The second parameter is an array of C-strings (an array of character arrays), which arethe arguments to your program! The star (*) is there because g++ doesn’t like havingmore than one dimension left unsized in a parameter, so just bear with me when I tellyou that it means about the same thing as char[][]. Note that the size isn’t specified,because the compiler can’t possibly know this in advance. Instead, your operatingsystem passes the size of argv in the first parameter, argc. You can use argc wherever you’d use “the size of argv”. (The names of these parameters are traditionaland well-respected, but I should tell you that you can rename them if you’d like—theorder must be the same, however.)

Page 24: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Activity: Program Arguments

#include <iostream>using namespace std;

int main(int argc, char *argv[]) { int i;

for(i = 0; i < argc; i++) { cout << "Arg " << i << ": " << argv[i] << "\n"; }

return 0;}

Without further ado, here is a program that tells you what its arguments are:

cout knows how to displaya char[] to the terminal

Page 25: Lab 6: Arrays · Type of the array. All elements are of this type. Name of the variable, as usual. Number of elements in the array. Initializer list—contains the starting values

Program ArgumentsWhen I run the previous program on my machine:

Note the “zeroeth” argument: it’s the name of your program!Most programs just ignore this, but some particularly versatileprograms will do different things depending on what name youcall them with. You can also use it to find out where yourprogram is.

Through careful, judicious use of arguments, you now have a wayto get input from the user without having to prompt them foreverything. Use it sensibly, of course :)