0% found this document useful (0 votes)
2 views38 pages

Lecture 4 - Arrays&Loops

The document discusses programming concepts related to arrays and loops, including how to declare and access arrays, as well as the different types of loops (while, do-while, for) and their flow control mechanisms. It explains the differences between scalar and array data types, and how to use loops in conjunction with arrays to iterate through their elements. Additionally, it covers topics such as designated initializers, memory management, and flow control commands like break and continue.

Uploaded by

coolguysemail222
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views38 pages

Lecture 4 - Arrays&Loops

The document discusses programming concepts related to arrays and loops, including how to declare and access arrays, as well as the different types of loops (while, do-while, for) and their flow control mechanisms. It explains the differences between scalar and array data types, and how to use loops in conjunction with arrays to iterate through their elements. Additionally, it covers topics such as designated initializers, memory management, and flow control commands like break and continue.

Uploaded by

coolguysemail222
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 38

Presented by UFMFGT-15-1: Programming for Engineers

Tom Knowles Week 15: Arrays and Loops

Code: XX-XX-XX

22 February, 2024
This session
• Arrays
o Scalar vs array data types
o How to declare them
o How to access their items

• Loops
o while, do-while, for
o Flow control within loops

• Loops and arrays together


Why do we need Arrays and Loops?
• Up to this point, you can make programs that can do user I/O and make decisions
o scanf, printf
o Flow control (if, switch)

Arrays Loops
• Declare a single block of • Runs a block of code a
memory number of times
• Holding multiple variables of • Can run repeatedly until a
the same type condition is met
• Can be treated as a group or • Can work with array items
individual items iteratively
Scalar declaration

data
type
name = value ;
• We can choose any valid combination of letters, numbers and underscores
• Names like this represent scalar variables – they are completely independent
Array declaration

data
type
name [N] = value
;
• Adding square brackets lets us declare how many memory items to associate with this
variable name
• Functionally, this is the same as declaring N variables one after the other
o Except, we can refer to them as a group by their name
Scalar vs Array
Scalar Declaration Array Declaration
int sc1; int arr[3];
int sc2;
int sc3; arr[0] = 1;
arr[1] = 2;
sc1 = 1; arr[2] = 3;
sc2 = 2;
sc3 = 3;
printf("My array items:
printf("My scalars: %d, %d, %d, %d",
%d, %d", sc1, sc2, arr[0], arr[1],
sc3); arr[2]);
Scalar vs Array
Scalar Declaration Array Declaration
int sc1 = 1; int arr[3] = {1, 2, 3};
int sc2 = 2;
int sc3 = 3;

printf("My scalars: %d, printf("My array items:


%d, %d", sc1, sc2, %d, %d, %d",
sc3); arr[0], arr[1],
arr[2]);
Scalar vs Array
Scalar Declaration Array Declaration
int sc1 = 1; int arr[] = {1, 2, 3};
int sc2 = 2;
int sc3 = 3;

printf("My scalars: %d, printf("My array items:


%d, %d", sc1, sc2, %d, %d, %d",
sc3); arr[0], arr[1],
arr[2]);
Designated Initialisers
Array Declaration
• Not all of an array needs to be initialised
• If we only want specific non-default values, int arr[100] = {[3] = 1,
we can refer to specific items within [49]= 3,
our initialisation [70] = 7};
• This assigns values to those indexes only;
the rest remain default for that data type
printf("My array items:
%d, %d, %d",
arr[0], arr[1],
arr[2]);
Using whole arrays
Array Declaration
• The array variable name is a pointer to int arr[] = {1, 2, 3};
where the array starts

• C represents the variables as they are in


memory; contiguous
arr
• When referring to the array itself, we can arr[0] arr[1] arr[2]

1 2 3
also refer to it as a whole by 'referencing'
the variable arr[0]; finding its starting
memory location

• Functionally, the difference ends up being


adding an 'address of' operator in front of
the array item to refer to the whole thing
Example: user input
Array Declaration
• Familiar from the 2nd week of exercises -> char input[3];

scanf("%2s", input); Whole array


input[0] input[1] input[2] referenced

input 'h' 'i' '\0' printf("%d,%d,%d",


input[0],
input[1], input[2]);
Array items
referenced

input[0] input[1] input[2]

input # # #
Example: user input
Array Declaration
• Familiar from the 2nd week of exercises -> char input[3];
&input[0]
scanf("%2s", &input[0]);Whole array
input[0] input[1] input[2] referenced

input 'h' 'i' '\0' printf("%d,%d,%d",


input[0],
input[1], input[2]);
Array items
&input[0] referenced

&
input[0] input[1] input[2] 'address of'

# # #
operator
input
Loops
• Structures that repeat an inner block of code
• Come in three flavours:

While Do-While For


• Runs whilst a • Runs whilst a • Runs a set number of
conditional expression conditional expression iterations
is true is true • Stops once the last
• Stops when this • Stops when iteration has been run
becomes false this becomes false • Uses its own
• Checks the expression • Checks the expression dedicated iterator
before the first after the first iteration variable
iteration
While
int start, end;

• While the expression is true, execute code scanf("%d %d", &start, &end);
block repeatedly
• Expression ideally will change at some point int t = start;
to allow the while loop to exit
while (t < end) {
• Does this loop ever end?
printf("%d", t);

t++;

}
While
int start, end;

• Yes; regardless of how large end is, t will scanf("%d %d", &start, &end);
eventually reach it
• If start >= end, it won't run int t = start;

while (t < end) {

printf("%d", t);

t++;

}
While
int start, end;

• Adding if statements to catch scanf("%d %d", &start, &end);


troublesome inputs is good practice
• Will this code complete, given enough int t = start;
time?
if start >= end {

printf("Warning: start time is


larger than end time.");

} else {

while (start < end) {

printf("%d", t);

t++;
}
}
While
int start, end;

• No! We have made a mistake, and are not scanf("%d %d", &start, &end);
checking the right variables
int t = start;

if start >= end {

printf("Warning: start time is


larger than end time.");

} else {

while (start < end) {

printf("%d", t);

t++;
}
}
While
int start, end;

• Now it is checking the correct variables in scanf("%d %d", &start, &end);


the expression
int t = start;

if start >= end {

printf("Warning: start time is


larger than end time.");

} else {

while (t < end) {

printf("%d", t);

t++;
}
}
While
int start, end;

• Similarly, a loop without a proper change in scanf("%d %d", &start, &end);


its expression could 'step over' the
expression that would stop the loop int t = start;

while (t != end) {

printf("%d", t);

t = t + 2;

}
While
int start, end;

• Sticking to lower-specificity expressions can scanf("%d %d", &start, &end);


catch these cases
int t = start;

while (t <= end) {

printf("%d", t);

t = t + 2;

}
Do-While
#include <robot.h> // not a real .h
int status;
• A while loop flipped on its head
• Performs the loop body, then checks the do {
condition
status = startUp();
• Great for if something needs to run at least
once before checking if it needs to be run if (status != 0) {
again
• Couple of easy things to miss printf("Startup exited with
o Semicolon after the while expression status
%d: retrying...",
o No condition after the do keyword
status);
}

} while (status != 0);


For
#include <dataSource.h> // not a real
.h
• A while loop that uses an iterator rather int data[10] = loadData();
than an expression
• An iterator is a variable that tracks which for (int i = 0; i < loops; i++) {
loop is currently being run
// do something until !(i <
• Always an integer, and always defined as loops)
part of the loop
o If you want to check an external }
variable's value, use a while loop with a
relational expression
For
#include <dataSource.h> // not a real
.h
Dedicated iterator (int i = 0; int data[10] = loadData();
int loops = 10;
Conditional
expression i < loops; for (int i = 0; i < loops; i++) {
Iterator change per
loop i++) // do something until !(i <
loops)
• Each for loop has three parts to its
expression }
• Typically an increment (counting upwards)
• Can add more that 1 each time
• Can decrement
For loops and arrays
#include <sensor.h> // not a real .h
&data[0] int samples = 10;
int data[] = readData(samples);
data[0] data[...] data[9]

? . . . ?
for (int i = 0; i < samples; i++) {
data
currentItem = data[i];

printf("Value of item %d = %d",


• Consider an array of known size, but i, currentItem);
unknown contents
}
• We might want to 'unpack' the
array; getting all of its values }
• We can use the iterator as an index
• Don't mix up the index (location) of the
data and the data at that index
Inspecting arrays
#include <stdio.h> // includes
&data[0] <stddef.h>
int samples = 10;
data[0] data[...] data[N] int data[] = readData(samples);

data ? . . . ? printf("Size of data (in bytes): %d",


sizeof(data));
Size of data (in bytes): 40
• Unlike some languages, C arrays are very
barebones
• They are not objects and do not have
properties outside of their data contents
• However, <stdio.h> has some functions #include <stdio.h> // includes
to help us work with them eg. sizeof() <stddef.h>
• This can also be used to find how large a
printf("Size of int: %d",
given data type is in memory Size of int (in bytes):
sizeof(int)); 4
Inspecting arrays
#include <stdio.h> // includes
&data[0] <stddef.h>
int samples = 10;
data[0] data[...] data[N] int data[] = readData(samples);

data ? . . . ? printf("Size of data (in elements):


%d", sizeof(data) / sizeof(int));
Size of data (in elements):
• To emulate the behaviour of MATLAB’s 10
numel() or Python’s len(), we can divide the
size in bytes, by the size of an integer in
memory
• This gives how many elements (in this case,
integers) exist in the array
• We can use this in our loop conditional
expressions to allow for varying array sizes
Memory overrun
#include <sensor.h> // not a real .h
&data[0] int samples = 10;
int data[] = readData(samples);
data[0] data[...] data[9] int nextItem;

data ? . . . ? for (int i = 0; i < samples; i++) {

nextItem = data[i+1];

• It is possible to refer to items outside of the printf("Value of next item %d =


array %d",
o What is presented as an index is really i+1, nextItem);
just a memory offset of }
sizeof(dataType)
• When this happens, behaviour is undefined }
• Make sure to keep indexing variables within
the bounds of the array
Memory overrun
#include <sensor.h> // not a real .h
&data[0] int samples = 10;
int data[] = readData(samples);
data[0] data[...] data[9] int nextItem;

data ? . . . ? for (int i = 0; i < samples; i++) {

if ((i + 1) < samples) {

• Like with while loops, we can catch nextItem = data[i+1];


problematic cases with if statements
} else {

nextItem = data[i];

printf("Value of next item %d =


%d",
i+1, nextItem);

}
Flow control - break
int emailAddress[40];
&data[0] int size = sizeof(emailAddress);
scanf("%s", emailAddress);
data[0] data[...] data[9] int username[20];

data ? . . . ? for (int i = 0; i < size; i++) {

if(emailAddress[i] == '@') {

• At times, we may want to end the loop break;


structure early
}
• Useful if the rest of the for loop is
redundant for the array printf("%c", emailAddress[i]);
• Note that this moves the program counter
outside the for block, regardless of the }
status of the iterator
Flow control - continue
int emailAddress[40];
&data[0] int size = sizeof(emailAddress);
scanf("%s", &emailAddress);
data[0] data[...] data[9] int username[20];

data ? . . . ? for (int i = 0; i < samples; i++) {

if(emailAddress[i] == '.') {

• At times, we may want to end the loop and continue;


restart
}
• Useful if the rest of the loop is redundant
for that item if(emailAddress[i] == '@')
• Note that this keeps the program counter {break;}
inside the for block, and will carry on to
the next iteration (if any) printf("%c", emailAddress[i]);

}
Casting arrays
&input[0] &output[0]
input[0] input[...] input[9] output[0] output[...] output[9]

input char . . . char int . . . int output

• Last week we explored the idea of casting; char input[10];


converting one variable to another data type scanf("%s", &input[0]);
• Casting arrays is tricky, because they are int output[10];
contiguous
• Generally, it is better to cast the items and for (int i = 0; i < sizeof(input); i+
+){
reassemble a new array iteratively
• We can use the sizeof() function to tell output[i] = (int)input[i];
us the size of the array
}
2D Arrays
int input[3][3] = {{1, 2, 3},
&input[0][0] {4, 5, 6},
{7, 8, 9}};
input[0] input[1] input[2]

? . . . ?
input[0][0] input[1][0] input[2][0]
• 2D (and higher) arrays are perfectly possible

1 4 7 • Each array item is itself an array


• Still contiguous in memory; this just helps us
organise certain data more naturally
input[0][1] input[1][1] input[2][1]
• Examples:
input
2 5 8 o Greyscale image data (3D for RGB image)
o Data tables

input[0][2] input[1][2] input[2][2]

3 6 9
Working with 2D Arrays
int input[3][3] = {{1, 2, 3},
&input[0][0] {4, 5, 6},
{7, 8, 9}};
input[0] input[1] input[2]

? . . . ?
input[0][0] input[1][0] input[2][0] n_cols = sizeof(input[0]);
n_rows = sizeof(input) / n_cols;

1 4 7 for (int i = 0; i < n_cols; i++){

input[0][1] input[1][1] input[2][1] for (int j = 0; j < n_rows; j++){

input
2 5 8
printf("Item (%d, %d): %d",
i, j, output[i][j]);

input[0][2] input[1][2] input[2][2] }

}
3 6 9 • Scales poorly, but is essential for working
with high-dimensional datasets
Flow control - break
int input[3][3] = {{1, 2, 3},
{4, 5, 6},
• break statements can also be used within {7, 8, 9}};
nested loops
• They only exit the innermost block they are n_cols = sizeof(input[0]);
called in, not all parent blocks n_rows = sizeof(input) / n_cols;

for (int i = 0; i < n_cols; i++){

for (int j = 0; j < n_rows; j++){

// do something
break;

}
Flow control - continue
int input[3][3] = {{1, 2, 3},
{4, 5, 6},
• continue can also be used within nested {7, 8, 9}};
loops
• Like break, continue stays within its n_cols = sizeof(input[0]);
block n_rows = sizeof(input) / n_cols;

for (int i = 0; i < n_cols; i++){

for (int j = 0; j < n_rows; j++){

// do something
continue;

}
Flow control - goto
int input[3][3] = {{1, 2, 3},
{4, 5, 6},
• If we want to exit several layers of {7, 8, 9}};
nested blocks at once, we can use goto
• Can simplify highly nested code n_cols = sizeof(input[0]);
n_rows = sizeof(input) / n_cols;
• It is, however, very difficult to debug
when overused for (int i = 0; i < n_cols; i++){
• If you find yourself wanting to use goto,
consider if there isn't a way to refactor your for (int j = 0; j < n_rows; j++){
code or rethink the problem first
// do something
goto exitPoint;

exitPoint: // more code below


Summary
• New data structure
o 1D arrays Attendance Code:
o ND arrays

XX-XX-XX
• Loops
o while
o do-while
o for

• Continue, break and goto

• Arrays and loops together


Assessment FAQs
Question Answer

Do I need to submit my source code? Yes; zipped, as per recent video demo
Do I need to do
flowcharts/pseudocode for every Yes; this is worth as much as the
exercise? source code itself

Do I need to include program banners


in my source code? Yes; see lecture 1 for what to include

When is the first deadline? This Sunday; 25th Feb, 2pm. #1 and #2
None for the progress submissions, yes
What about RAs/extensions? for the final submission

You might also like