Title: Leftovers
1Leftovers
- Why be pedantic?
- Undefined behaviour
- Fun with chars
2Standards
- C is a language, originally written for UNIX but
ported to other environments - Porting involves writing a compiler to translate
C to machine code - Variations crop up among compilers
- Standards have been adopted
- Lowest common denominator
- We use C90, GCC supports much of C99 (not all)
3Undefined
- C standards specify what must be supported
- Some things are left up to the compiler
- Ex leaving variables uninitialized, divide by
zero - Can range from does what you'd think to crash
- Avoid undefined behaviour!
- Especially for portable code!
4Fun with char
- char type is basically an int between 0 and 127
- Printable characters start at 32 (space)
- Digits, lower case letters, upper case letters
each show up in groups - You can do math on these
char x 'a' 2 char y 65 char digit
'6' int value digit '0' char upper
'B' char lower upper 32
5ArraysFunction Design
6Outcomes Arrays
- The C Programming Language, Sections 1.6, 5.7
- Other textbooks on C on reserve
- After the conclusion of this section you should
be able to - Declare, initialize, and traverse C arrays
- Pass arrays to functions
- Start working with multidimensional arrays
7One-dimensional Arrays
- C arrays
- have a lower bound equal to zero
- are static - their size must be known at compile
time. - To define an array
- type arrayNamesize
- For example
- int id1000
- define SIZE 10
- double scoresSIZE1
8One-dimensional Arrays
- It is good programming practice to define size of
an array with a macro - define N 100
- ...
- int aN
- for (i0, sum0 i lt N i)
- sum ai
- Avoids error of falling off end of array
-
Idiom!
9Array Initialization
- Most common form
- int a10 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
- If list of initializers is shorter, remaining
elements initialized to zero. - int a10 1, 2, 3, 4, 5, 6
- Can omit length of array when initializing
- int a 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
10Array Subscripting
- aexpr, when expr is an integer expression
- aexpr can be used in same way as ordinary
variables - a0 1
- printf("d\n", a5)
- aiN j 42
- ai
- Other idioms with for loops
- for (i0 i lt N i)
- ai 0 / clears a /
- for (i0 i lt N i)
- scanf("d", ai) / reads data into a /
11Array Subscripting
- C doesn't require that subscript bounds be
checked! - int aN,i
- for (i0 i lt N i)
- ai 0
- Will compile and run, but could cause infinite
loop!
12include ltstdio.hgt int main() int i0, j,
a5 printf("enter some integers,followed by D
on blank line ") while(scanf("d",ai)
1) i for(j 0 j lt i j) printf("d
",aj) printf("\n") return 0
Try it with more than 5 integers!
13Using sizeof with Arrays
- sizeof gives number of bytes of argument
- int a20
- sizeof(a) \ 20sizeof(int) \
- sizeof(a) / sizeof(a0) \ 20 \
- define SIZE(x) (sizeof(x) / sizeof((x)0))
- for (i 0 i lt SIZE(a) i)
- ai 0
14Array errors
- int arrayNameSIZE
- arrayNameSIZE 2 / error /
- int n 3
- double sn wrong size of array must be
constant - s 5 wrong arrays are not l-values
- Side-effects make the result of assignments
involving index expressions implementation
dependent - ai i
15Array Arguments in Functions
- Length of array is left unspecified
- int f(int a)
- ...
- If length is needed, must be specified with extra
parameter - int f(int a, int n)
- ...
- Can't use sizeof to determine length of an array
parameter, as we just did for array variable - int f(int a)
- int len (sizeof(a) / sizeof(a0)) / WRONG
/ - ..
16include ltstdio.hgt int sizeofArray(int
a) int main() int a5 printf("sizeof
int d\nsizeof array a d\n",
(int)sizeof(int),(int)sizeof(a)) printf("si
zeof of array passed to function
d\n", sizeofArray(a)) return 0 int
sizeofArray(int a) return sizeof(a)
17Array Arguments in Functions
- When calling a function with an array argument,
simply pass the array name - define LEN 100
- int f(int a, int n)
- int main()
-
- int g, aLEN
- ...
- g f(a, LEN) / g f(a, LEN) is WRONG /
- ...
-
18- define LEN 100
- ...
- int main()
-
- int bLEN, total
- ...
- total sum_array(b, LEN)
- ...
-
- int sum_array(int a, int n)
-
- int i, sum 0
- for (i 0 i lt n i)
- sum ai
- return sum
19- define LEN 100
- ...
- int main()
-
- int bLEN, total
- ...
- total sum_array(b, 50) / sum first 50 /
- / total sum_array(b, 150) is WRONG! /
- ...
-
- int sum_array(int a, int n)
-
- int i, sum 0
- for (i 0 i lt n i)
- sum ai
- return sum
20Array Arguments in Functions
- When array passed as argument to a function, base
address is passed call-by-value, and not the
array elements themselves. - See pointers (soon!)
- This means arrays that are passed as parameters
to functions can be modified by those functions
21- define LEN 100
- ...
- int main()
-
- int bLEN, total
- ...
- read_array(b, LEN)
- total sum_array(b, LEN)
- ...
-
- void read_array(int a, int n)
-
- int i
- for (i 0 i lt n i)
- scanf("d", ai)
22Multidimensional Arrays
- An array can have any number of dimensions
- Create a two-dimensional array
- int m23
- To access element in row i and column j
- mij
- Arrays stored in row-major order
23Initializing Multidimensional Arrays
- Nest one-dimensional initializers
- int m23 1, 0, 1,0, 1, 0
- Inner braces can be omitted
24Multidimensional Arrays as Parameters
- Only length of first dimension may be omitted
- / call using j sum_array(b, nrows) /
- int sum_array(int aLEN, int n)
-
- int i, j, sum 0
- for (i 0 i lt n i)
- for (j 0 j lt LEN j)
- sum aij
- return sum
-
- Can work around this using pointers (soon!)
25Strings in brief
- Strings are simply an array of characterschar
s Hellochar t10 Hello - Must end with null terminator ('\0')
- Access/modify characters like arrays
- For now
- Declare strings to be big enough
- Use scanf with s to read them in
26String Example
include ltstdio.hgt int main() FILE f char
filename20 / Max length 19 chars / if
(scanf(s, filename) ! 1) fprintf(stderr,
Error reading filename\n) return 1 if
((f fopen(filename, r)) NULL)
fprintf(stderr, Error opening file
s, filename) return 1 ...
27Outcomes Function Design
- Reference Code Complete, Steve McConnell,
Microsoft Press - After the conclusion of this section you should
know what to aim for when designing functions
they should be strongly cohesive and loosely
coupled.
28Cohesion
- How closely are the operations in a function
related? - sin()
- sinAndTan()
- Strong cohesion
- Function should do one thing well and not do
anything else
29Types of Cohesion
- Functional cohesion
- The best kind!
- Sin(), GetCustomerName(), CalcLoanPayment()
- Can be very short
- Sequential cohesion
- Temporal cohesion
- Logical cohesion
- ...
30Sequential Cohesion
- Operations performed in a specific order, share
data from step to step, but don't perform a
complete function - Program Open File, Read File, Perform
Calculations, Output Results, and Close File - DoStep1() DoStep2()
- Open File Output Results
- Read File Close File
- Perform Calculations
31Removing Sequential Cohesion
- Names should have verb object
- GetFileData() MassageData()
- Open File Perform Calculations
- Read File
- OuputFileData()
- Output Results
- Close File
32Temporal Cohesion
- Operations combined in a function because all
done at same time - Startup()
- Best to have this kind of function call other
functions - ReadConfigFile()
- InitializeMemory()
- ShowInitialScreen()
33Logical Cohesion
- Function does one of several things depending on
a control flag parameter - OutputAll(int mode)
- Better to have distinct functions for each
operation - OutputSummary(), OutputReport(),
OutputDetailedReport() - Can still have logically cohesive function call
these
34Coupling
- How strongly functions are related to each other
- Want loose coupling independent functions
- Coupling criteria
- Size (how many variables shared?)
- Intimacy (parameters, global data, files)
- Visibility (coupling by global data is sneaky)
- Flexibility (how easily can connections be
changed?)
35Levels of Coupling
- Data coupling
- simple data
- data structures
- Control coupling
- One function controls the logic of another
function (i.e. by passing control parameters) - Global data coupling
- tolerable if global data is read-only, or if
global data couples closely related functions in
a module
36Why Loose Coupling?
- Reduces program complexity, allowing programmer
to focus on one thing at a time. - If functions are too closely coupled then
complexity is not reduced.
37/ Read floats from stdin. Output those that
are greater or equal than average Version 1
no functions other than main / include
ltstdio.hgt define SIZE 10 int main() float
listSIZE, avg 0.0 int i for (i0 i
lt SIZE i) if(scanf("f", listi) !
1) fprintf(stderr,"invalid number\n") return
1 for (i 0 i lt SIZE i) avg
listi avg / i for (i0 i lt SIZE
i) if (listi gt avg) printf ("f
", listi) printf ("\n") return 0
38/ Read floats from stdin. Output those that
are greater or equal than average Version 2
first functional decomposition / include
ltstdio.hgt define SIZE 10 float listSIZE,
avg int init() void doStuff1() void
doStuff2() int main() if(init()) doStuff1
() doStuff2() else return 1 return
0
39int init() int i for (i0 i lt SIZE i)
if(scanf("f", listi) ! 1) fprintf(stde
rr,"invalid number\n") return 0 return
1 void doStuff1() int i for (i 0 i lt
SIZE i) avg listi void
doStuff2() int i avg / SIZE for (i0 i lt
SIZE i) if (listi gt avg) printf ("f
", listi) printf ("\n")
40/ Read floats from stdin. Output those that
are greater or equal than average Version 3
second functional decomposition / include
ltstdio.hgt define SIZE 10 int readFloatArray(floa
t list, int size) float averageFloat(float
list, int size) void printGreaterAvg(float
list, int size, float avg) int main()
float listSIZE, avg if(readFloatArray(
list, SIZE)) avg averageFloat(list,
SIZE) printGreaterAvg(list, SIZE,
avg) else return 1 return 0
41int readFloatArray(float list, int size) int
i for (i0 i lt size i) if(scanf("f",
listi) ! 1) fprintf(stderr,"invalid
number\n") return 0 return 1 float
averageFloat(float list, int size) int
i float avg for (i 0 i lt size
i) avg listi avg / i return
avg void printGreaterAvg(float list, int
size, float avg) int i for (i0 i lt size
i) if (listi gt avg) printf ("f ",
listi) printf ("\n")
42void printGreaterAvg(float list, int size,
float avg) int i for (i0 i lt size i)
if (listi gt avg) printf ("f ",
listi) printf ("\n")
43/ Read floats from stdin. Output those that
are greater or equal than average Version 4
third functional decomposition / include
ltstdio.hgt define SIZE 10 define GREATER
1 define LESSER 0 int readFloatArray(float
list, int size) float averageFloat(float
list, int size) void printSome(float list,
int size, int flag, float avg) int main()
float listSIZE, avg if(readFloatArray(l
ist, SIZE)) avg averageFloat(list,
SIZE) printSome(list, SIZE, GREATER,
avg) else return 1 return 0
44void printSome(float list, int size, int flag,
float avg) int i if(flag) / print greater
or equal than avg / for (i0 i lt size i)
if (listi gt avg) printf ("f ",
listi) else / print lesser or equal than
avg / for (i0 i lt size i) if
(listi lt avg) printf ("f ",
listi) printf ("\n")
45Summary
- Most important reason for creating functions
reduce complexity - Complexity easier to manage if functions are
strongly cohesive and loosely coupled - Short functions can be useful
- But don't go overboard use if sequence of
operations should be documented - The name of a function is an indication of its
quality