ENGGEN 131

Introduction to Engineering Computation and Software Development

Course Manual
C Programming Module
Second Semester 2013

Department of Computer Science

ENGGEN 131 SC 2013

This coursebook belongs to:

Name:

ID:

Email:

Lab Session Checklist Lab Lab 7 Tutor's signature (upon completion of lab tasks)

Lab 8

Lab 9

Lab 10

Lab 11

Lab 12

EngGen 131 S2 2013

ENGGEN 131 C Programming
Second Semester
2013

─────────────────────

Contents

─────────────────────

Page Course Outline Lecture 13: An Introduction to C Lecture 14: Types, Operators and Standard I/O Lecture 15: Conditionals, Loops and 1D arrays Lecture 16: 2D arrays, Library Functions and Structures Lecture 17: File I/O and Random Numbers Lecture 18: Functions Lecture 19: Pointers and Strings (Part 1) Lecture 20: Project Discussion Lecture 21: Pointers And Strings (Part 2) Lecture 22: Recursion Lecture 23: Software Engineering Overview Lecture 24: Exam Revision 1 7 15 31 51 67 81 99 115 117 129 141 –

Lab 7: An Introduction to Visual Studio Lab 8: Conditionals, Loops, Arrays and Structures Lab 9: File I/O and Functions Lab 10: Pointers and Strings Lab 11: Project and Strings Lab 12: Recursion and Project Reviews

143 159 175 193 207 221

Course Manual (C Programming)

EngGen 131 S2 2013

Feedback Any and all feedback on this coursebook is welcome. Please send all corrections, comments and other feedback to paul@cs.auckland.ac.nz Thank you!

Paul Denny September, 2013

Course Manual (C Programming)

auckland. Resources ──────────────────────────────────────────────── Cecil All of the material for this section of the course is available on Cecil: http://cecil. This part of the course is an introduction to the C programming language.auckland. 87087 Content ────────────────────────────────────────────────── Welcome to the second half of the ENGGEN 131 course for 2013. It’s great to have you with us! The numbering of the Lectures and Labs in this course book is a continuation from the MATLAB coursebook (we begin with Lab 7 and Lecture 13). It will be assumed that you are familiar with the principles of programming covered in the first section of the course using MATLAB.nz Forums We are using Piazza as a class forum this semester.ac. Computer Science Building (Building 303 S) paul@cs.cloudcoder.EngGen 131 S2 2013 ENGGEN 131 – C Programming: Course Outline 2013 Contact ────────────────────────────────────────────────── Paul Denny Room: Email: Phone: 465.org/cloudcoder Course Outline –1– Course Manual (C Programming) .ac.com CloudCoder You will be using CloudCoder to practice writing short fragments of C code (practice makes perfect!) https://auckland. This is the best place for you to ask questions and discuss the course content: https://piazza.nz 3737599 xtn.

you may use any ANSI C compiler you like. but the following environments are recommended: Windows: Microsoft provides “Express” versions of Visual Studio for free.org/ Mac: XCode Apple provides support for GCC in the standard XCode development environment http://www. we will be using Microsoft Visual Studio Professional Edition.EngGen 131 S2 2013 Aropä – the peer review system The Aropä peer review system is available at: https://aropa.nz You will use Aropä to submit your project and to review the projects of your peers.com/visualstudio/eng/downloads Linux: GNU Compiler Collection GCC comes standard with all major Linux distributions http://gcc. Visual C++ 2010 Express This version is perfectly fine for this course. but you may have to look a little harder to find the 2010 version): http://www. but make sure you get the version for “Windows Desktop”. These will provide you with an environment similar to what you have in the labs. Programming environments In the labs. try not to be overwhelmed by all the different varieties. Use the following download link to obtain either version (of course you can search for them as well. this is your only choice if you are running a version of Windows prior to 7. However.microsoft. If you would like to download one of these versions.gnu.ac.apple. depending on whether or not you are running Windows 7 or later: Visual Studio Express 2012 for Windows Desktop This is the most recent Express version. There really are just two versions you can choose from that meet the requirements of this course. At home.ec. Also.auckland. which is what we are using) and has a more modern look and feel than the 2010 version.com/macosx/developers/ Course Outline –2– Course Manual (C Programming) . you will need to be running either Windows 7 or Windows 8 to install this version. This version supports multiple languages (including C.

Loops and 1D arrays Lecture 16 2D Arrays. 10:00pm Lecture 23 Software Engineering Overview Lecture 24 Revision Lab 12 Recursion and Project Reviews Discussion and Exercises Peer review Friday 25th Oct. Loops. 10:00pm Course Outline –3– Course Manual (C Programming) . Library functions and Structures Lab 8 Conditionals.EngGen 131 S2 2013 Timetable ──────────────────────────────────────────────── The following timetable gives an overview of the final 6 weeks of the EngGen 131 course. 10:00pm Lecture 19 Pointers and Strings (Part 1) Lecture 20 Project Discussion Lab 10 Pointers and Strings Discussion and Exercises TEST (in class) Week 11 (14th – 18th Oct) Lecture 21 Pointers and Strings (Part 2) Lecture 22 Recursion Lab 11 Project and Strings Discussion and Exercises Week 12 (21 – 25th Oct) st Project Due Sun 20th Oct. Arrays and Structures Discussion and Exercises Lecture 17 Week 9 File I/O and Random (30th Sept – 4th Oct) Numbers Lecture 18 Functions Lab 9 File I/O and Functions Discussion and Exercises Week 10 (7th – 11th Oct) CloudCoder Sun 6th Oct. Operators and Standard I/O Lab 7 An Introduction to Visual Studio Discussion and Exercises Week 8 rd (23 – 27th Sept) Lecture 15 Conditionals. Week Lecture 1 (Monday) Lecture 2 (Tuesday) Lab (Tuesday .Friday) Lecture 3 (Friday) Week 7 (16 – 20th Sept) th Lecture 13 An Introduction to C Lecture 14 Types.

Exam (worth 25%) The final exam contributes 50% to your final grade. The test will consist of multiple-choice questions and will contribute 5% to your final grade. You must finish the peer review by 10:00pm Friday 25th October. In order to get credit for this assessment. and 50% of the exam will cover this section of the course. will be available once the module begins. You must submit the project via Aropä before 10:00pm. Please attend your scheduled lecture time on this day. Sunday 20th October. Test (worth 5%) The test for this section of the course will be held on Friday 11th October in the lecture time. This peer review will begin during Lab 12 (from 22nd – 25th October) and will use Aropä. and a link to it from Cecil. you need to complete a peer review (contributing 2% towards your final grade) which involves reviewing the code produced by other students in the class. worth a total of 6%. The exam for the C programming section of the course will be multiple-choice. More information about CloudCoder. with an emphasis on the material in the labs and the project. Completing the exercises on CloudCoder will contribute 2% towards your final grade. Course Outline –4– Course Manual (C Programming) . The goal here is to focus on simple exercises first to increase your confidence and familiarity with C syntax. CloudCoder (worth 2%) We will be using a tool called CloudCoder to give you practice writing short fragments of code. before moving on to more complex problems.EngGen 131 S2 2013 Assessment ─────────────────────────────────────────────── The assessment for this section of the course (contributing 50% towards your final grade) consists of the following: Labs (worth 6%) There are 6 lab sessions supporting the material taught in this section of the course. Project (worth 10%) and Peer Review (worth 2%) The project for this section of the course contributes 10% towards your final grade.

EngGen 131 S2 2013 Function Summary ──────────────────────────────────────── The following list summarises some of the ANSI C functions that you may find useful. <stdlib. Course Outline –5– Course Manual (C Programming) . char *mode). int fgetc(FILE *stream). .. c). void srand(unsigned int seed).h> int toupper(int int tolower(int int isdigit(int int isalpha(int c).. <string.. int strcmp(const char *s. char *format. <stdio.. unsigned long strlen(char *s). int putchar(int c). int fclose(FILE *stream). char *t). double sin(double x).h> char *strcpy(char *s. and the corresponding header files. double y).h> int rand(void). char *strcat(char *s. int fscanf(FILE *stream. c). . void *malloc(unsigned long size)..h> double sqrt(double x).).h> int printf(char *format. . c). <math. char *gets(char *s). char *format. int getchar(void).). double pow(double x.).). .. void free(void *p). FILE *fopen(char *filename.. int scanf(char *format. char *t).. char *t). int fprintf(FILE *stream. <ctype.

EngGen 131 S2 2013

Style Summary ───────────────────────────────────────────
The following are recommended guidelines for the programming style that you should follow for this course. You are welcome to use other styles if you wish, as long as you are consistent. Variable identifiers The first letter should be lower case, and the first letter of subsequent words should be upper case: int numberOfStudents; double taxRate; Function identifiers Identifiers for functions from the standard library are entirely in lower case. For functions that we define, the first letter should be upper case, as should the first letter of subsequent words: int SumArray(int values[]) Braces for functions The opening brace should be on a line by itself, immediately below the line which defines the functions return type, name and parameters. The closing brace should be on a line by itself and line up with opening brace: int main(void) { <statements...> } Braces for other blocks of code The opening brace should be on the same line as the statement which begins the block. The closing brace should be on a line by itself, lined up with the first character of the statement which begins the block: if (i < 10) { <statements...> } Indentation All statements between an opening and closing brace should be indented by one level using a tab character: int main(void) { int a = 10; if (a < 10) { printf("ok\n"); } return 0; }

──────────────────────────────
–6–

Course Outline

Course Manual (C Programming)

EngGen 131 S2 2013

Lecture 13: An Introduction to C
By now, you already know how to program. The language that was used to introduce you to the principles of programming was MATLAB, which provides excellent support for matrix manipulation and the plotting of functions and data. You have learnt how to use variables, and how to write programs that implement algorithms requiring conditionals, loops and arrays. You have used many of the powerful functions that come standard with the MATLAB library, and you have defined your own functions to decompose a program into simple pieces. Now, we are going to learn another language – the C programming language. Many of the ideas will be similar, particularly those involving basic arithmetic operators and control flow (loops, conditionals, and the mechanics of function calling), however there are a number of differences; some major and others quite subtle.

MATLAB vs. C ───────────────────────────────────────────
Your first question might be "why are we learning a new language?" Depending on the problem you are trying to solve, it makes sense to use the most appropriate tool. There are some things that we can do more effectively using MATLAB, and there are other things that we can do more effectively using C. For many simple programs, it doesn't make much difference which language we use. A few comparisons between the two languages are made below. Speed Programs written in C typically execute much more quickly than programs written in MATLAB. The reason for this is that C is a compiled language, whereas MATLAB is an interpreted language. C is a compiled language. In order to run a C program, the source code (that we write) is first entirely converted by a program called a compiler into binary code. This binary code is targeted specifically for the processor and operating system on which the program is to be run. The main advantage of using a compiled language is the performance of the resulting program. MATLAB is an interpreted language. When a MATLAB program executes, each instruction in the source code (that we write) is translated to an appropriate set of binary instructions which are then executed on the processor. This translation step takes place for each instruction as the program is running, slowing down the execution. One advantage of interpreting the code is that we can run our programs as soon as we have written them without requiring the compilation process. Another advantage is that if there are any errors in the program, we can be given very useful, specific feedback about where in the source code the error exists.

Lecture 13

–7–

Course Manual (C Programming)

EngGen 131 S2 2013

Syntax There are a number of subtle differences between the syntax of C and the syntax of MATLAB which you will pick up as you learn the language. Some of the differences are: MATLAB denoted by a starting keyword (such as if or for) followed by the ending keyword, end start at 1, and elements are accessed using parentheses, () ~, |, & a variable consists of just a name, and can be used to store any kind of data built-in support for matrices, vectors, and operations on them M-files are either scripts or functions. The name of a function file defines the existence of a function. C denoted by curly braces, {}

code blocks

array indexes logical operators types

matrix operations file organisation

start at 0, and elements are accessed using square brackets, [] !, ||, && a variable consists of a name and a type, and can be used to store only that type of data – the compiler ensures that this is not violated no built-in support for matrices A source file is simply a collection of functions. The definition of a function in the source code defines the existence of the function.

Licensing MATLAB is a proprietary product of The MathWorks, and can only be used by purchasing an appropriate license. On the other hand, there are many freely available compilers and environments for developing C programs.

History C was first developed in 1972 and has influenced many modern languages including C++, C# and Java (in particular, the syntax of these languages is similar to C). MATLAB was initially developed using Fortran in the late 1970s. In the early 1980s, MATLAB was rewritten in the C programming language, and in 1984 The MathWorks was founded.

So, MATLAB or C? MATLAB is perfectly suited to solving numerical problems, particularly involving matrix or vector manipulation. Solutions to these kinds of problems can be developed rapidly in MATLAB, as it provides direct support for matrices and operations on matrices. MATLAB also provides many library functions for producing graphical output, so it is perfect for problems where solutions need to be visualised in the form of graphs or plots. C is suited to problems where speed is critical, as programs written in C can execute very quickly. C is also suitable when it is necessary to have low-level access to computer memory via machine addresses, particularly for embedded systems. Also, if it is necessary to have fine control over defining and manipulating data structures, C is an excellent choice.

Lecture 13

–8–

Course Manual (C Programming)

EngGen 131 S2 2013

ANSI C ──────────────────────────────────────────────────
In 1978, Dennis Ritchie and Brian Kernighan published a book, called "The C Programming Language" which described the features of the language. Although not officially a language specification, this book was used informally as a definition of what features a compiler should support. Compilers were initially developed for many different systems, but often each compiler would provide special features that suited the specific system the compiler was designed for. This meant that any code making use of these special features could not be compiled on another system. However, the ability to easily port code from one system to another is very desirable, and so it became necessary to develop a standard specification for the language, defining all the features that must be supported by a C compiler. In 1989, the American National Standards Institute (ANSI) completed a specification for the language known as ANSI C. With this specification, anyone writing source code adhering to the ANSI C standard could be sure that the code would compile correctly with any compiler that supported the ANSI C standard. In this course, we will be writing code that adheres to the ANSI C standard. ANSI C is supported by almost all of the widely used C compilers.

A first C program ─────────────────────────────────────────
Here is a very short, ANSI compliant, C program which prints out a welcome message. This is a good starting point for some of the simpler programs you will develop in this course: #include <stdio.h> /* This program displays a welcome message */ int main(void) { printf("hello world\n"); return 0; }

Comments ────────────────────────────────────────────────
In MATLAB, to comment a line you would use the % symbol. This meant that all text to the right of the symbol was ignored by the MATLAB interpreter. For example, in the following MATLAB code: % set up constants g = 9.81; length = 1.0; k = g/length;

% acceleration due to gravity % length of the pendulum

all of the text to the right of the % signs is ignored when the program runs. The purpose of including comments is to help anyone that tries to read our code.

Lecture 13

–9–

Course Manual (C Programming)

return 0. In this course. “Controlling complexity is the essence of computer programming. Another language. we are learning C.EngGen 131 S2 2013 In C. These are very similar to the MATLAB style comments. whereas C++ was developed in 1978 by Bjarne Stroustrup. they are supported by many C compilers because of their usefulness. introduced single line comments where everything to the right of the symbol // is ignored by the compiler. Anything between these pair of symbols is treated as a comment and ignored by the compiler. C++. } // prints welcome message Although single line comments are not part of the standard ANSI C specification. C++ is an extension of C (in fact. The C programming language was first developed in 1972 by Dennis Ritchie and Brian Kernighan.Brian Kernighan Lecture 13 – 10 – Course Manual (C Programming) . most C++ compilers will compile C code) that adds a number of features the most important of which is object orientation.” .h> int main(void) { printf("hello world\n"). comments have not only a beginning symbol (/*). For example: #include <stdio. but also a terminating symbol (*/). C and C++ are different languages.

h> /* This program displays a welcome message */ int main(void) { printf("hello world\n"). Once the compiler has finished.c Preprocessor Compiler assembly code Assembler object code Standard C Library Linker Executable hello. C source files are given the suffix ". The diagram below summarises this compilation process: C source file hello. } To run this program. the first thing we have to do is compile it. consider the following program saved in a file called hello.c".c #include <stdio. it should produce an executable file (such as hello.exe file Lecture 13 – 11 – Course Manual (C Programming) .EngGen 131 S2 2013 Compiling a C program ──────────────────────────────────── A C source file is simply a text file. and can be written using any text editor.c: File: hello.exe) which can be run directly. return 0. The detailed process of what happens when you compile a C program is quite complicated. For example. and for the most part we don't need to worry about all of the steps.

It is very common to refer to this entire process (preprocessing. The Linker The final step in the process is where the linker takes all of the object code files produced by the assembler. #define This preprocessor directive is followed by two expressions. This preparation involves: • removing all the comments from the source code (the compiler doesn't need to see the comments. On a Windows machine. executable files have a . Lecture 13 – 12 – Course Manual (C Programming) . which are there only for the benefit of someone reading our code) • interpreting any special preprocessor directives in the source code Preprocessor directives are denoted by the # symbol followed by a command. The Assembler The assembler takes the assembly code from the compiler and translates it to machine language.obj suffix.exe suffix.h suffix). The Result The result of this process is an executable file that contains all the necessary instructions to run the program. object code files have a . The two most common preprocessor directives are: #include This preprocessor directive is followed by the name of a file (which should be a header file with a . and prepares it for the actual compiler. and converts it to assembly code. On a Windows machine. also called object code. yet still human-readable language. The Compiler The C compiler takes the source file that the preprocessor has prepared. It takes a source file as input. assembling and linking) informally as simply "compiling". For example: #define MAX_STUDENTS 500 replaces all occurrences of the text MAX_STUDENTS in the source file by the text 500. where each assembly code instruction corresponds to a particular machine language instruction. For example: #include <stdio.h> inserts the contents of the file stdio.EngGen 131 S2 2013 The Preprocessor The C preprocessor is the first step in the process. and combines them with each other (if the source code in one file has called a function in another file) and with the object files that store the standard library functions (if the source code has called any of the standard library functions) to form a single executable file.h into the source file. This directive is very simple – the preprocessor simply inserts all of the text from the header file into the source file. Assembly code is a low level. This directive does a very basic text search and replace – it replaces all occurrences of the first expression in the source file by the second expression. compiling. The machine language instructions are what the computer actually understands – they are simply patterns of bits that make sense only to a particular type of processor and operating system.

For example.EngGen 131 S2 2013 Running a C program ───────────────────────────────────── Once we have compiled our code. when the program shown above is executed. The printf() function can be used to produce text output – whatever text appears in the quotation marks will be printed out. is reached. The simplest way of producing output is to display some text on the screen. the output would simply be: hello world Lecture 13 – 13 – Course Manual (C Programming) . from top to bottom. in order. the program exits. the main() function is entered. } program exits When the statement: return 0. and every statement in the main function is executed. The printf() function To be useful. and the value 0 (which corresponds to a successful program execution) is returned to the operating system. and in this course we will always be using the following version which does not take any parameters: int main(void) This function is the entry point for the program. there are only two valid ways that the main() function can be defined. When we launch the executable. a program must produce some kind of output. executed return 0. what happens when we run the executable? The main() function Every C program must have a function called main() defined. According to the ANSI standard. program begins int main(void) { statements printf("hello world\n").

Don’t panic – have a look at the line of code and try your best to understand the message. Be patient! ────────────────────────────── Lecture 13 – 14 – Course Manual (C Programming) . sometimes the error messages can be quite cryptic and difficult to understand.obj : error LNK2019: unresolved external symbol _print referenced in function _main hello. Compiler message: hello. } #include <stdio. Compiler message: hello.h> int main(void) { print("hello world\n"). Unfortunately.c(6) : error C2143: syntax error : missing '. Syntax errors are very common – they happen all the time.exe : fatal error LNK1120: 1 unresolved externals #include <stdio. this error is picked up by the linker when it tries to link your compiled code with the standard library (and discovers that “print” doesn’t exist). not single quotation marks Compiler message: hello. Don’t worry if your code has syntax errors – the most important thing is that when you have such errors you are able to locate them and correct them. the compiler picks up syntax errors and will issue an error message that includes the line of code on which the error has occurred. } Syntax error: strings must be surrounded by double quotation marks. Let’s look at a couple of examples: #include <stdio. you will get used to syntax errors and will be able to correct them quickly.c(5) : error C2015: too many characters in constant With experience. } Syntax error: the semi-colon that is required at the end of the line with the printf() is missing. Note: in fact. Fortunately.' before 'return' Syntax error: the “f” is missing from the “printf” function – there is no such function as “print”. return 0.EngGen 131 S2 2013 Syntax errors ───────────────────────────────────────────── A syntax error is an error that occurs when you make a mistake typing the characters that make up your source code.h> int main(void) { printf("hello world\n") return 0. return 0.h> int main(void) { printf('hello world\n').

process and retrieve data. In C. MATLAB >> A = input('Enter a: '). and appropriate conversion specifiers. 100. MATLAB provides the disp() and input() functions for displaying output and getting input from the user respectively. When we create a variable in MATLAB. Learning outcomes ──────────────────────────────────────── After this lecture. We also need to be able to receive input. you should be able to: • • • • • declare a variable of a specific type. Lecture 14 – 15 – Course Manual (C Programming) . The kind of data that a variable can store is defined by the type of the variable.8. >> disp('Hello'). we use variables to store our data.3.EngGen 131 S2 2013 Lecture 14: Types. we not only need to give the variable a name.4. characters and numbers use the scanf() function to read characters and numbers typed by the user at the keyboard MATLAB Comparison ──────────────────────────────────── We have already seen that in MATLAB. and be able to store a value in that variable evaluate simple equations consisting of the arithmetic operators and parentheses cast an expression of one type to another type use the printf() function. to display text. Operators and Standard I/O To write any useful kind of program. All we need to do is think of a name for our variable and then we can store anything we like in it using the assignment operator. an integer.2. a floating point number or even a string. and produce output.7.6. we don't need to consider whether it is going to be used to store a 2D array. The basic arithmetic operators are very similar in MATLAB and in C. we need to be able to store. 'the quick brown fox'. MATLAB >> >> >> >> A B C D = = = = [1.9]. however. (F-32)*5/9. when we want to use a variable. the corresponding functions are printf() and scanf(). but we must also explicitly indicate what kind of data we want the variable to store.5. In C.

we can only store certain types of values in certain types of variables. as well as minutes and seconds) is given in the summary program section at the end of this lecture. The next few pages introduce the basic types. We need to know how to get input from the user. and we will see how to get input and display output. how to perform some sort of simple arithmetic. the number of minutes will be the "whole part" of this division and the number of seconds will be the "remainder". We want to divide the input value by 60. Lecture 14 – 16 – Course Manual (C Programming) .there are four basic types to choose from. In this particular example. or what is left over. Before we can use a variable to store a value. The arithmetic we want to perform is division. However. 125 seconds C Program input output 2 minutes and 5 seconds The algorithm for this problem is pretty straightforward and is illustrated in the flow chart to the left. if the duration is 125 seconds. the choice is not too complicated . we first must specify what type of variable we want. all of the numbers we are working with are whole numbers – we are not dealing with any numbers that consist of a fractional part. Fortunately. we will store this value in a variable. in MATLAB. In C. The completed program for the time conversion example (which includes a conversion to hours. In the output.EngGen 131 S2 2013 Introduction ─────────────────────────────────────────── Let's start with the simple problem of converting a given duration (specified in a total number of seconds) into an equivalent number of minutes and seconds. and how to display output back to the screen. Let's say we want to write a program in C which solves this problem. and explain how to work with variables. then that is equivalent to 2 minutes and 5 seconds. When we read the input value from the user (which in the example above was 125). The arithmetic operators are also introduced. we will want to store this somewhere. Just like in MATLAB. you can store any kind of value in a variable. For example.

and is determined by the fixed amount of storage allocated for that type (for example. we need to pick the correct type for it by keeping in mind what values we need the variable to store Type modifiers In addition to these basic types. the int type cannot represent all of the integers) • when we want to use a variable. to give: short int long int and the unsigned modifier can be applied to char and any of the integer types: unsigned unsigned unsigned unsigned char short int int long int The unsigned modifier indicates that we only want to store positive values in the variable. http://xkcd. and long int is usually abbreviated to long. The type short int is usually abbreviated to just short. which are sometimes referred to as the primitive types.com/ Lecture 14 – 17 – Course Manual (C Programming) . The integer type (int) can be modified with either short or long. a few modifiers exist which can be applied to effectively create a few more types.EngGen 131 S2 2013 The basic types ─────────────────────────────────────────── There are only 4 basic types of variables in C: type char int float double kind of information stored can store an ASCII character can store an integer value (whole number) can store a floating point number (with single precision) can store a floating point number (with double precision) We should keep in mind: • the set of values that each type can represent is finite. and therefore doubles the range of values that can be represented.

followed by a semi-colon: <type> <identifier>.647 0 to 4.967. as well as the range of values that can be stored: type unsigned char unsigned short unsigned int unsigned long float double char short int long typical size (in bytes) 1 1 2 2 4 4 4 4 4 8 range of values that can be stored 0 to 255 -128 to 127 0 to 65535 -32. the most common types that we will use are char.483.648 to 2.767 0 to 4.797693e+308 In general.EngGen 131 S2 2013 Variable sizes The type information tells the compiler how much space in memory to set aside for storing the variable.402823e+38 ±2. the actual number of bytes used for each type is dependent on the compiler and the operating system.147.225074e-308 to ±1.175494e-38 to ±3. double exchangeRate.483.147. the following statements declare three variables: char firstInitial.648 to 2.483.147. int numberOfStudents.647 ±1.147.294. and what name we want the variable to have (called an identifier).768 to 32.967. The following table gives typical numbers.295 -2.294. int and double. For example. char 1 byte int 4 bytes double 8 bytes Declaring a variable ─────────────────────────────────────── We must declare variables before we can use them. Lecture 14 – 18 – Course Manual (C Programming) . but in practice.483. A declaration tells the compiler what type we want the variable to be.295 -2. The ANSI standard defines the minimum number of bytes that are guaranteed to be used to store each type.

Identifier names are case-sensitive. Instead. Variables must be declared at the beginning of a block of statements. Where to declare We cannot declare variables just anywhere. we cannot declare a variable in the middle of a block of statements. It is a good idea to give meaningful names to our identifiers. Therefore. This is quite a common style for naming identifiers. Also notice that each identifier name started with a lower case letter.EngGen 131 S2 2013 The relative sizes of these variables could be visualised accurately as follows: firstInitial 1 byte numberOfStudents 4 bytes exchangeRate 8 bytes although in practice we tend not to visualise the physical sizes of the variables. and the first letter of each subsequent word in the name was in upper case. For example. as illustrated below: int main(void) { <variable declarations> <statements> } Lecture 14 – 19 – Course Manual (C Programming) . we think of every variable as a box of the same size but recognise that they have the capability of storing different ranges of values. Number and NUMBER as distinct identifier names. so be aware that the compiler would regard number. such as a function definition. we chose the identifier names so that they were meaningful and gave an idea of what information the variables were going to store. because it makes it easier for other people to understand our code. we would visualise these three variables as follows: firstInitial numberOfStudents exchangeRate Identifier names In the above example.

. There are different kinds of constants corresponding to the different variable types. When the compiler sees a character constant.0 1. A variable of type char actually stores the ASCII code (which is an integer between 0 and 127) of the character that it represents.6e2 "apple" "A" – the upper case 'A' character – the lower case 'b' character – the newline character – the backslash character – the tab character – the "null" character (totally different to '0') – the numeric value "-45" – the numeric value "260" – can have multiple digits in the fraction – can be positive or negative – the numeric value 160. are of type double by default.EngGen 131 S2 2013 Constants ──────────────────────────────────────────────── A constant is a value that appears in the source code for our program. it is much easier for us to let the compiler do this for us. / 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 0 1 2 3 4 5 6 7 8 9 : . Some examples are shown in the table below: character constants 'A' 'b' '\n' '\' '\t' '###BOT_TEXT###' -45 260 3. Numbers in the source code. < = > ? – 20 – 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 @ A B C D E F G H I J K L M N O 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 P Q R S T U V W X Y Z [ \ ] ^ _ 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ` a b c d e f g h i j k l m n o 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 p q r s t u v w x y z { | } ~ (del) Course Manual (C Programming) .0 – a string consisting of 5 characters – a 1 character string (totally different to 'A') integer constants floating point constants string constants Numbers in the source code. it converts that into the corresponding ASCII code of 65.1416 -15.3. like 5. like 26. are of type int by default. rather than looking up the ASCII codes manually from a table: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Lecture 14 (nul) (soh) (stx) (etx) (eot) (enq) (ack) (bel) (bs) (ht) (nl) (vt) (np) (cr) (so) (si) 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 (dle) (dc1) (dc2) (dc3) (dc4) (nak) (syn) (etb) (can) (em) (sub) (esc) (fs) (gs) (rs) (us) 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 (sp) ! " # $ % & ' ( ) * + . like 'A'. From our point of view.

It is an excellent idea to get into the habit of visualising variables in memory. So this is a good habit to get into early. size 100 Lecture 14 – 21 – Course Manual (C Programming) . exchangeRate = 0. int numberOfStudents. we specify the name of the variable on the left. The type of the value on the right of the assignment operator should match the type of the variable on the left (that the value is being assigned to).EngGen 131 S2 2013 Assignment operator (=) ─────────────────────────────────── The assignment operator in C is the '=' character. and being able to visualise it clearly can make a huge difference in how long it takes us to find errors in our code. To store a value in a variable that has been declared. firstInitial = 'X'. numberOfStudents = 430. and the value to store in it on the right: char firstInitial. We don’t need to declare and initialise a variable in separate statements – it is very common to initialise a variable at the same time that we declare it: int size = 100. double exchangeRate.672 Although this may seem trivial now.672. drawing diagrams of memory is a simple but effective tool when we inevitably have to locate a bug in our program. Each variable is drawn as a box with the current value stored by the variable drawn inside the box: firstInitial 'X' numberOfStudents 430 exchangeRate 0. Sometimes the contents of memory can be quite complex.

The Stack Whenever we call a function. we are not going to be dynamically allocating memory. Instructions The memory for our running program includes the actual binary instructions that were produced by the compiler. As the CPU executes these instructions one at a time. Data Any variables that we declare outside of a function definition are called “global” variables. When we come back to look at global variables later. it is possible for it to request memory to use. This is known as dynamic memory allocation. Memory allocated by these requests is available in an area known as the “heap”. there are special functions such as malloc()for requesting memory. In C. A stack frame stores the values of any variables defined inside the function definition. Lecture 14 – 22 – Course Manual (C Programming) . The diagram below shows a very simplistic view of the memory allocated for our program. For now. which obviously “grows” every time the program requests new memory. When a function finishes executing. The Heap When a program is running. In this course. the operating system allocates memory for the program to use. when you run “hello. the memory it was using on the stack is returned – thus. it will be useful for us to know that they are stored in a separate section of the memory for our running program.EngGen 131 S2 2013 Let’s briefly discuss how our computer’s memory is organised while our C program is running. The memory allocated on the stack when a function is called is known as a “stack frame”. When you execute your program (for example. we say the program “runs”. some memory is allocated for storing information about the function. This memory is placed on the “stack”.exe”). we will only be declaring variables inside of function definitions – these are called “local” variables. the stack grows and shrinks as the program runs and functions begin and end.

We visualise this call to the main() function like a box. we see the variables firstInitial. They are binary codes and wouldn’t make any sense to us anyway. We also are not going to visualise “The Heap” – at least not in this course. We know that the main() function is always called when our program starts. In this case.672. let’s understand the fundamentals really well first. int numberOfStudents. There will be plenty of time to learn this later. labelled with “main()”. Let’s now consider the following complete C program: #include <stdio.EngGen 131 S2 2013 The previous description was a little abstract. there is nothing in the “Data” area. numberOfStudents. } We will visualise the memory allocated for this running program as follows: NOTE: We are not going to visualise the “Instructions”. return 0. firstInitial = 'X'.h> int main(void) { char firstInitial. double exchangeRate. exchangeRate = 0. numberOfStudents = 430. In the diagram to the left. and exchangeRate. What we can see is that the main() function has been called (it appears on the stack). We will learn about global variables later in the course. Lecture 14 – 23 – Course Manual (C Programming) . and inside the box are the variables declared inside the function definition. because we will not be allocating memory dynamically. That is because there are no “global” variables declared.

to a as well. and then assigns the result of that expression. Type combination If two different types are combined in an arithmetic expression. The result is the same type as the operands.e.0). it will be promoted to 12. from largest to smallest. which is equivalent to a = (b = 0). such as: a = b = 0. Arithmetic operators ────────────────────────────────────── The following basic mathematical operators are available: + * / % – addition – subtraction – multiplication – division (the result is an integer if both operands are integers) – modulus (or remainder – applies only to integers) The operators apply to operands of the same type. consider the expression: 12 + 5.EngGen 131 S2 2013 Assignment expressions The assignment operator also acts like an expression – the expression evaluates to whatever value was assigned to the variable. because a smaller type is always promoted to a larger type. the smaller type is the int type (the constant 12) which will be promoted to double before the addition is performed (i. This assigns the value 0 to b. is summarised below: largest: double float long int short char smallest: For example. The expression will therefore evaluate to 17.5 Here.5. An ordering of the basic types. the compiler will automatically promote the smaller type to the larger type. No information is lost in a promotion. We sometimes see this value being used as part of a larger expression. 0. Lecture 14 – 24 – Course Manual (C Programming) .

where <expression> can be any expression. and the value 17 would be assigned to a. a. The general form of a cast is below. and <type> is the type to convert the expression into: (type)<expression> For example: int a. a = (int)(12 + 5. The compiler will issue a warning about this.5.operators increment or decrement the value in a variable. the right hand side of the assignment evaluates to 17.5 (as the 12 is promoted to the double value 12. such as: warning '=' : conversion from 'double' to 'int'. a = 12 + 5. Unary operators The unary ++ and -. printf("%d %d". a double value cannot be assigned to an int variable because the fractional part of the number can not be stored. b). would produce the output: 11 9 Lecture 14 – 25 – Course Manual (C Programming) . For example.0 before the addition takes place). b--. However. int b = 10. The statement: a++.5). the statements: int a = 10. would now compile without warning. possible loss of data There are some situations where we would like to force a conversion from one type to another (such as from a larger type to a smaller type). a++. We tell the compiler that we want the conversion to take place by using a cast. has the same effect as the explicit arithmetic and assignment: a = a + 1.EngGen 131 S2 2013 Casting So what would happen in the following expression? int a. A cast from type double to type int simply truncates the fractional part of the number – no rounding is performed. In this case.

we could either use: a = a + 15. The shorthand assignment operators are: +=. when an expression consists of multiple arithmetic operators of the same precedence. there is a corresponding shorthand assignment operator.5).EngGen 131 S2 2013 Special assignment operators For each of the mathematical operators.-1. int a = 8.(4 .(4 .-1. -=.-1. evaluation takes place from left to right int a = 1 + 6 . %= Operator precedence The precedence of the operators is summarised in the table below: () ++ * + = += -= / *= /= -% increasing order of precedence For example. the statement: int a = 1 + 2 * 3 .5). as the operators would be evaluated in the following order: int a = 1 + 2 * 3 . would assign the value 8 to the variable a. to add 15 to the value of variable a. /=. int a = 7 . or we could use the shorthand operator: a += 15. For example. *=. int a = 1 + 2 * 3 . Lecture 14 – 26 – Course Manual (C Programming) .

as well as conversion specifiers which correspond to additional values that are going to be printed. . In order to use either of these functions. i.h> printf() Formatted output is produced using the printf() function.46 We must make sure that the type of each conversion specifier matches the type of the corresponding value to be displayed. d).prec]type where flags width . <values>. the output will not be correct.. printf("Value: %d %. printf(<format string>. will print: Value: -75 123.. Lecture 14 – 27 – Course Manual (C Programming) . and to read input from the keyboard we can use the scanf() function. we need to have the following preprocessor directive at the top of our source file: #include <stdio.prec type : left justify the output + : display the sign of number minimum size of the output field the number of digits to display the type of value these attributes are optional and where the most common values for type are: %d %u %f %s %c signed integer unsigned integer floating point number (float or double) string character For example: int i = -75.).456. The format string contains the text to be printed out. we use the printf() function. Each conversion specifier has the following general form: %[flags][width][. If the types do not match.EngGen 131 S2 2013 Standard Input and Output ──────────────────────────────── To produce output to the screen. double d = 123.2f".

we get a warning message from the compiler similar to the following: warning C4996: 'scanf': This function or variable may be unsafe. In order for this to work however. use _CRT_SECURE_NO_WARNINGS.2 then the variable i will store 55 and the variable d will store 6. As with printf(). See online help for details. We must make sure that the type of each conversion specifier matches the type of the corresponding variable being initialised. double d. the scanf() function needs to know the address of each variable. Consider using scanf_s instead. double and float have different specifiers The scanf() function will read values typed in at the keyboard and store them in the variables that are specified as arguments to scanf(). it is sometimes considered to be unsafe as it is known to be vulnerable to certain kinds of security attacks known as buffer overflows. with common values being: %d %u %f %lf %s %c signed integer unsigned integer float double string character note. Although scanf() is an ANSI C function. scanf("%d %lf".. so it is perfectly safe for us to use. If the types do not match. Lecture 14 – 28 – Course Manual (C Programming) . which appears immediately to the left of the variable name. the format string contains conversion specifiers which correspond to each of the values that are going to be input. scanf(<format string>.2. if the user types the following at the keyboard when the program is run: 55 6. This information is obtained using the address operator. To disable deprecation. the variable will be initialised incorrectly.). &. <address>. consider the code: int i.EngGen 131 S2 2013 scanf() Input from the keyboard can be obtained using the scanf() function. Visual Studio and scanf() If we call the scanf() function in the Visual Studio environment.. &i. &d). . The programs that we write in this course will not be susceptible to these kinds of problems. These specifiers indicate the type of value that is to be read. For example.

scanf("%d". Visual Studio provides a simple solution to this. printf("%d seconds is %d hours. seconds = leftOverSeconds % SECONDS_PER_MINUTE. For example. hours = input / SECONDS_PER_HOUR. input. hours. minutes. leftOverSeconds. If we add the following preprocessor directive: #define _CRT_SECURE_NO_WARNINGS as the very first line of code in our source file (before any of the #include directives) then this warning will not be issued by the compiler. #define _CRT_SECURE_NO_WARNINGS #include <stdio.EngGen 131 S2 2013 However. leftOverSeconds = input % SECONDS_PER_HOUR. printf("Enter duration (secs): "). minutes. ────────────────────────────── – 29 – Lecture 14 Course Manual (C Programming) .h> #define SECONDS_PER_MINUTE 60 #define SECONDS_PER_HOUR 3600 int main(void) { int input. and then display the results to the screen. 25 minutes and 45 seconds. %d minutes and %d seconds. seconds). &input). it is not nice to have the warning appear whenever we compile our code. process that input using the standard arithmetic operators. return 0.\n". hours. } An example of this program running is given below (user input is in bold): Enter duration (secs): 12345 12345 seconds is 3 hours. Lecture 14 Summary Program ───────────────────────────── We can now write programs that receive input from the user. the following program converts a period of time specified by the user in seconds. minutes = leftOverSeconds / SECONDS_PER_MINUTE. to hours minutes and seconds. seconds.

com/ Lecture 14 – 30 – Course Manual (C Programming) .EngGen 131 S2 2013 http://xkcd.

EngGen 131 S2 2013

Lecture 15: Conditionals, Loops and 1D arrays
With the programs we have seen so far, the statements in the main() function are executed in order, from top to bottom. We can modify the flow of control of our programs by using conditionals and loops, and we can use arrays to store and process large collections of data.

Learning outcomes ────────────────────────────────────────
After this lecture, you should be able to: • • • • • evaluate boolean expressions consisting of the relational and logical operators use an if statement to conditionally execute a block of code use both while and for loops to repetitively execute blocks of code declare and initialise a one-dimensional array variable in a single statement write a loop which iterates over a one-dimensional array

MATLAB Comparison ────────────────────────────────────
MATLAB provides statements for performing conditional execution (IF) and loops (FOR, WHILE).
MATLAB

IF expression statements ELSEIF expression statements ELSE statements END

FOR variable = expr statement statement END

WHILE expression statements END

C has corresponding statements, but with some syntax differences. MATLAB provides built-in support for working with collections of values. Defining vectors or matrices is trivial, and the arithmetic operators are designed to work automatically with such structures. For example, two vectors can be initialised and then added as follows:
MATLAB

>> a = [1 2 3]; >> b = [4 5 6]; >> c = a + b c = 5 7 9

In C, there is no automatic support for working with anything except the basic types. If we need to store a large collection of data, we should use an array. There are no built-in operations that we can use to process the data in an array, instead we must define the code that processes them.
Lecture 15

– 31 –

Course Manual (C Programming)

EngGen 131 S2 2013

Booleans in C ─────────────────────────────────────────────
C does not have an explicit boolean type. Instead, the language treats the integer value 0 as false, and any non-zero integer value (although 1 is typically chosen) as true. Any integer expression can therefore be used as a condition. Conditions can be composed of expressions combined with the relational operators: == != < <= > >= equal not equal less than less than or equal greater than greater than or equal

Expressions involving the relational operators always evaluate to either 0 (for false) or 1 (for true). Consider the following example: int value; value = (11 == 12); printf("%d\n", value); value = (11 <= 12); printf("%d\n", value); value = (11 != 12); printf("%d\n", value); The output of the code to the left would be: 0 1 1

Conditions can be combined using the logical operators: && || ! and or not

Again, the logical operators always evaluate to either 0 (for false) or 1 (for true). The first two operators, && and ||, take two operands, whereas the ! operator takes just one. Order of precedence: If parentheses are not used to enforce order of evaluation, the order of precedence of the logical operators is: ! (highest precedence) && || (lowest precedence) For example: int value; value = !(5 < 6) && (3 == (1 + 2)); printf("%d\n", value);
– 32 –

The output of the code to the left would be: 0
Course Manual (C Programming)

Lecture 15

EngGen 131 S2 2013

Selection statements ───────────────────────────────────────
C uses curly braces { } to denote blocks of code. The basic if statement has the following syntax: if ( <expression> ) <statement> First, the <expression> is evaluated. If it is true, then the <statement> is executed, otherwise the <statement> is not executed. As an example: int value = 9; if ((value >= 20) || (value < 10)) printf("Value = %d", value); would print: Value = 9 Whereas: int value = 9; if ((value >= 20) && (value < 10)) printf("Value = %d", value); would not produce any output. Multiple statements If there are multiple statements in the block, then curly braces are mandatory: if ( <expression> ) { <statement> <statement> <statement> } A common mistake is to forget to include the curly braces when there is more than one statement in the block. Be aware that indentation is ignored by the compiler – its purpose is to make the logical organisation of the code easier for us to read and understand. So the following code: if (1 == 2) printf("Never printed"); printf("Always printed"); would always print "Always printed" despite the fact the condition is obviously false.

To avoid such problems, it is a good idea to get into the habit of always including the braces around blocks of code, even if they only consist of a single line.
Lecture 15

– 33 –

Course Manual (C Programming)

EngGen 131 S2 2013

An else clause can also be included, and will be executed if the condition is false: if ( <expression> ) { <statement> <statement> } else { <statement> <statement> } Again, if there is only a single statement in the block, then the curly braces are not necessary: if (1 == 2) printf("Never printed"); else printf("Always printed"); However, be careful – the following code will not compile because the second printf() statement appears outside of the if clause, and hence when the compiler encounters the else statement there is no corresponding if. In this case, curly braces are necessary to denote the blocks. if (1 == 2) printf("Never printed"); printf("This code won't compile"); else printf("Always printed");

won't compile

To avoid these kinds of problems, it is a good idea to always include braces explicitly around blocks of code – even if the block consists of only a single statement. else if A common combination of if and else occurs when there are a number of conditions to be tested, and only one will be true. if ( <expression-1> ) { <statement> <statement> } else if (<expression-2>) { <statement> <statement> } else if (<expression-3>) { <statement> <statement> } else { <statement> <statement> } With if, else if, else statements, only one of the blocks of statements will be executed. To the right is an example, where only the statements in the else clause will be executed.
Lecture 15

if (1 == 2) { printf("Not printed"); printf("Not printed"); } else if (2 == 3) { printf("Not printed"); } else { printf("1 does not equal 2"); printf("and 2 does not equal 3"); } – 34 –
Course Manual (C Programming)

return 0. an exam mark is valid if it is between 0 and 100 inclusive: File: exam.h> int main(void) { int examMark. Lecture 15 – 35 – Course Manual (C Programming) . scanf("%d". else printf("the exam mark must be between 0 and 100").EngGen 131 S2 2013 Consider the following program which asks the user to enter an exam mark. } Notice that the conditional test: if ((examMark >= 0) && (examMark <= 100)) determines whether or not the exam mark lies between 0 and 100 inclusive by testing two separate conditions: "examMark is greater than or equal to zero AND examMark is less than or equal to 100" Warning – be careful Consider what would happen if the conditional test in the previous program was written as: if (0 <= examMark <= 100) which looks correct from a mathematical point of view. the compiler interprets the expression as: (0 <= examMark) <= 100 In this case. and then displays whether or not the exam mark is valid.c #define _CRT_SECURE_NO_WARNINGS #include <stdio. examMark). so the expression: 0 <= examMark <= 100 will always evaluate to true. but this result is always going to be less than 100. printf("Enter exam mark: "). regardless of the value of examMark. because the relational operators will be evaluated from left to right. &examMark). For the purposes of this program. if ((examMark >= 0) && (examMark <= 100)) printf("%d is valid". In this case. the condition (0 <= examMark) will always evaluate to either 0 or 1 (depending on the value of examMark).

The general form is below: <expression1> ? <expression2> : <expression3> First. else printf("%d apples\n". An equivalent way of doing this would involve using the conditional operator as follows: printf("%d apple%s\n".EngGen 131 S2 2013 Conditional operator (NOT EXAMINABLE) C provides a special conditional operator which can be used in place of simple if/else statements. break. If it is true. case value2: statements. (apples == 1) ? "" : "s"). otherwise expression3 is evaluated and becomes the result of the statement. The general form is: switch ( <expression> ) { case value1: statements. switch statement (NOT EXAMINABLE) A switch statement can often be clearer than a series of if/else statements. expression1 is evaluated. break. default: statements. For example. then expression2 is evaluated and becomes the result of the statement. } • • • • The controlling expression must be an integer expression The case values must be unique and they must be constants Once a case is matched.. . unless a break has been encountered Lecture 15 – 36 – Course Manual (C Programming) . all following statements are executed until a break is encountered The default statements are always executed. break. It also prints out the word "apple" and uses an if else statement to decide whether or not to add an "s": if (apples == 1) printf("1 apple\n"). apples). consider the following code which prints out the value stored in the variable apples which is of type int.. apples.

scanf("%c". } "excellent" ). "ok but " ). "good" ). default: printf( break. two printf() statements were executed because there is no break statement in the case 'C' clause. case 'C': printf( case 'D': printf( break. switch( grade ) { case 'A': printf( break. Output from this code segment is below (user input is in bold): Enter your grade: A excellent Enter your grade: B good Enter your grade: C ok but you must do better Enter your grade: D you must do better Enter your grade: X are you sure?? Notice that when the input was 'C'. printf("Enter your grade: "). &grade). case 'B': printf( break.EngGen 131 S2 2013 For example. "you must do better" ). Lecture 15 – 37 – Course Manual (C Programming) . consider the following code: char grade. "are you sure??" ).

i). <statement>. < statement >.EngGen 131 S2 2013 Loops ──────────────────────────────────────────────────── C provides syntax for three different kinds of loops (for. Of the three different kinds of loops. except the condition is tested at the end of the loop rather than at the start (this is useful if the body of the loop needs to be executed once before the condition is tested): < initialisation > do { < statement >. < increment >. } do A do loop is very similar to a while loop. for int i. <increment> ) { <statement>. i < 5. < increment >. i++. } while int i. while and do). do do { printf("%d ". for (i = 0. for and while loops are the most commonly used. i++) { printf("%d ". < statement >. while (i < 5) { printf("%d ". i++. } for A for loop combines the standard initialisation. i = 0. } int i. while A while loop has the following syntax: < initialisation > while ( < condition > ) { < statement >. i = 0. i). } while ( < condition > ). The following table shows a comparison of the three loop styles. i). < condition > . } while (i < 5). These loops are equivalent – in each case the output is a single line displaying the values: 0 1 2 3 4 Lecture 15 – 38 – Course Manual (C Programming) . condition and increment into its syntax: for ( <initialisation> .

. Another way this code could be written would be to use a break statement in the body of the loop. } Consider the following loop. when used inside the body of a loop. i++.EngGen 131 S2 2013 break and continue Sometimes.. or stop executing the remaining statements in the body of the loop and simply jump back to the top of the loop and test the condition again. break. by testing to see if it is divisible by any number less than itself (starting from 2): i = 2. it simplifies the loop condition. continue. Lecture 15 – 39 – Course Manual (C Programming) . } if (i == value) printf("%d is a prime number\n". allow us to do these things as shown in the diagram below. The keywords break and continue. when the body of a loop is executing. else printf("%d is not a prime number\n". This has advantages and disadvantages: while it complicates the body of the loop.) { .. else printf("%d is not a prime number\n". while ((i < value) && (value % i != 0)) { i++. value). which determines whether the value stored in the variable value is a prime number. } while (.. value)....) { . . .. i = 2.. while (i < value) { if (value % i == 0) break.. value). value). } if (i == value) printf("%d is a prime number\n".. while (.. we might encounter a situation where we would like to either jump out of the loop completely.

In order to use an array in your program. We can visualise this array in memory as follows: numbers 0 1 2 3 4 5 6 7 Lecture 15 – 40 – Course Manual (C Programming) .. this will allocate a contiguous block of memory that is made up of individual int variables..EngGen 131 S2 2013 One-dimensional arrays ─────────────────────────────────── Arrays store a collection of variables of the same type. . return 0. } In either case. The value of <size> must be a constant integer value. and the individual elements can be accessed through the identifier and a subscript. .. we could use a #define preprocessor directive: #define MAX_INPUTS 8 int main(void) { int numbers[MAX_INPUTS]. it must first be declared.... An array has an identifier. } Or. perhaps a better idea in terms of code style. return 0. For example. like any other type of variable. Declaring an array The general form of declaring an array is as follows: <type> <identifier>[<size>].. we could declare an array called numbers consisting of 8 elements using a constant as follows: int main(void) { int numbers[8].. . .

Also. introduced a feature known as variable length arrays. For this reason. However. in this course do not write code that uses variable length arrays. In particular. return 0. Lecture 15 The compiler will issue an error: error: expected constant expression – 41 – Course Manual (C Programming) . which does allow code like the example above where the size of the array is determined at run-time based on the value stored in a variable. the compiler does not verify this and won’t allow the code to compile. Due to this limitation. } Although it is obvious to us that in the above example the value stored in x is 100. known as C99. These values may. malloc() in which case the memory is allocated on the heap rather than the stack). in this course we will not be considering dynamic memory allocation.EngGen 131 S2 2013 You cannot assume that the values initially stored in the array elements are 0. as in the diagram on the right. notably the Microsoft compiler (cl) used in this course. . Warning: variable length arrays An update to the original ANSI C standard.. in fact. we would visualise it as part of the memory allocated for the main() function. int values[x]. so that their size can be determined and modified while the program is running. be random and so you must initialise the elements in the array before you use them (initialisation is introduced shortly). numbers ? 0 ? 1 ? 2 ? 3 ? 4 ? 5 ? 6 ? 7 The memory for the array is allocated when the main() function is called. it is quite common for programmers to create arrays dynamically (using. for example. Therefore we need to carefully decide what the most appropriate size for the array is at the time we declare it in our code. however it is not supported by all compilers. Some compilers (such as gcc) do support this feature. it cannot be a variable as in the incorrect example below: int main(void) { int x = 100. because the size of the array is specified in the array declaration. Note that in the array declaration.. it cannot be resized or made larger. the size of the array must be a constant. Like any other variable that is declared inside the definition of the main() function.

as this sets the value of the first element of the array (an int variable) to be the sum of the next two elements (both int variables). For example. of the element we want. Consider the following array: numbers 3 0 1 1 6 2 2 3 5 4 9 5 7 6 8 7 After the expression: numbers[0] = numbers[1] + numbers[2]. the sum 7 would be stored in index position 0: numbers 7 0 1 1 6 2 2 3 5 4 9 5 7 6 8 7 Lecture 15 – 42 – Course Manual (C Programming) . we use square brackets and we specify the index. is executed. the following expression is perfectly valid: numbers[0] = numbers[1] + numbers[2]. numbers 0 1 2 3 4 5 6 7 numbers[1] Each element of this array is simply a variable of type int. or subscript. We can therefore refer to an element of this array in any situation where it makes sense to have a variable of type int.EngGen 131 S2 2013 Accessing array elements To access an individual element in an array.

0. Lecture 15 – 43 – Course Manual (C Programming) . 0. assume we tried to access the element at index 20 in the above array: numbers[20] = 2. 0. then the remaining values are filled in with zero. For example. However. 3. by surrounding the values in curly braces {} and separating them with commas. sets aside space for 20 ints in the numbers array which are all initialised to zero: numbers 7 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 0 0 0 0 0 0 0 0 0 0 9 10 11 12 13 14 15 16 17 18 19 Warning – be careful We must be very careful not to attempt to access a non-existent element in an array. 0. 0. it is not actually necessary to include the length of the array in the square brackets because the compiler can work it out based on the length of the initialisation sequence. 0. for clarity. it is a good idea to always include the array length in the square brackets. The resulting array would be visualised as follows: numbers 6 0 3 1 9 2 0 3 0 4 0 5 0 6 1 7 NOTE: In this example. Therefore. 9. 3. the above array could also be initialised with the following statement: int numbers[] = {6. and the initialisation sequence is shorter than the length of the array. int numbers[8] = {6. 0.EngGen 131 S2 2013 Initialising an array The elements of an array can be initialised as part of the declaration. If the size is specified. For example: int numbers[20] = {7}. 9. 1}. 0. 1}.

the value that is stored in the memory location is unpredictable.EngGen 131 S2 2013 This will overwrite some memory outside of the array bounds. If not. If this value was used in some equation or expression rather than being printed out. 20 is not a valid index value. numbers[19]). Lecture 15 – 44 – Course Manual (C Programming) . If it does crash straight away. and therefore if we attempt to access it. the program may behave unpredictably. other than the value printed out being unusual. printf("%d\n". then the error may be very difficult for us to find because we may not discover it until we try to access the overwritten value and realise it is not what we expected. printf("%d\n". Here is the output produced when the above code was executed: 0 1245120 Notice that the code compiled successfully and there was no indication of any error when the program was run. As an example. then we are lucky because we will know something is wrong. You need to be very careful not to access elements outside of the valid bounds of an array. numbers 0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 0 0 0 0 0 0 0 0 0 0 9 10 11 12 13 14 15 16 17 18 19 numbers[20] = 2. numbers[20]). This kind of error may or may not cause our program to crash immediately. consider the following poorly written code: int numbers[20] = {0}. The valid index values for this array range from 0 to 19 inclusive.

For example. There are no shortcut operations that will process an entire array at once. For example. } Sometimes it is difficult to predict exactly how many elements are going to be required to store information when the program executes. consider the following variable declarations: int numbers[20] = {0}. 3. It is therefore quite common to allocate more space than is expected to be required.EngGen 131 S2 2013 Processing arrays If we want to access all of the elements in an array. 1 and 8 have been added: numbers 7 0 3 1 1 2 8 3 0 4 0 5 0 6 0 7 0 8 0 0 0 0 0 0 0 0 0 0 0 9 10 11 12 13 14 15 16 17 18 19 numElements 4 Lecture 15 – 45 – Course Manual (C Programming) . We could visualise these variables as follows: numbers 0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 0 0 0 0 0 0 0 0 0 0 9 10 11 12 13 14 15 16 17 18 19 numElements 0 Each new data value is stored in the array at the index specified by numElements. The most convenient way of accessing each element in an array is to use a loop. consider the following loop which sets each element of the array numbers equal to 10: int numbers[20]. for (i = 0. consider the array after four values 7. i < 20. for example maybe we want to set each element equal to some value. we must do so one by one. and use a separate variable to store how many of the initial elements of the array are actually being used to store useful information. int numElements = 0. and then the value of numElements is incremented. For example. i++) { numbers[i] = 10. int i.

we would use the value of the variable numElements in the stopping condition to the loop. Lecture 15 – 46 – Course Manual (C Programming) . to store the value 99: numbers[numElements] = 99. i < numElements. after which. After the new value is stored. numElements++.EngGen 131 S2 2013 If we were to print out each of these data values. as follows: for (i = 0. we would also have to increment numElements. } If we wanted to store another data value in the array. the value of numElements indicates at which index the new value should be stored. and hence cannot allocate exactly the right amount of space at the time the array is declared. i++) { printf("%d ". numbers[i]). the array and the variable numElements would be visualised as: numbers 7 0 3 1 1 2 8 99 3 4 0 5 0 6 0 7 0 8 0 0 0 0 0 0 0 0 0 0 0 9 10 11 12 13 14 15 16 17 18 19 numElements 5 This approach is very common when we don't know beforehand exactly how many elements we need to store. For example.

i < numElements.. So the loop variable will start at 1: int i.EngGen 131 S2 2013 Summing the elements Assume we have an array of integers called numbers. The next value we need to consider is the second element in the array. add numbers[numElements-1] to this We can easily convert the basic steps listed above into source code. Lecture 15 – 47 – Course Manual (C Programming) . for (i = 1. and the variable numElements stores the number of elements in the array that store useful data. i < numElements. and then updating this as we progress through the array. } Finding the minimum value Again. An algorithm for the basic steps required is: • • • • • • start with the value 0 add numbers[0] to this add numbers[1] to this add numbers[2] to this . We can start by recording the smallest element we have seen so far. int i. We might want to calculate the sum of all of the values in this array. by defining a variable called sum to keep a track of the current sum as we iterate through the elements of the array: int sum = 0. Initially. the value stored in the variable smallestSoFar will be the smallest value in the array. assume we have an array of integers called numbers. We might want to calculate the value of the smallest element in the array. i++) { sum += numbers[i].. and the variable numElements stores the number of elements in the array that store useful data. i++) { if (numbers[i] < smallestSoFar) { smallestSoFar = numbers[i]. for (i = 0. } } When the loop finishes. the first element of the array must be the smallest value we have seen so far: int smallestSoFar = numbers[0].

} An example of this program running is given below (user input is in bold): Enter a number: 133 133 is not a prime number Lecture 15 – 48 – Course Manual (C Programming) . For example. return 0.EngGen 131 S2 2013 Lecture 15 Summary Program ───────────────────────────── We can now write programs that use conditionals to make decisions and use loops for repetition. while ((i < value) && (value % i != 0)) { i++. else printf("%d is not a prime number\n". value). } if (i == value) printf("%d is a prime number\n".h> int main(void) { int value. &value). i = 2. printf("Enter a number: "). i. #define _CRT_SECURE_NO_WARNINGS #include <stdio. value). scanf("%d". the following program determines whether or not the number entered by the user is a prime number.

testIndex++) { value = inputs[testIndex]. value).h> #define MAX_INPUTS 100 int main(void) { int inputs[MAX_INPUTS]. value = 0. for (testIndex = 0. #define _CRT_SECURE_NO_WARNINGS #include <stdio. i = 2. The program then tests each of the numbers in the array for primality – similar to the previous program..\n\n"). if (value != -1) { inputs[numInputs] = value. int value. It extends the previous program. int numInputs = 0. while (value != -1) { printf("Enter number %d: ". testIndex < numInputs. printf("Enter -1 to stop input and begin testing.EngGen 131 S2 2013 We can also use arrays to store and process collections of values. value). by allowing the user to enter any number (up to MAX_INPUTS) of input values – which are then stored in an array. } } printf("\nNow testing for prime numbers.\n\n"). } Lecture 15 – 49 – Course Manual (C Programming) . printf("Enter numbers to test for primality. else printf("%d is not a prime number\n". testIndex. numInputs). i. numInputs++. } return 0.. while ((i < value) && (value % i != 0)) { i++. } if (i == value) printf("%d is a prime number\n". scanf("%d".\n"). &value). The user enters the value -1 to indicate no more input. Below is a more complicated example.

com/ Lecture 15 – 50 – Course Manual (C Programming) .EngGen 131 S2 2013 An example of this program running is shown below (user input is in bold): Enter numbers to test for primality. Enter Enter Enter Enter Enter Enter Enter Enter number number number number number number number number 0: 1: 2: 3: 4: 5: 6: 7: 100 37 15 31 94537207 7850 7853 -1 Now testing for prime numbers. Enter -1 to stop input and begin testing.. 100 is not a prime number 37 is a prime number 15 is not a prime number 31 is a prime number 94537207 is a prime number 7850 is not a prime number 7853 is a prime number ────────────────────────────── http://xkcd..

and what is the output returned by the function. For example. >> B = sqrt(A). we need to know the name of the function. 0. and use a nested loop to iterate over its elements write code that includes the header file for an ANSI C standard library or an external library. what sort of input arguments to pass to it. where the elements are arranged into rows and columns. a two-dimensional array (or matrix) can be defined by specifying the comma-separated values one row at a time. we could pass a vector to it and it would return a new vector containing the square root of the original elements: MATLAB >> A = [50. Lecture 16 – 51 – Course Manual (C Programming) . 0. The basic C data types can be combined together to form more complex types which may be better suited to the problems we are working on. 0]. 0. to use the sqrt() function. There are a large number of useful functions that are available to us in MATLAB. 4. and makes calls to the functions defined in that library define and use a structure consisting of several fields declare and use an array where the elements of the array are a structure type MATLAB Comparison ──────────────────────────────────── In MATLAB.60. 2. you should be able to: • • • • declare a two-dimensional array. and two index values are used to access the data. Many useful tasks can be performed by calling functions that are defined in libraries that are either a standard part of the language. or programmer-defined. 3. To use any of the standard MATLAB functions. 5.70]. 1. 2. Library Functions and Structures A two-dimensional array is a natural extension of a one-dimensional array. with each row terminated by a semi-colon: MATLAB >> A = [1.EngGen 131 S2 2013 Lecture 16: 2D arrays. 0. we must declare the appropriate type of variable and access the data using two index values – one for the row and one for the column. Learning outcomes ──────────────────────────────────────── After this lecture. To work with two-dimensional arrays in C.

given the array as declared previously: int numbers[4][3]. i++) { for (j = 0. called structures. For example. For example. in C there is no automatic support for working with anything except the basic types. there are also a number of standard library functions we can call (although the standard C library is much smaller than the MATLAB library).EngGen 131 S2 2013 In C. to specifically suit our needs. 3 column array can be declared with the following statement: int numbers[4][3]. j++) { numbers[i][j] = i + j. A two-dimensional array has two index values. To perform operations with structures. Two-dimensional arrays ─────────────────────────────────── Sometimes the data we are working with is most naturally organised as a table. Unlike MATLAB. or subscripts: one to denote the row and the other to denote the column of the element. } } Lecture 16 – 52 – Course Manual (C Programming) . organised into 4 rows and 3 columns: 0 0 1 2 1 numbers 2 3 With two-dimensional arrays. what values to pass to it. a 4 row. we would use a nested loop: for (i = 0. we typically use a nested loop to access each element systematically. we might want to initialise this so that each element stores the sum of its row and column position. it is more convenient to visualise the array as follows. arranged into rows and columns. To do this. we need to explicitly define the code that processes them. We need to know the name of the function. Although the memory allocated for this array would be a single contiguous block (in this case consisting of enough space to store 12 ints). A two-dimensional array is declared in a similar way to a one-dimensional array. except both the number of rows and the number of columns must be specified. A good example is when we are manipulating the pixels of an image. j < 3. i < 4. If we need more complex types we can define our own data types. and what value it returns.

j++) { printf("%d ". 2. to represent the row index and the second index. } which would produce the following output: 0 1 2 3 1 2 3 4 2 3 4 5 Rows then columns When accessing an element of a two-dimensional array. {1. the initialisation below creates the same array that was initialised using a nested loop in the previous example: int numbers[4][3] = { {0. to avoid confusion. such as: numbers[i][j] it is conventional for the first index. j < 3. } printf("\n"). It is a good idea to stick with this convention all the time. to display the contents of this two-dimensional array (formatted into rows and columns) we could use the following code: for (i = 0. i++) { for (j = 0. numbers[i][j]). {3. to represent the column index. 3}. {2. 2}.EngGen 131 S2 2013 And. 4. i. 5} }. The values on each row of the array should be surrounded in curly braces {} and separated with commas. We would visualise this array as follows: 0 0 1 2 0 1 2 3 1 2 3 4 2 3 4 5 1 numbers 2 3 Lecture 16 – 53 – Course Manual (C Programming) . Initialising a two-dimensional array The elements of a two-dimensional array can be initialised as part of the declaration. 3. 1. For example. j. i < 4. as should the rows themselves. 4}.

we have seen that in order to use the printf() or scanf() functions.h> : <float. would produce the output: 65536. our program must include: #include <math.h> header file. 16).h> : <setjmp.h> : <signal. The list of header files that comprises the standard library is given below: <assert.h> : <stdlib. include: sqrt(x) computes the square root of x pow(x. To use a function that is declared in a particular header file.h> : <stdio.h> : <stddef. printf("%f". the preprocessor directive: #include <name of standard library header file> should be included at the top of the source file. where x is in radians For example.h> : Diagnostics Character Class Tests Error Codes Reported by (Some) Library Functions Implementation-defined Floating-Point Limits Implementation-defined Limits Locale-specific Information Mathematical Functions Non-local Jumps Signals Variable Argument Lists Definitions of General Use Input and Output Utility functions String functions Time and Date functions Mathematical functions ──────────────────────────────────── To use the math functions from the standard library.h> : <errno.h> : <ctype. Each header file contains the declarations for a number of functions which have been categorised as performing similar types of tasks. which take double values as arguments and return double values. y) computes x to the power of y sin(x) computes the sine of x.000000 Lecture 16 – 54 – Course Manual (C Programming) .h> : <time. the following code: double values = pow(2.h> : <string.EngGen 131 S2 2013 ANSI C standard library ─────────────────────────────────── The functions available in the ANSI C standard library are declared in a set of 15 header files.h> : <math. we must include the <stdio.h> : <locale.h> : <stdarg. For example.h> Some of the useful math functions. values).h> : <limits.

Character based input and output can be achieved with the following pair of functions (defined in <stdio. the int type is large enough to represent all possible characters. otherwise if they enter any other character. Here are several examples of the program running: Play again? (y/n): n Thanks .h>): putchar(c) getchar() outputs the specified character to standard output (the screen) reads a character as input from standard input (the keyboard) The getchar() function returns an int value. ‘y’ or ‘Y’. these functions take int values as arguments and return int values. and print this out to the screen. ‘N’. 0 otherwise Although processing characters. For example. A number of character conversion and comparison functions are defined in the standard library. c). 0 otherwise returns non-zero if ch is an uppercase or lowercase letter. Lecture 16 – 55 – Course Manual (C Programming) . and so is able to represent all possible character values. EXAMPLE Let’s look at an example that highlights a potential problem when dealing with character input. If the user enters ‘y’ or ‘n’ then we will display their choice back to them.EngGen 131 S2 2013 Character functions ─────────────────────────────────────── The standard library contains a number of functions for input and output of character data. as well as processing character data. that will store the ASCII code of the character entered. This is fine because the int type is larger than the char type. we will prompt them again. This allows the user to enter either ‘n’. will store the character that is entered at the keyboard in the variable c.you entered y Notice (in the middle example above) that the program converts upper case input characters into lower case. To use these.h> A few of these useful functions are listed below: toupper(ch) tolower(ch) isdigit(ch) isalpha(ch) returns the corresponding upper case letter returns the corresponding lower case letter returns non-zero if ch is a digit. for example to indicate “yes” or “no” in response to some question. the following code: int c = getchar().you entered n Play again? (y/n): a Play again? (y/n): N Thanks . Note. our program must include: #include <ctype. printf("You typed %c".you entered n Play again? (y/n): q Play again? (y/n): w Play again? (y/n): e Play again? (y/n): r Play again? (y/n): t Play again? (y/n): y Thanks . Assume we would like to prompt the user to enter either ‘y’ or ‘n’.

if ((c == 'n') || (c == 'y')) { validInput = 1. We need to ignore the new line character from the input buffer each time through the loop. } You can see that the while loop continues to execute until the value stored in the variable validInput becomes 1. The solution that has been used in the example above is to test if the character from the input buffer is the new line character: if (c == '\n') { c = getchar(). When the user enters a character at the command line. } If it is. the new line character would be returned on the next iteration. the new line character will still be in the buffer.h> #include <ctype. then we simply ignore it by calling the getchar() function again to get the next character the user enters. if we only called getchar() once each time around the loop. c = getchar(). Lecture 16 – 56 – Course Manual (C Programming) . This only occurs when the lower case version of the input character is either ‘n’ or ‘y’. However. there are in fact two characters that get stored in the input buffer.you entered %c\n".h> int main(void) { int c = ' '. while (!validInput) { printf("Play again? (y/n): "). it may be confusing for the user. } c = tolower(c). return 0. Therefore. if the user enters the character ‘a’. The input buffer is a block of memory where input values are stored until they are needed by the program. } } printf("Thanks . we will receive the ‘a’ character.EngGen 131 S2 2013 Below is one implementation of a program for handling user input in this way: #include <stdio. c). This can cause a problem: the first time through the loop. If we don’t take care to ignore this character. if (c == '\n') { c = getchar(). int validInput = 0. when we call getchar(). both the ‘a’ and the new line character (representing the ENTER key) will be stored in the input buffer. For example.

In such cases.h main.c external library We could now call functions defined in the library from within the main..h and library. When the #include directive is used to include a header file that is not part of the standard library. } our program library.. the name of the header file is surrounded with quotation marks. and the source file contains the actual definitions of these functions.h" and make sure the library.h" int main(void) { . There may be functions defined in libraries that are not part of the standard library which we would like to use in our programs.c files were available to the compiler.c source file. we would include the header file using the #include preprocessor directive. .. Lecture 16 – 57 – Course Manual (C Programming) .. we would typically have access to both the header file and the source file for the library. .EngGen 131 S2 2013 External library functions ────────────────────────────────── The functions defined in the ANSI C standard library are guaranteed to be available on any system that is ANSI C compliant.h and the source file library.. To use the functions defined in the library. This means that programs relying on functions from the standard library can be transferred (or ported) from one system to another and still compile and work correctly...c #include "library. rather than the angle brackets that are reserved for header files from the standard library: #include "name of programmer defined header file" For example. We would add the statement: #include "library. assume that we would like to make use of functions defined in an external library distributed as the header file library. The header file contains declarations (essentially just the names and parameter types) of all of the functions in the library. .c.. library.

To use this library from the command prompt. we can manipulate the image in many possible ways as long as we can perform two simple operations: • • obtain the colour value of a pixel at a given row and column of the image change the colour value of a pixel at a given row and column of the image to a new value To provide this functionality. You will need to add: #include "LibBMP. LibBMP. You can download both of these files from Cecil.c #include "LibBMP.. . and then add LibBMP.h. . simply copy these two files into the folder for your program. } our program LibBMP.bmp... Lecture 16 – 58 – Course Manual (C Programming) . Given a file in this format. and a source file: LibBMP. file format is a fairly well known (and relatively simple) file format for storing digital images..h images.c. say image.c and LibBMP.c external library The LibBMP library consists of a header file: LibBMP.EngGen 131 S2 2013 Example: LibBMP ──────────────────────────────────────── The Windows Bitmap. or BMP.h" to the top of the source file that is going to use the library.. To use this library from Visual Studio. in this course we will use a library called LibBMP. . copy these two files into your project folder.h" int main(void) { ...h to your project.. This library contains functions that allow you to read the bitmap data from an image file stored in the BMP (Windows Bitmap) file format (only uncompressed 24-bit images are supported).

this function sets the intensity value (between 0 and 255) of the specified channel of a pixel in the image. Parameters: • value: the intensity value (between 0 and 255) to be stored in the specified channel of the pixel • row: the row. col. Parameters: • "fi. 1 = green. or horizontal position. 1 = green.bmp": is the name of the output image file – this will be created as output by the program and appear in the project folder • width: the width of the image • height: the height of the image Lecture 16 – 59 – Course Manual (C Programming) . height) This saves the image in memory out to a file on disk in BMP format. of the pixel • channel: the colour channel (0 = red.bmp". channel) Once an image file has been loaded into memory. row. width. or vertical position. of the pixel • col: the column. this function returns an integer value (between 0 and 255) representing the intensity of the specified colour channel of a pixel in the image.bmp". 2 = blue) SaveBMPFile("fo. channel) Once an image file has been loaded into memory.EngGen 131 S2 2013 The LibBMP library provides the following functions that you may find useful. LoadBMPFile("fi. &height) This loads an image file stored on disk in BMP format into memory. Parameters: • "fo. of the pixel • col: the column. of the pixel • channel: the colour channel (0 = red.bmp": is the name of the input image file – this will already exist on disk in the project folder • &width: the address of the int variable that will be initialised to the width of the image once it is read from disk • &height: the address of the int variable that will be initialised to the height of the image once it is read from disk GetPixelValue(row. Parameters: • row: the row. col. or vertical position. 2 = blue) SetPixelValue(value. or horizontal position. &width.

row. height . for (row = 0. int row. &height). colour = GetPixelValue(row.1 . LoadBMPFile("clown. height.h> #include "LibBMP. width.row. 1). } } SaveBMPFile("output. SetPixelValue(colour.1 . &width.EngGen 131 S2 2013 Image manipulation example The program below uses the LibBMP library to fold a copy of the top half of an image down onto the bottom half. row < height / 2. height). height . col. 2). col. 0).row. return 0. 0). col.bmp output. col++) { colour = GetPixelValue(row. col. col.bmp Lecture 16 – 60 – Course Manual (C Programming) . row++) { for (col = 0. col. SetPixelValue(colour. 1). 2).bmp". col < width.h" int main(void) { int width. int colour. height .bmp". } clown.1 . col. #include <stdio. SetPixelValue(colour. colour = GetPixelValue(row.

} Point. We can define a new structure type using the following syntax: typedef struct { <type> <fieldName1>. int main(void) { Point a. b. } <name>. For example. so we can define our own data type for this. int y. In C. or typedefs. a. a. } return 0. the program on the left defines and uses Point structures. same = ((a. Before we can store anything using this structure.y)). For example.x = 10.x) && (a.. <type> <fieldName2>. } Point.x = 10.EngGen 131 S2 2013 Structures ──────────────────────────────────────────────── It can be convenient to compose new types of data by combining the basic data types. b. grouped together under a single name. There is no predefined data type that allows us to store a point. each of which consists of an x and a y value.x == b.. to define a structure to store our point data. we need to declare a variable of this new type. int same. This structure definition does not allocate space for any variables. double y. } else { printf("The points are different"). if (same) { printf("The points are the same"). . b. we might want to write a program that processes 2-dimensional points. #include <stdio.y = 20. This allows us to work with variables which more closely match the basic kinds of data that we are manipulating in our programs. All that it does is define a new type called Point.y = 40.h> typedef struct { double x. The definitions of structures. the basic user-defined data type is the structure (sometimes referred to as a record). usually occur just after the #include and #define statements (if there are any) at the top of the source file. A structure consists of a collection of fields (also called components or members) which can be of different types. For example. we could declare the following structure: typedef struct { int x. } Lecture 16 – 61 – Course Manual (C Programming) .y == b.

p1. For example. we could declare two variables called p1 and p2 of type Point as follows: Point p1.x = 100.y = 150. which is a ". both p1 and p2 would require 8 bytes of storage (two variables of type int.EngGen 131 S2 2013 Declaring a structure variable Declaring a variable of a structure type is done in the same way as declaring a variable of one of the basic types. p2 = p1. This assignment statement copies the values stored in each field of variable p1 into the fields of p2.": Point p1. x 100 p1 y 150 p2 y 150 x 100 Lecture 16 – 62 – Course Manual (C Programming) . p1. which each require 4 bytes) Accessing fields To access the fields of a structure we use the structure selection operator. p2. p1. So in this case. p2.x = 100. p1 y 150 x 100 Structure assignment The assignment operator copies all of the fields from one structure to another: Point p1. We would visualise these variables as follows: x p1 y p2 x y The amount of memory that is allocated to store a structure is just the sum of the amount of memory required to store each of the fields. p1.y = 150. We simply specify the type of the variable and give it a name.

. locations[2]. For example. y 2 x y 99 Each element of this array.x = 547. } Point.. can be treated in exactly the same way that we would treat an individual variable of type Point. We can declare an array to store 100 points: Point locations[100].. int y..EngGen 131 S2 2013 Arrays of structures ─────────────────────────────────────── Consider an array..y = 126. would assign 547 and 126 to the fields of the third element of the locations array: x locations y 0 x y 1 x 547 . given the following structure definition: typedef struct { int x. We would visualise this array as follows: x locations y 0 x y 1 x . where each element is a structure type. For example.. for example locations[2]. y 126 2 x y 99 Lecture 16 – 63 – Course Manual (C Programming) . the statements: locations[2].

as well as printing a * next to the result with the highest mark. i++) { average += results[i]. int main(void) { int i. topIndex = 0. i < NUM_RESULTS. scanf("%d %lf". It then echoes all of the results out to the screen and calculates and displays the average mark. Lecture 16 – 64 – Course Manual (C Programming) . &results[i].mark.mark). These results represent student results in a course and consist of an ID number and a final mark. double average. #define _CRT_SECURE_NO_WARNINGS #include <stdio. */ /* A result will consist of an ID number and a mark */ typedef struct { int id.id. int topIndex. /* Create an array to store the results */ Result results[NUM_RESULTS]. as entered by the user. } Result. i). } /* Calculate the average and highest mark */ average = 0.h> #define NUM_RESULTS 5 /* A program which reads in a series of results. /* Allow the user to input the results */ for (i = 0. if (results[topIndex].0. &results[i].EngGen 131 S2 2013 Lecture 16 Summary Program ───────────────────────────── We can now write programs that work with arrays and structures. i < NUM_RESULTS. for (i = 0. i++) { printf("Please enter result %d [id mark]: ".mark < results[i]. double mark. } average = average / NUM_RESULTS. For example.mark) topIndex = i. the following program calculates some basic statistics for a small set of student marks.

4 * 50.0 Average mark: 65.4 50.EngGen 131 S2 2013 /* Print the results */ printf("\nSummary:\n"). } printf("\n"). i++) { printf("ID: %d MARK: %. return 0.2 39. for (i = 0. i < 5. average).8 81.3 91.0 Summary: ID: 2034871 ID: 2345392 ID: 4837726 ID: 3958837 ID: 2293847 66. The values that appear in this diagram represent the values at the end of the program (after the loop has finished and all output has been produced.mark). results[i]. given a small input of 5 results is shown below (user input is in bold): Please Please Please Please Please enter enter enter enter enter result result result result result MARK: MARK: MARK: MARK: MARK: 0 1 2 3 4 [id [id [id [id [id mark]: mark]: mark]: mark]: mark]: 2034871 2345392 4837726 3958837 2293847 66.id.3 91. } printf("\nAverage mark: %f".2 39. if (i == topIndex) { printf(" *").1f". just before the “return 0” statement is executed): Lecture 16 – 65 – Course Manual (C Programming) . results[i]. } The output from this program.8 81.740000 We can visualise the memory for this program as in the diagram below.

For example. and use the < symbol to redirect the contents of the file as the input to the program.8 81.com/ Lecture 16 – 66 – Course Manual (C Programming) .txt ────────────────────────────── http://xkcd. where we have the input in a text file. However this will require us to modify our code as we will be using new library functions. Instead of 5 entries. From the command line.2 39. How about the example above though.txt: input.4 50.3 91. this would look like the following (where the compiled program is called summary): C:\Lecture 16> summary < input. which works perfectly well for obtaining input from the keyboard. a nice solution is to use redirection.EngGen 131 S2 2013 Redirection In the example above.0 We could get the same output from the program as before by redirecting the file to be the input for the program. it was inconvenient to have to enter all the results by hand. Is there any way we can obtain input from a file without needing to rewrite the code? Yes! If we are working at the command line. if we created a text file called input. In the next lecture we are going to learn about file I/O. which will allow us to read input directly from files stored on disk.txt 2034871 2345392 4837726 3958837 2293847 66. imagine if there were 500 – we need a more convenient way to get the input into the program.

For example.5 'heads' else 'tails' end The C standard library also defines a rand() function which returns a pseudo-random integer value between 0 and RAND_MAX. it may not be convenient to use standard input and output to initialise or display the data. we could use: MATLAB if rand < . which is a constant defined in the standard library.EngGen 131 S2 2013 Lecture 17: File I/O and Random Numbers When we are working with large amounts of data. Learning outcomes ──────────────────────────────────────── After this lecture. fscanf() and fgetc() can be used for file I/O. The rand function (which is used without parentheses for scalar values) in MATLAB returns a pseudo-random. There are lots of situations where it is useful to be able to produce random numbers – for example we might be programming a game and we want the behaviour to be unpredictable. and write data to. to make a random choice between two equally likely values. C provides file I/O functions which allow us to read data from. In C. – 67 – Lecture 17 Course Manual (C Programming) . or a pseudo-random floating point number between a specified upper and lower bound using the rand() function MATLAB Comparison ──────────────────────────────────── MATLAB provides the load(). scalar value drawn from a uniform distribution on the unit interval (0 – 1). files on disk. the functions fprintf(). or we might be implementing a computer simulation that involves randomness. save() and fprintf() functions for reading from and writing to files on disk. you should be able to: • • • • • • • declare a file pointer variable open either a text file or a binary file for either reading or writing read input from a file using either the fscanf() or fgetc() functions write output to a file using either the fprintf() or fputc() functions close a file that has been opened set the seed of the standard library's random generator to the current time generate a pseudo-random integer.

Declaring a variable to store this file pointer is done as follows (the file pointer variable is called fp in this example. This end of line sequence is different between operating systems (for example in Unix. In situations where we want to process large volumes of data. but it could be called anything you like): FILE *fp. When we work with files in our C programs. the program may automatically convert the end of line sequence to a different sequence internally. although the actual characters of text will not be modified. Most really interesting problems require that we work with large amounts of data. On Windows. which we must #include at the top of our source file. when a text file is being written to disk. Apart from that. received input from the keyboard (using the scanf() function) and produced output to the screen (using the printf() function). All access to the file goes via this file pointer. C source files are another good example of text files. Text files vs. When a text file is being read from disk. and has a name with which we can identify it. a single line feed character is used whereas in Microsoft Windows. Lecture 17 – 68 – Course Manual (C Programming) . C uses what is known as a file pointer.txt extension is often used for text files. the program will write the correct end of line sequence for the current operating system. a carriage return followed by a line feed is used). Each line of text is terminated by a special byte or sequence of bytes which indicates the end of the line. A file is a collection of bytes stored on disk. The reason for the * will be explained later. we need to specify which type of file we are working with. The FILE type is defined in <stdio. when we look at pointers. with the type (FILE) and the identifier (fp).h>. and produce output to files. and the current position within that file where you are reading from or writing to. The general process for reading data as input from a file stored on disk is: • open the file for reading • read bytes of data from the file • close the file The general process for writing data as output to a file on disk is: • open the file for writing or appending • write bytes of data to the file • close the file File pointer To keep track of the file you have opened. for which the keyboard and screen may not be the most convenient interfaces. so far. this looks pretty much like any variable declaration. Likewise. we can have our programs read input from files. binary files A file stored on disk can be classified as either a text file or a binary file. the . The correct type to use depends on whether or not it is acceptable for automatic conversions to be made to the bytes as they are being either read or written.EngGen 131 S2 2013 File Input and Output ───────────────────────────────────── Our programs have. Text files A text file consists of plain text characters which are arranged into lines.

Opening a file To open a file. our program will crash.EngGen 131 S2 2013 Binary files A binary file consists of bytes which must be read in from file exactly as they appear on disk and must be written out to file exactly as they are stored in the program.jpg files). for example maybe the file name is invalid. if the file already exists. any new output will appear at the end of the file If the file cannot be opened for some reason. any new output will appear at the end of the file append binary – creates a binary file for writing. } else { < perform the I/O > } It is always a good idea to test for a NULL file pointer whenever opening a file. the following code attempts to open a text file for reading. Most binary files usually require some special application to interpret the bytes so that the data in the file can be used. "r"). as follows: fp = fopen("<filename>". Lecture 17 – 69 – Course Manual (C Programming) . An informative error message to the user that the file could not be opened is much nicer than having the program crash.bmp and . we call the fopen() function and assign the result of this function call to the file pointer variable. an . For example. if the file already exists. Other good examples of binary files include image files (such as . the fopen() function will return NULL (which is a symbolic constant defined in stdio. couldn't open the file"). if the file already exists it will be overwritten write binary – creates a binary file for writing. if (fp == NULL) { printf("Sorry. because if we try to perform any I/O on a NULL file pointer. a music player application must be used. In order to listen to the music encoded in the file. There should be no conversion performed by the program as there is with text files. if the file already exists it will be overwritten append text – creates a text file for writing. It is therefore good style to handle this case elegantly.txt". For example. where <filename> is the name of the file and <mode> can be any of several I/O modes: Mode r rb w wb a ab Explanation read text – opens a text file for reading read binary – opens a binary file for reading write text – creates a text file for writing.h).mp3 music file is a good example of a binary file. "<mode>"). and will print an error message if the file cannot be opened: fp = fopen("filename.

. The second call to fscanf() reads the entire second line – the four characters that are read: '5'. which is "%d"). The general form of the fscanf() function is: fscanf(fp. The output is therefore: first: 1234 second: 5678 Lecture 17 – 70 – Course Manual (C Programming) . and the conversion specifier that is used in the call. <format string>. When the end of the file has been reached and there is no more input to read. "r").txt".txt" contains two lines of text. '7' and '8' are converted to the numeric value 5678 before being assigned to the variable value. After the character '4' is read. and the first parameter is a file pointer.couldn't open file"). } data. The first line of text contains the characters "1234" and the second line contains the characters "5678". One "value" at a time The fscanf() function returns a value of type int. <address>. . the next character is not a digit (it will be the new line character) so the characters are converted to the numeric value 1234 and assigned to the variable value. &value). This value is the number of input items converted and assigned. int value. These companion functions are prefixed with the letter "f".h>. printf("second: %d\n". if (fp == NULL) { printf("Sorry . The exact number of characters that will be read depends on the data in the file. "%d".. then the character '2'. printf("first: %d\n". } return 0. fp = fopen("data. '6'. #define _CRT_SECURE_NO_WARNINGS #include <stdio.EngGen 131 S2 2013 Reading from a file The standard input and output functions we have already used (scanf() and printf()) each have variants which work with files rather than the keyboard and the screen. value). } else { /* Read the first integer value */ fscanf(fp. When fscanf() is called. more than one character (or byte) may be read from the file. in which a text file called "data. which is a constant defined in <stdio. this function returns the value EOF. value). then '3' and so on – it will continue to read characters from the input file as long as they are a digit from 0 to 9 (which matches the conversion specifier.).h> int main(void) { FILE *fp. The character '1' is read first.txt 1234 5678 The first call to fscanf() will read the entire first line of text. "%d". /* Read the second integer value */ fscanf(fp. Consider the example below. &value).

} else { /* Read the first character */ c = fgetc(fp).h> int main(void) { FILE *fp. /* Read the second character */ c = fgetc(fp). fp = fopen("data. printf("first: %c\n". the second call to fgetc() reads the second character from the file and returns the value 50 (the ASCII code of the character '2'). if (fp == NULL) { printf("Sorry . The ASCII code of the character '1' is the value 49. The integer value returned by the fgetc() function is the ASCII code of the next character (if reading from a text file) or the value of the next byte (if reading from a binary file). "r"). Likewise. The fgetc() function takes the file pointer as a parameter. note that the conversion specifier used in the printf() call is "%d" and so the output will be 49. c = fgetc(fp). } return 0. c). The value returned by fgetc() is the ASCII code of the character. Lecture 17 would produce the output: first: 1 second: 2 – 71 – Course Manual (C Programming) . #define _CRT_SECURE_NO_WARNINGS #include <stdio. printf("second: %d\n".couldn't open file"). When this is printed. The first line of text contains the characters "1234" and the second line contains the characters "5678".txt 1234 5678 The first call to fgetc()reads the first character in the file. c). c).txt" contains two lines of text. fgetc(fp). printf("second: %c\n".EngGen 131 S2 2013 One char / byte at a time It is also very common to use the fgetc() function for reading data from a file. printf("first: %d\n". or the constant value EOF indicating that the end of the file has been reached. So: c = fgetc(fp). The output is therefore: first: 49 second: 50 To print the characters themselves (rather than their ASCII codes). in which a text file called "data. '1'. c). and returns an integer. int c. the "%c" conversion specifier could be used in the printf() statements. } data. Consider the example below.txt".

ch). we need some way of systematically reading each value until we reach the end of the file (at which point there are no more data values to read). fp = fopen("data. and displayed to the screen: FILE *fp. } else { while ((ch = fgetc(fp)) != EOF) { printf("%c". int ch. Consider the following statements: This assignment statement stores the value read from the file (which in this case is a single byte/character) in the variable called value This boolean statement assigns the value read from file to the variable (as described above) but also compares that value with the value EOF. ch). Overall. The fscanf() and fgetc() functions will return the value EOF when the end of the file is reached. this expression evaluates to true/1 (if the value is not EOF) or false/0 (if the value is EOF) This while statement uses the boolean (evaluated as described above) to execute while there are still data values in the file being read (while the end of file has not yet been reached) value = fgetc(fp) (value = fgetc(fp)) != EOF while ((value = fgetc(fp)) != EOF) We can therefore use a loop like the following to read and display all of the characters in a text file: while ((ch = fgetc(fp)) != EOF) { printf("%c".EngGen 131 S2 2013 Reading an entire file Although we can open a file and read just a few values from it. if (fp == NULL) { printf("Sorry. it is common to want to read all of the data from a file.txt". As we probably do not know exactly how much data is in the file. the file could not be opened"). } The following example illustrates how a text file (called file. } fclose(fp). one character at a time. } Lecture 17 – 72 – Course Manual (C Programming) .txt) may be read. "r").

txt 1234 5678 One character at a time: while ((value = fgetc(fp)) != EOF) { printf("Value = %c (decimal=%d)\n". one character is read at a time from the file. until it reaches some whitespace (like a new line or a space). This character is read from the Value = 7 (decimal=55) file (just like the other characters). "%d". Lecture 17 Output: Value = 1234 Value = 5678 – 73 – Course Manual (C Programming) . int value. The output displays both the printable representation of the character and the decimal ASCII code of the character.txt (shown below) has been opened through the file pointer fp: input. the two values are read from the file one line at a time. The fscanf() function is smart enough to read a sequence of characters that make up an integer. you can see that a new line is actually displayed). the %d conversion specifier reads one integer from the file. When Value = 8 (decimal=56) the new line character is printed (using the %c conversion specifier. &value) != EOF) { printf("Value = %d\n". and that the file input. The ASCII character code of the new line character is 10. value). In this example. One value at a time: while (fscanf(fp. Assume we have the following variable declarations: FILE *fp. So in this case. } In this example. value. value). } Output: Value = 1 (decimal=49) Value = 2 (decimal=50) Value = 3 (decimal=51) Value = 4 (decimal=52) Value = (decimal=10) Notice that the file contains one new line Value = 5 (decimal=53) character – at the end of the first line of Value = 6 (decimal=54) the file.EngGen 131 S2 2013 The example below illustrates the difference between reading one character at a time and reading one value at a time from a text file.

int byte. "wb"). To close a file. fpOut = fopen("duplicate. <value>. } fclose(fpIn). Closing a file It is always a good idea to close a file when you have finished with it.. The fputc() function takes two parameters – an integer storing the character (or byte) to be written to file.mp3) by reading one byte at a time from the original file using fgetc(). fclose(fpOut). the files could not be opened"). the following code duplicates a binary file (in this case a music file called music. and the characters are written to the file rather than the screen. and writing one byte at a time to the output file (called duplicate. For example. *fpOut.mp3". Lecture 17 – 74 – Course Manual (C Programming) .EngGen 131 S2 2013 Writing to a file The general form of the fprintf() function is: fprintf(fp.. except the first parameter is a file pointer. This behaves like the printf() function. fpOut). if ((fpIn == NULL) || (fpOut == NULL)) { printf("Sorry.). fp). <format string>. . } else { while ((byte = fgetc(fpIn)) != EOF) { fputc(byte.mp3): FILE *fpIn. we call the fclose() function and pass it the file pointer: fclose(fp).mp3". although this will happen automatically when our program exits. It is also common to use the fputc() function for writing data to a file. fpIn = fopen("music. "rb"). and the file pointer: fputc(ch. } Notice the "rb" and "wb" modes used for opening the files – these are necessary because the files contain binary data.

which produces the output: 32767 The ANSI C standard defines that 32. What output do you get? Do you get 41? Amazing coincidence? Lecture 17 – 75 – Course Manual (C Programming) . we can simply print it out: printf("%d\n".767 is the smallest allowable value for RAND_MAX. rand() 0 . we cannot generate truly random numbers in our programs. printf("%d\n".EngGen 131 S2 2013 Random numbers ───────────────────────────────────────── In practice. To generate a pseudo-random number. To find out the value of RAND_MAX. but are really generated by a formula. Instead. we use functions that produce pseudo-random numbers. } Try compiling and running the above code.. our program must include: #include <stdlib. r). which generates a pseudo-random number between 0 and RAND_MAX.h> if we are going to use the rand() function. and the prototype of the rand() function are defined in <stdlib. r = rand().h> #include <stdlib.h> int main(void) { int r. RAND_MAX The value of RAND_MAX. The standard library defines a function called rand(). we simply call the rand() function: #include <stdio.. they appear to be random. and in fact this value is common in many modern compilers. return 0..h>.RAND_MAX). That is. Therefore.

If it is convenient. printf("%d\n". The srand() function only needs to be called once to initialise the seed. for (i = 0. this can be quite useful. as shown in the example below: srand((unsigned int)time(NULL)). 1. i++) { r = rand(). consider the following code: int i. we call it with a parameter of NULL. Sometimes. i < 10. To achieve this. the following output will be produced: 41 18467 6334 26500 19169 15724 11478 29358 26962 24464 It may seem strange that our so-called "random" numbers are so predictable. We are able to initialise the value of the seed to whatever we like by calling the srand() function: srand(seed). is to use the current time. this seed value could be provided by the user. Jan. r).h> defines a function called time() which returns the time that has elapsed since 00:00:00 GMT. A more common way of initialising the seed. 1970 (known as the Unix epoch). } Every time we execute this code. However. For example. measured in seconds. in most situations we would like our program to produce a different sequence of pseudorandom numbers each time it is executed. which does not require user interaction. Lecture 17 – 76 – Course Manual (C Programming) . the current time will be different and therefore so will the seed value. This is useful because each time the program is executed. It makes it a lot easier to diagnose a problem in our code if we are able to reproduce the same sequence of values that the program is working with each time. the pseudo-random number generator uses what is known as a seed to compute the first number in the sequence. The header <time. and cast the return value to unsigned int. To use this value to initialise the random number generator's seed. r. where seed is an unsigned int value. such as when we are debugging our program.EngGen 131 S2 2013 Integer sequences The sequence of values generated by rand() will be the same each time the program is executed.

double randomDouble. For example.692251 0. } An example of this program running is given below (user input is in bold): How many random numbers? 5 0. srand((unsigned int)time(NULL)).h> #include <stdlib. the following program generates a sequence of random floating point values between 0 and 1.c #define _CRT_SECURE_NO_DEPRECATE #include <stdio. Floating point sequences To generate a random floating point value between 0. so the numbers are different each time the program runs. printf("How many random numbers? ").060305 0.0 (inclusive) we can call the rand() function and divide by RAND_MAX: double randomDouble. using the following formula: (rand() % (b-a+1)) + a The value of (b-a+1) should be less than RAND_MAX. randomDouble). &numRandoms). i < numRandoms.h> int main(void) { int i. numRandoms. File: randoms. scanf("%d". The random seed is set to the current time.0 and 1. } return 0. randomDouble = ((double)rand()/RAND_MAX). printf("%f\n". i++) { randomDouble = ((double)rand()/RAND_MAX).610340 0.104862 0.h> #include <time.785638 Lecture 17 – 77 – Course Manual (C Programming) . for (i = 0.EngGen 131 S2 2013 Range We can generate a random value between a and b inclusive.

fpIn = fopen("input. one byte or character at a time. if ((fpIn == NULL) || (fpOut == NULL)) { printf("The files could not be opened. "r").txt".txt. } else { while ((ch = fgetc(fpIn)) != EOF) { if (isalpha(ch) || (ch == ' ') || (ch == '\n')) fprintf(fpOut.h> int main(void) { FILE *fpIn.txt. } printf("Copying complete. "w"). Only upper and lower case alphabetic characters. int ch. } Lecture 17 – 78 – Course Manual (C Programming) . fpOut = fopen("output. ch). "%c". } return 0. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <ctype. fclose(fpOut). and stores the result in the output file output.\n").EngGen 131 S2 2013 Lecture 17 Summary Program ───────────────────────────── We can now write programs that read data from and write data to files on disk.\n"). the space character and the new line character are preserved. For example. the following program strips out all punctuation from the input file input. *fpOut.txt". fclose(fpIn).

txt is identical to the source code above.EngGen 131 S2 2013 If the file input.txt define CRTSECURENOWARNINGS include stdioh include ctypeh int mainvoid FILE fpIn fpOut int ch fpIn fopeninputtxt r fpOut fopenoutputtxt w if fpIn NULL fpOut NULL printfThe files could not be openedn else while ch fgetcfpIn EOF if isalphach ch ch n fprintffpOut c ch printfCopying completen fclosefpIn fclosefpOut return ────────────────────────────── http://xkcd. output. then after the program has executed the output file.txt will contain the following text: File: output.com Lecture 17 – 79 – Course Manual (C Programming) .

EngGen 131 S2 2013 http://xkcd.com Lecture 17 – 80 – Course Manual (C Programming) .

Learning outcomes ──────────────────────────────────────── After this lecture. y] = polar_to_cartesian(r.* cos(theta).m" suffix). We can define our own functions to better organise our code and make the program easier to maintain and reuse. In C.* sin(theta). In MATLAB. parameter list. and which has the same name as the function (with a ". A program may consist of a single source file which is made up of several functions. body and return type declare a function prototype write code which calls a function you have defined determine whether a variable is local or global and identify the scope of a variable calculate the output that would be produced by a program consisting of several functions and function calls MATLAB Comparison ──────────────────────────────────── We can define our own functions in MATLAB by creating a function file which contains the statements for the function. return. the following function would be defined in a file called polar_to_cartesian. Lecture 18 – 81 – Course Manual (C Programming) . y = r . and this value is specified immediately after the return keyword in the function definition. functions do not have to be defined in their own file. For example. or it may consist of multiple files. In C. this gets very cumbersome as our programs get larger and more complex. theta) x = r . a function can only return a single value. each one defining several functions. the values that are returned by the function are the values that are assigned to the output variables in the body of the function (x and y in the example above).m: MATLAB function [x.EngGen 131 S2 2013 Lecture 18: Functions Although it is possible to define all of the code for our programs in the main() function. you should be able to: • • • • • define a function with a name.

The code we write for the rest of the program can become much clearer if we make use of functions. but perhaps in other programs we write as well. The following table summarises some of the qualities that we should aim for when defining our own functions. then we are free to change the implementation (perhaps to make it more efficient) without affecting the rest of the program. the new implementation of the function would still need to produce the expected output in order for the program to work correctly. so that we can decompose our programs into smaller. We do not need to know where the function is going to be called from. Particularly if we need to perform some task several times. rather than having some difficult to understand section of code repeated each time the task needs to be performed. and how we should calculate the output. if other parts of the program only rely on the output of our function. We can think of a function like a black box. Quality reusability Explanation If a function performs its job really well. without worrying about how the output is calculated. well-defined task. in order to define the function.EngGen 131 S2 2013 Functions ──────────────────────────────────────────────── We have seen many examples of calling functions from the standard library. or what the output value is going to be used for by some other part of the program. When we define our own functions. The term black box refers to the fact that we do not need to know about the details of how the function works in order to use it. we only need to interest ourselves in what the inputs are. more manageable pieces. they should perform a single. Of course. our program will be much easier to follow if we call a function each time we need to perform that task. if we are writing a function definition. as illustrated below. Related to information hiding. and don't rely on the details of how it is implemented. This makes the rest of the program easier to design. We give the function some inputs. – 82 – Course Manual (C Programming) information hiding maintainability clarity Lecture 18 . It is useful for us to define our own functions. inputs output function Similarly. because we only need to call the function and process its output. and it produces an output for us. useful. then we are likely to reuse it – not only in the current program. The rest of the program should not have to know about the details of how the function is implemented (it should be a black box).

if there are no input parameters passed to the function. void If the function does not return any output value. for example it may produce output directly to the screen. and use the same style throughout. result = a + a. Similarly. } Identifier names The name of a function should be chosen so that it is meaningful and describes what it is that the function does. which is used to call the function a list of parameters (also called arguments) which the function is given as input a body. underscores are placed: • • • • • • functionName() function_Name() FunctionName() Function_Name() functionname() function_name() There is no correct or incorrect style. which differ in where the capital letters and. possibly. return result. then the return type should be specified as void. void should appear between the parentheses. The following is an example of a function that takes no input parameters and returns no value: void PrintGreeting(void) { printf("Hello there!\n"). which defines the type of value the function produces as output Here is an example of a function that takes an integer as a parameter. there are lots of different styles that are commonly used.EngGen 131 S2 2013 Defining a function A function is defined by the following: • • • • a name. In terms of the style of the name. } Lecture 18 – 83 – Course Manual (C Programming) . which contains the code that processes the input and calculates the output value a return type. What is most important is that you are consistent. and produces twice the value of that integer as output: int TimesTwo(int a) { int result. This helps to make the code that calls the function very clear.

the function will stop and return to where it was called from in which case this statement won't be printf("less than or equal to zero\n").EngGen 131 S2 2013 return For a function which returns a value. exit A special function exists which allows us to terminate the execution of a program from within any function. without returning control to the calling function. } Lecture 18 – 84 – Course Manual (C Programming) .. void PrintMessage(int a) { if (a > 0) { printf("greater than zero").must be the same as the type of this expression As soon as the return statement is reached. the function stops executing and the value is returned to the line of code where the function was called from. if (<cannot continue condition>) { exit(EXIT_FAILURE). for example. return result. result = a + a. attempting to open an input file which does not exist. and control will be returned to where the function was called from. executed If a function which does not return a value does not contain a return statement. This is commonly used when a situation arises from which it is not possible to continue executing the program. For a function which does not return a value. return. The exit() function prototype is declared in <stdlib. then the function returns after the last statement in the function definition has been executed. the body of the function may contain a return statement which is not followed by any expression. the exit() function completely terminates the program. the return type. Unlike return. } } if a is greater than 0. This statement will cause the function to stop immediately.. } ... which returns control to wherever the current function was called from.h>. int TimesTwo(int a) { int result. the return statement in the body of the function must be followed by an expression which is the same type as the return type. then as soon as the return statement is reached. The exit() function takes one parameter which is the value that will be returned to the operating system upon termination of the program.

whereas now we are writing the definitions of the functions ourselves. is equivalent to return EXIT_SUCCESS. Calling a function We have already seen how to call functions. When we call a function like this. and the result 8 would be returned. as previously mentioned. } A call to this function would look like: int result. The diagram below illustrates how we would visualise the TimesTwo() function as a black box: 4 8 TimesTwo() Lecture 18 – 85 – Course Manual (C Programming) . Previously all of the functions we called were from the standard library. The value 4 would be passed into the function.h> which can be used: EXIT_FAILURE EXIT_SUCCESS The statement that we have typically seen at the end of our main() function: return 0. The return value is then assigned to the variable result so that we can do something with it (perhaps use it in another calculation. return result. or print it to the screen). Consider the TimesTwo() function again: int TimesTwo(int a) { int result. we think of the function as a black box.EngGen 131 S2 2013 The following two constants have been defined in <stdlib. result = TimesTwo(4). result = a + a.

a. For example. Let’s now consider what happens in memory when this program is executed. } and it would make no difference to the code that called the function. } int TimesTwo(int a) { return 3*a . int main(void) { int a. Let's now look at the complete definition of a program which uses the TimesTwo() function. In other words: int result = TimesTwo(4). return 0. b = TimesTwo(a). function prototype declaration printf("%d times two is %d\n". Lecture 18 – 86 – Course Manual (C Programming) . } The output from this program is: 10 times two is 20 Notice that there is a function prototype declaration as well as the definition of the TimesTwo() function.a.a.EngGen 131 S2 2013 Notice that when we are thinking about using the TimesTwo() function. a = 10. b). b. we don't worry about how it is implemented.h> int TimesTwo(int a). the TimesTwo() function could be rewritten like this: int TimesTwo(int a) { return 3*a . would still assign the value 8 to the variable result. #include <stdio.

we would visualise this as follows: For now. memory is allocated to store information about that function call – specifically. Information about the calling function is also stored. Lecture 18 – 87 – Course Manual (C Programming) . The main() function only has access to the variables (a and b) that we visualise inside the box for its allocated memory. so that when the function returns the program can return back to the calling statement. As we will see shortly. So as an example. The TimesTwo() function only has access to the variable (a) that we visualise inside the box for its allocated memory. these are called local variables. so we always visualise that in memory. the most important thing to notice here is that the variable declared inside the TimesTwo() function is distinct from the variable of the same name (a) declared inside the main() function. When another function is called. when the main() function calls the TimesTwo() function.EngGen 131 S2 2013 Remember the visualisations of memory from Lecture 14? They looked like this: The main() function is always executed when the program starts. space is allocated for the variables declared in the function and for any parameters passed to the function.

and that returns a value of type int. that takes a single parameter of type int. } The output would be: Hello there! Hello there! Notice that the function calls. The prototype allows the compiler to check that when we do actually call the function (in this case from the main() function).h> void PrintGreeting(void). have empty parentheses.EngGen 131 S2 2013 Prototypes The function prototype declaration tells the compiler that we intend to call a function somewhere in our program that is called TimesTwo(). in the main() function. consider the following program: #include <stdio. } void PrintGreeting(void) { printf("Hello there!\n"). function calls function definition Lecture 18 – 88 – Course Manual (C Programming) . The function definition uses the word void to indicate that the function does not take any inputs. For example. PrintGreeting(). then when we call the function we leave the parentheses empty. int main(void) { PrintGreeting(). we have done so correctly. return 0. No parameters If the function does not take any input parameters.

double d). the function would return 1 (or true. } int SameWholeNumber(int x. the order is important – if we made the following function call: if (SameWholeNumber(1. For example. before the function body executes. the input values are separated by a comma. possible loss of data Lecture 18 – 89 – Course Manual (C Programming) .7. When we call the function. 10. In this case. consider the following program: #include <stdio. we specify the inputs in the corresponding order as the parameters.9)) { printf("same\n").EngGen 131 S2 2013 Multiple parameters If the function takes more than one input parameter.9 is 10) and so the output of the program would be: same Notice that in the function call. because the input value 1. 3)) the compiler would issue a warning. Also. and separate them with commas. the parameters are separated by commas in the function definition. } function definition When the SameWholeNumber() function is called. function call int main(void) { if (SameWholeNumber(10. } return 0.9 is assigned to the input parameter d.h> int SameWholeNumber(int x. double d) { int truncated = (int)d.7 (a floating point value) cannot be assigned to the first input parameter x (of type int) without losing data: warning: 'function' : conversion from 'double' to 'int'. return x == truncated. because the whole part of the double value 10. the value 10 is assigned to the input parameter x and the value 10.

Local variables.. } int FunctionTwo(int a) { . appearing inside the box representing the memory allocated for the function call. the memory for the local variable disappears. When the function exits.. So in this case. The local variable a in the memory for FunctionTwo() is only accessible by code defined in FunctionTwo(). Local variables A local variable is a variable that is defined at the start of a block of code... When the function is called and control enters the function. In the diagram below. within FunctionTwo() } A local variable exists only while the function is executing. are only accessible by code defined in that function definition. the function FunctionOne() . memory is allocated for the local variable. The scope of a local variable is just the block of code in which it is defined. For this example... The local variable a in the memory for FunctionOne() is only accessible by code defined in FunctionOne().EngGen 131 S2 2013 Variable scope ──────────────────────────────────────────── The scope of a variable is the section of code in which it is valid to refer to or access the variable. the variable x is local to the FunctionOne() function. It can only be referred to from within the body of FunctionOne(). the local variable x is only accessible by code defined in FunctionOne(). we can visualise memory being organised as in the diagram on the left (arbitrary values have been assigned to the variables). variable x cannot be referred to from . the scope of variable x is just the body of .. for example at the start of a function definition. – 90 – Lecture 18 Course Manual (C Programming) .. int FunctionOne(int a) { int x.

. This means that local variables for FunctionOne() will no longer exist when the function finishes. is in a separate section of memory to the memory allocated for the function calls.. Lecture 18 – 91 – Course Manual (C Programming) . } the scope of variable x is the entire source file A global variable exists in memory for as long as the program is executing. Note the global variable... In the diagram below. we can visualise memory being organised as in the diagram below. The scope of a global variable begins at the declaration of the variable.. int FunctionOne(int a) { . the variable x is a global variable and it is valid to refer to it from within either FunctionOne() or FunctionTwo(). } int FunctionTwo(int a) { .. When FunctionOne() finishes executing. and ends at the end of the source file. ... However the global variable exists in memory for as long as the program is running – its value persists even when functions start and finish.EngGen 131 S2 2013 Global variables A global variable is a variable that is defined outside of any function. . int x = 10. where it can be reused for subsequent function calls). x. the memory that has been allocated for it will disappear (it is returned to the system. For this example. The global area of memory is accessible by all functions in the program – so code defined in FunctionOne() and FunctionTwo() can access this global variable.

j < SIZE. i++) { for (j = 0. for (i = 0. We can pass the value of a local variable from one function to another via a parameter.000. then every other function definition will require a parameter so that the value of the variable can be passed to it. j++) { imageData[i][j] = 0. j < SIZE. for (i = 0. as a consequence. The version on the right will work. Compare the following versions of a program that uses a very large array (100.000 elements): Uses local variable (this is likely to crash due to an overflow of local storage. which is limited) #define SIZE 10000 int main(void) { int imageData[SIZE][SIZE]. Global variables are stored in a separate part of memory which is not as limited in size as the stack. Remember that ideally a function should be like a black box. There are two situations where it makes sense to use a global variable instead of a local variable (but these are guidelines rather than set rules): • if the variable is critical to the program and is used by every function but it is defined locally in the main() function. as the size of our programs increase. the code may be cleaner if the variable is made global and so the parameter is not needed in every function. j++) { imageData[i][j] = 0. this creates code which can be harder to maintain as when one function changes the value of the global variable. j. int i. i < SIZE. When we try to run the program. However. it will crash because there is not enough local storage (to store the memory for the very large local variable imageData). it is a good idea to use local variables whenever possible. } } return 0. the use of global variables makes the code harder to read and understand. In this case. this can affect the way another function which relies on the variable behaves. Importantly. int main(void) { int i. i < SIZE. because memory for storing global variables is not allocated on the stack and is not limited in the same way. if the storage required for that variable is very large (for example. so it is a good idea to try to avoid having the implementation of the function relying on a global variable. } } Uses global variable (this version will work as global storage is not limited in the same way) #define SIZE 10000 int imageData[SIZE][SIZE]. it might be an array with many elements). Lecture 18 – 92 – Course Manual (C Programming) .EngGen 131 S2 2013 Local or global? Use local variables whenever possible. } } return 0. In general. then there may not be room on the stack (where space for local variables is allocated when a function is called). The main advantage of using a global variable is information sharing – every function can access the global variable and so they are all able to share its value. j. i++) { for (j = 0. • This second point can lead to subtle errors if you are not careful. The version on the left will not work correctly.

For example. except that their values are initialised when the function is called. printf("a = %d\n". printf("result = %d\n". Remember that when a function is called. memory is allocated for storing any local variables and any parameters the function defines. } int TimesTwo(int a) { a = a + a. The value from the calling statement is assigned to the parameter which therefore has its own copy of the value. To begin with. The assignment to the variable result cannot happen until the function call has completed and returned a value. } The output when this code is executed is: a = 10 result = 20 The value of a is still 10 despite the changes made to the variable a in the TimesTwo() function. return a. as soon as the main() function is entered. result = TimesTwo(a). return 0. int a = 10. Let’s visualise the way memory changes as this program is executed.EngGen 131 S2 2013 Call by value Parameters in a function are exactly like local variables. When the statement: result = TimesTwo(a). Lecture 18 – 93 – Course Manual (C Programming) . a). is executed. only variable a is given a value. result). space is allocated for its two local variables: Initially. the first thing that happens is the function call takes place. consider the following code: int main(void) { int result. The variable result will initially store a garbage value which we visualise as ???.

EngGen 131 S2 2013 When the TimesTwo() function is called. This modifies the value of the local variable a in the TimesTwo() function. that is returned by the function essentially replaces the function call expression in the calling statement: 20 result = TimesTwo(a). Lecture 18 – 94 – Course Manual (C Programming) . 20. the return statement is executed: return a. In particular. This is equivalent to the assignment statement: a = 10. notice it has no effect on the local variable of the same name in the main() function. the body of the TimesTwo() function executes: The TimesTwo() function contains just one line of code: a = a + a. Now. All of the memory allocated for the TimesTwo() function disappears as soon as the function returns. In this case it only has the parameter a. The value. The value from the calling statement (the variable a in the main() function) is assigned to the parameter (the parameter a in the TimesTwo() function). Next. space is allocated for the local variables and parameters of the function.

When it returns. once the value 20 has been assigned to the variable result. 4. 6. the memory it was occupying is returned to the system and can be reused by subsequent function calls. Lecture 18 – 95 – Course Manual (C Programming) . is just like a local variable to the function in which it is defined • its value is initialised by assignment when the function is called. 3}. This will be discussed in more detail later. What would the prototype declaration for this SumArray() function look like? It could look like this: int SumArray(int nums[5]. double or even a structure). int values[5] = {2. but for now it will be useful to see what an array parameter looks like in a function definition. and any changes made to the parameter are local to the function Arrays as parameters There is one exception to the previous rule about parameters being local variables – and that is when the parameter is an array. which creates an array of ints. 1. 5). In summary: • any parameter (whether it is an int. sum = SumArray(values. and then calls a function to calculate the sum of all of the elements in the array: int sum. Consider the following code. we would visualise memory as follows: The TimesTwo() function no longer occupies memory.EngGen 131 S2 2013 Finally. int numElements).

In this case. 2. } Two-dimensional arrays as parameters When a two-dimensional array is passed to a function as a parameter. for (i = 0. 3). 4. Although it is often clearer. 4}. {1. way of declaring an array parameter which does not use square brackets when we learn about pointers). {2. 3}. int sum = 0. consider the following code which passes a two-dimensional array of ints to a function called SumArray(): int sum. How could this function be defined? Here is one possible definition: int SumArray(int nums[]. In fact. int numElements) { int i. i++) sum += nums[i]. return sum. 3. int rows. the prototype for the function must at least specify how many columns the array has: int SumArray(int nums[][3]. when passing two-dimensional arrays as parameters to functions. more common. 4. For example. to include both dimensions: int SumArray(int nums[4][3]. 2}. when an array parameter is defined. int numElements). In order to calculate where in memory each element of the array is. the compiler must at the very least know how many columns the two-dimensional array has. this is typically how it is done – the square brackets are empty (we will see another. int rows. int cols). 5} }. the prototype could look like this: int SumArray(int nums[]. {3. int values[4][3] = { {0. int cols). Lecture 18 – 96 – Course Manual (C Programming) . the compiler does need to know something about the dimensions of the array.EngGen 131 S2 2013 However. 1. i < numElements. the number of elements does not need to be specified in the square brackets. Therefore. sum = SumArray(values.

that tests the pseudo-random number generator to see how evenly the values it generates are distributed. i < rows. int rows. frequency[i]). i++) { frequency[rand() % (VALUES)]++. } printf("\n"). j < cols. int cols) { int i. } – 97 – The output from this program may be as follows: 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 0 0 0 0 0 0 0 0 0 0 99854 99899 100022 100177 100055 99729 99602 100653 100269 99740 Lecture 18 Course Manual (C Programming) .h> #include <stdlib. return sum. /* Generate and record the random numbers */ for (i = 0. int sum = 0. i++) { printf("%d: %d\n". int i. j. /* Print the values in the array */ for (i = 0. frequency[i]). } printf("\n").h> #define VALUES 10 #define NUM_RANDOMS 1000000 int main(void) { int frequency[VALUES] = {0}. i++) { printf("%d: %d\n". for (i = 0. i < VALUES. i++) for (j = 0. } Lecture 18 Summary Program ───────────────────────────── We can now write programs that are composed of individual functions. It prints the values in the array before and after the loop executes: #include <stdio. written as a single main() function. Consider the following program. } /* Print the values in the array */ for (i = 0. i. return 0. i.EngGen 131 S2 2013 One possible definition of this SumArray() function is as follows: int SumArray(int nums[4][3]. i < VALUES. j++) sum += nums[i][j]. i < NUM_RANDOMS.

int RandomBetween(int a. } the function definitions the function prototype declarations ────────────────────────────── Lecture 18 – 98 – Course Manual (C Programming) . Take. int numValues) { int i. int i. i. We could therefore define a function to print the array: void PrintArray(int values[]. } PrintArray(frequency. return 0. } printf("\n"). i++) { printf("%d: %d\n".h> #include <stdlib. the code that prints the elements of the array. i < numValues. values[i]). int numValues). } printf("\n"). This is poor style. At the moment. i++) { frequency[RandomBetween(0. } int RandomBetween(int a. i++) { printf("%d: %d\n". int main(void) { int frequency[VALUES] = {0}. this code is repeated in two separate places in the main() function (before and again after the random number generation). because if we wanted to change the way the array was printed then we would have to modify the code in two places. we could define a function to calculate a random number between an upper and lower bound – to make the expression that is used to index the array more readable. int numValues) { int i. VALUES-1)]++. i < NUM_RANDOMS. The complete code is: #include <stdio. VALUES). i < numValues.EngGen 131 S2 2013 The same program could be decomposed into functions. values[i]).h> #define VALUES 10 #define NUM_RANDOMS 1000000 void PrintArray(int values[]. int b). for (i = 0. for example. for (i = 0. i. int b) { return (rand() % (b-a+1)) + a. } void PrintArray(int values[]. for (i = 0. } Likewise.

we have imagined a section of memory (which we thought of as a box) that stores some value. Instead. and test whether a pointer is null use the -> operator to access the fields of a structure via a pointer variable declare an array of chars to represent a string. That section of memory is located at some address in the memory of the computer. There is no "string" type in C. A pointer is a variable that stores the address in memory of some other variable. when we have visualised a variable. Pointers are critical for allocating memory dynamically – although we aren’t going to be learning about dynamic memory allocation in this course. we will be learning the basics of pointers.EngGen 131 S2 2013 Lecture 19: Pointers and Strings (Part 1) Pointers are one of the most powerful programming constructs in the C language. or "refer to". like char. int and double constants have corresponding variable types that are used to store them. you should be able to: • • • • • • • declare a pointer variable and initialise it using the address operator (&) dereference an initialised pointer variable using the dereference operator (*) visualise a pointer variable as a box containing an arrow initialise a null pointer. In this lecture. Learning outcomes ──────────────────────────────────────── After this lecture. other variables. Lecture 19 – 99 – Course Manual (C Programming) . we will look at some of the basic ideas behind pointers and strings. So far. and initialise that array using the scanf() function define and call a function where the parameters are pointers MATLAB Comparison ──────────────────────────────────── Pointer variables are not supported in MATLAB. This allows us to have variables that "point to". a string in C is stored as an array of type char. A string constant is a collection of characters surrounded by quotation marks: "this is a string constant" Other types of constants. We have seen string constants appearing in our printf() statements. Pointers ────────────────────────────────────────────────── A pointer is a variable that stores an address in memory.

Visualising a pointer When we visualise a pointer variable we don't usually concern ourselves with the actual value of the address that it stores. a 10 p Lecture 19 – 100 – Course Manual (C Programming) . A pointer variable that stored the address 0x12FF60 would be said to "point to". However we must be careful when we are working with them. we draw a box (as usual) which contains an arrow that originates from the centre of the box and points to some other variable. the variable a is a variable of type int that currently stores the value 10. and p is a pointer variable that stores the address of the variable a. For example.EngGen 131 S2 2013 The diagram below shows a variable called a that stores the value 10: variable identifier value stored a 10 0x12FF60 address in memory of the variable a A pointer is a special type of variable which can store an address. that stores the address of the variable a. the variable a. as below: value stored p 0x12FF60 0x1300F0 address in memory of the variable p Pointers are a powerful part of the C language. and allow us to do some interesting things. like 0x12FF60. p. In the diagram below. Instead. or "refer to". as they are commonly the source of errors when not used correctly. we would visualise a pointer variable.

it does not point to anything. Another very common term for an uninitialised pointer is a "bad pointer". which is of type "pointer to int". We would visualise this as in the diagram below: a 10 p Lecture 19 – 101 – Course Manual (C Programming) . The pointer variable p is now initialised to store the address of the variable a. p = &a. &. Consider the following code: int a = 10. and reminds us that we should not use the pointer until we have initialised it. when we first declare a pointer variable.EngGen 131 S2 2013 Declaring a pointer To declare a pointer variable. In fact. This creates a variable called p. When applied to a variable. Initially. We would visualise this variable as follows: p x x x The "x x x" indicates that this variable has not been initialised. int *p. the address operator evaluates to the address of the variable – exactly what we want to store in a pointer variable. we say that variable p is of type "int *". Initialising a pointer To initialise a pointer. we use an asterisk "*": int *p. we can use the address operator.

(this is wrong) this pointer is bad. Similarly. we can dereference the pointer p in the previous diagram with the following statement: int result = *p. It is a unary operator which appears on the left hand side of a pointer variable. that is. as shown in the diagram below: a 23 p Warning – be careful The most common error with pointers is to try to dereference a bad pointer. or even worse. It accesses the variable that the pointer points to. and should not be dereferenced p x x x By assigning the value 23 to *p before we initialise p. The following code will corrupt some random part of memory (wherever the bad pointer happens to point): int *p. we can modify the value of variable a by assigning a new value to *p: *p = 23. a pointer which has not been initialised.EngGen 131 S2 2013 Pointer dereferencing The pointer dereference operator is the asterisk. For example. This may cause our program to crash immediately. it may be much later that the problem becomes apparent. we will overwrite whatever memory the bad pointer happens to point to. The golden rule is: make sure you never dereference a bad pointer. "*". *p = 23. This would store the value 10 in the variable result. This would assign the value 23 to the variable a. Lecture 19 – 102 – Course Manual (C Programming) .

Here we have dereferenced both pointers. a b c 1 x x x p 2 x x x s 3 Before we initialise p and s. and the pointer values change.EngGen 131 S2 2013 Example Let's look at another example involving pointers. b c 1 p 2 s 3 We have used the address operator "&" to initialise the pointers a b c 3 p 2 s 3 *p = *s. s = &c. Pay attention to how the variable values. they are bad pointers and so we visualise them as boxes containing "x x x" a p = &a. int *s. Lecture 19 – 103 – Course Manual (C Programming) . int *p. int a = 1. int b = 2. int c = 3. and the value stored in the variable that s points to is assigned to the variable that p points to. Essentially this statement does exactly the same thing as if we had done: a = c.

a b c 3 p 2 s 7 *p = 7. Lecture 19 – 104 – Course Manual (C Programming) . consider the statement: a = p. Similarly.EngGen 131 S2 2013 a b c 3 p 2 s 3 p = s. This is referred to as sharing. consider the following statement in relation to the previous diagram: s = 3. Essentially this makes p point to the same variable that s points to. This stores the value 7 in the variable that p points to. the value of both *p and *s is 7. For example. We must always appreciate the distinction between a pointer and what it points to. and the result is stored in the variable b. Notice that after this assignment statement. The types on either side of an assignment statement should always match. The value of *p is added to the value of *s. this is wrong because we can't assign a value of type "pointer to int" to a variable of type int. a b c 3 p 14 s 7 b = *p + *s. so this statement assigns the value stored in pointer s (which is the address of variable c) to the pointer p. No dereferencing is done. Notice that this has quite a different result to the previous statement. (this is wrong) Again. (this is wrong) This is wrong because we cannot assign a value of type int to a variable of type "pointer to int".

like this: p It is also possible to use the integer constant 0 directly to refer to the null pointer. The value NULL can be assigned to a pointer variable in the usual way: int *p. p = NULL. because any non-zero value represents the boolean true. and unlike a bad pointer.h> and <stdlib. It is therefore quite common to explicitly use a test before dereferencing any pointer which may be null: if (p != NULL) printf("%d\n". including <stdio. When the pointer is not pointing anywhere useful. printf("%d\n". but not all. Usefulness of null pointers Typically. *p). The constant NULL is predefined as part of the standard library.h>. we can use the value NULL to indicate this. We typically visualise a null pointer as a box that has a line through it. A pointer that stores the value NULL is said to be a null pointer. For example. That value is NULL. of the time. the following code: int *p = NULL.EngGen 131 S2 2013 Null pointers ───────────────────────────────────────────── There is a special value that a pointer can have when we want to indicate that it is not pointing to anything. So p = 0. the above test is equivalent to: if (p) printf("%d\n". It is an error to try to dereference a null pointer. would also set p to be a null pointer. *p). – 105 – Lecture 19 Course Manual (C Programming) . and because the value NULL is equal to zero. will cause our program to crash. In fact. we use a null pointer to indicate that a pointer variable is not currently pointing to anything valid. and actually appears in a number of the standard header files. *p). It is common to have a pointer in a program which points somewhere useful some. we can easily test to see if the pointer is null.

x location y we can also declare a pointer to a variable of this type: Point *locationPtr. location x y 10 20 Lecture 19 – 106 – Course Manual (C Programming) . } Point. location. In the same way that we can declare a variable of this type: Point location.y = 20. we use the ". locationPtr x x x as with any pointer variable.EngGen 131 S2 2013 Pointers to structures ────────────────────────────────────── Consider the following structure type: typedef struct { int x. x locationPtr location y To access the fields of a structure through a variable like location. locationPtr will initially be a bad pointer until we explicitly initialise it: locationPtr = &location." operator: location.x = 10. int y.

are necessary because the ". we can explicitly dereference it: (*locationPtr). has a higher precedence) than the "*" operator. (*locationPtr).y = 40. This operator consists of the following two symbols: "->".x = 30. around the *locationPtr.com/ Lecture 19 – 107 – Course Manual (C Programming) . and there is a special operator that can be used to access the fields of a structure through a pointer variable. rather than using the explicit dereference as shown above. Pointers to structures are quite common. locationPtr->x = 30. http://xkcd.e. locationPtr->y = 40.EngGen 131 S2 2013 To access the fields of a structure through a pointer variable. x locationPtr y 40 30 Note that the parentheses above." operator binds more tightly (i.

We could have set the size of the array to be larger and it would make no difference – it is the location of the null character that determines the end of the string. to read a string typed in by the user at the keyboard. like: char greeting[6] = "hello". For example. Remember that to initialise a variable. the size of the array here is 6 to accommodate the null character. greeting). to whatever text is typed at the keyboard. Any other elements in the array after the null character are simply ignored. greeting 'h' 'e' 'l' 'l' 'o' '###BOT_TEXT###' 0 1 2 3 4 5 the characters that make up the string "hello" are stored in the elements of the array the end of the string is indicated by the null character The end of the string is denoted by a special character called the null character. This will initialise the character array name. and the %s conversion specifier.EngGen 131 S2 2013 Strings ─────────────────────────────────────────────────── Strings in C are stored as arrays of type char. so the following declaration is just fine (and quite common): char greeting[] = "hello". consider the following: char name[100]. In fact. Lecture 19 – 108 – Course Manual (C Programming) . Whenever we write a string constant in our source code. we are not required to explicitly include the size of the char array when we are initialising it with a string constant. scanf("%s". and terminates it with the null character. The null character has an ASCII code of 0. printf("Please enter your name: "). Initialising a string with scanf() We can use the scanf() function. the scanf() function requires a pointer to that variable. name). We use the printf() function to print out a string using the %s modifier: printf("%s". The array variable name is a pointer to the first element in the array. Notice that although there are only 5 characters in the word. and is represented by the character constant '###BOT_TEXT###'. the compiler automatically creates the appropriate array of chars. The compiler will calculate that 6 elements are needed and will allocate the right amount of space.

printf("Hello %s". scanf("%s". consider the following program: char name[100]. and can even modify the way the program behaves. name). There are (non-standard) functions available in the Visual Studio compiler that are not vulnerable to overflows. but these are potential security risks. you can use a different function called gets(). name). If you want to read all of the text that is typed at the keyboard into a character array. the additional characters will overwrite the bytes in memory that appear after the array. Take the example above – the array is only 100 characters long. then rather than using scanf(). we won’t be writing code in this course that anyone will care to exploit! Lecture 19 – 109 – Course Manual (C Programming) . When the text "none of your business" is entered. gets(name). printf("Please enter your name: "). The gets() function takes the character array as a parameter. name). This time. Not only can these bugs be hard to find for a programmer (variables in your program that happen to be located in memory after the array can be randomly corrupted). the output would be: Please enter your name: none of your business Hello none of your business Buffer overflows A notorious vulnerability in C programs is that of buffer overflow. Malicious users may exploit these buffer overflows. and reads the input typed at the keyboard until a new line character is encountered: char name[100]. If the input string is longer than that.EngGen 131 S2 2013 Be aware that the %s conversion specifier will only read the text typed at the keyboard up to the first white-space character (a space. the output would be: Please enter your name: none of your business Hello none because the input stops being processed after the first space character in the text. Fortunately. printf("Hello %s". Both scanf() and gets() are vulnerable to buffer overflows – which is why the compiler warns us about using them. tab or newline). For example. printf("Please enter your name: ").

Any changes made to the values of x and y within the body of the Swap() function do not affect the values stored in a and b in the main() function. b). the values of a and b (which are local to the main() function) are copied into the parameters x and y. int y). the function gets a copy of the value of the parameter. Parameters are just like local variables inside a function. b). int y) { int temp = x. so any changes made to a parameter does not affect any variables in the code from where the function was called. that parameter is passed by value – in other words. x = y. } void Swap(int x. y = temp. will not work: #include <stdio. the output of this program is: a=10. a. int main(void) { int a = 10. main() a 10 the values of a and b are copied into the parameters x and y Swap() x 10 b 20 y 20 Therefore. b=%d\n". } When the Swap() function is called.h> void Swap(int x. return 0. Swap(a.EngGen 131 S2 2013 Pointers as parameters ──────────────────────────────────── When we pass a parameter to a function. printf("a=%d. b=20 – 110 – Lecture 19 Course Manual (C Programming) . int b = 20. This means that the following Swap() function. which is supposed to swap the values that are stored in the two parameters.

we need to initialise the pointer parameters x and y by passing them the addresses of the variables a and b: Swap(&a. *y = temp. when we call the Swap() function. as follows: void Swap(int *x.com/ Lecture 19 – 111 – Course Manual (C Programming) . main() a 10 Swap() x b 20 y This time. int *y) { int temp = *x. &b). we can modify the Swap() function to take two parameters of type "pointer to int". the program will actually swap the values that are stored in a and b. } Now. and the output will be: a=20. b=10 http://xkcd. *x = *y.EngGen 131 S2 2013 Now that we have seen how pointers work.

7. Item *b). void SwapLightest(Item *leftPos. The main() function calls this SwapLightest() function once for each element in the array. For example. 5. int weight. 2.h> #include <stdlib.c #include <stdio. and then displays the items in increasing order of weight. File: main.EngGen 131 S2 2013 Lecture 19 Summary Program ───────────────────────────── We can now write programs that use pointers to manipulate data stored in memory. and to the right of it. 6. a function called SwapLightest() is used. and how to refer to structures via pointers. This function takes a pointer to an Item in an array as a parameter. in the array. and swaps this Item with any element that is lighter than. int num). The program first displays all of the items in the order that they were manufactured. 4. 8. weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: weight: 111) 117) 104) 110) 129) 104) 118) 118) 122) 114) 104) 104) 110) 111) 114) 117) 118) 118) 122) 129) To sort the items by order of weight. 6. 4. int num). 9. void Swap(Item *a. We have also looked at how to pass pointers as parameters to functions. void PrintItems(Item items[]. 5. Lecture 19 – 112 – Course Manual (C Programming) . the following program simulates the manufacturing of a set of 10 items – each of which has a random weight. } Item.h> #define NUM_ITEMS 10 typedef struct { int order. 9. 0. 1. 3. 1. the output is as follows: Manufacturing order: (order of manufacture: (order of manufacture: (order of manufacture: (order of manufacture: (order of manufacture: (order of manufacture: (order of manufacture: (order of manufacture: (order of manufacture: (order of manufacture: Sorted (order (order (order (order (order (order (order (order (order (order by of of of of of of of of of of weight: manufacture: manufacture: manufacture: manufacture: manufacture: manufacture: manufacture: manufacture: manufacture: manufacture: 0. When the program runs. 8. 3. 2. 7.

return 0. i < NUM_ITEMS.order = i.order. i++) { SwapLightest(items+i. items[i]. int num) { int i. for (i = 0. weight: %d)\n". next). items[i]. for (i = 0.weight). NUM_ITEMS). i < num. } Lecture 19 – 113 – Course Manual (C Programming) . } /* Examines all num elements to the right of leftPos. } printf("\n").EngGen 131 S2 2013 /* This program creates a set of items. next = leftPos + 1. } printf("Sorted by weight:\n"). } printf("Manufacturing order:\n"). items[i]. } } void Swap(Item *a. *a = *b. } next++. NUM_ITEMS-i). i++) { printf("(order of manufacture: %d. NUM_ITEMS). i < NUM_ITEMS. int i. Item *b) { Item temp = *a. each with a random weight. } void PrintItems(Item items[]. i++) { items[i]. and also sorted by their weights */ int main(void) { Item items[NUM_ITEMS]. int num) { Item *next. while (next < (leftPos + num)) { if (next->weight < leftPos->weight) { Swap(leftPos. for (i = 0. PrintItems(items.weight = rand() % 30 + 100. and swaps any element with a smaller weight with the element currently stored at position leftPos */ void SwapLightest(Item *leftPos. and then displays the items in the order they were initialised. PrintItems(items. *b = temp.

and so on. i < NUM_ITEMS. NUM_ITEMS-i). order 9 weight 111 0 weight 117 1 weight 114 9 Swap() Every element that next points to which has a smaller weight value than the element that leftPos points to. NUM_ITEMS-i). ────────────────────────────── Lecture 19 – 114 – Course Manual (C Programming) . The SwapLightest() function then examines all elements to the right of leftPos: leftPos next order 0 order 1 .e. the second smallest Item in the array will be shifted to index position 1. When this main loop finishes. executes again.. when the SwapLightest() function is called the first parameter is a pointer to the Item at position 0 of the array (i. The third time through this loop. When this loop within the SwapLightest() function finishes. i++) SwapLightest(items+i. Then the main loop: for (i = 0. is swapped with leftPos. the left-most Item) and the second parameter is the value NUM_ITEMS (i. the third smallest Item in the array will be shifted to index position 2.. i++) SwapLightest(items+i. the number of Items in the array). the Item with the smallest weight will be stored in index position 0 of the array.e..EngGen 131 S2 2013 The loop that actually drives the sorting is this one: for (i = 0. i < NUM_ITEMS. The second time through this loop. The first time through the loop. the Items will be sorted into increasing order.

EngGen 131 S2 2013 Lecture 20: Project Discussion Lecture 20 – 115 – Course Manual (C Programming) .

EngGen 131 S2 2013 http://xkcd.com ────────────────────────────── Lecture 20 – 116 – Course Manual (C Programming) .

EngGen 131 S2 2013 Lecture 21: Pointers and Strings (Part 2) We have already covered the basics of pointers and we know that a pointer is a variable that stores an address in memory. is achieved by performing the appropriate vector operations. the standard library provides several functions for working with strings. String operations. We will now see that we can perform arithmetic with pointers and that array variables are. just pointers. We will look at some basic functions that we can perform with strings. Lecture 21 – 117 – Course Manual (C Programming) . A string is specified using single quote marks: MATLAB >> S = 'MATLAB'. like calculating the length of the string or concatenating strings together. in fact. you should be able to: • • • • • explain the result of applying the plus operator (+) to a pointer variable use pointers and array variables interchangeably describe the effect of modifying the elements of an array that is passed as a parameter to a function write code using several of the string functions defined in string. Learning outcomes ──────────────────────────────────────── After this lecture.h>. and we will look at how to pass strings as parameters to functions.h use the type char * when working with strings and when passing strings as parameters to functions MATLAB Comparison ──────────────────────────────────── A string in MATLAB is actually a vector whose elements are the ASCII codes for the characters. These functions are declared in the header file <string. In C. We have also seen that a string in C is simply a null terminated array of characters.

multiplying it by the index position of the element that we want (in this case 5) and adding the product to the address of the first element in the array (in this case 0x220). is simply a pointer to the first element in the array. numbers. arithmetic. numbers[5]. For example. 8}. we can visualise this array stored in memory as below: 0x220 0x224 0x228 0x22C 0x230 0x234 0x238 0x23C numbers 1 0 2 1 3 2 4 3 5 4 6 5 7 6 8 7 The elements of the array are stored in contiguous memory locations. 6. the memory locations (in hexadecimal) of each element are also given (even though we usually would not include these in such a diagram). 5.EngGen 131 S2 2013 Pointer arithmetic ───────────────────────────────────────── When we declare an array: int numbers[8] = {1. 2. 7. or base-16. is given by: &numbers[5] We can see from the diagram that the address of this element is 0x234. Notice that in the above diagram. this is 0x220. we can talk about the relationship between the addresses of the elements in the array. and therefore takes up four bytes in memory. Fortunately. Lecture 21 – 118 – Course Manual (C Programming) . the address of the first element in the array could be calculated as: &numbers[0] and in this example. so we do not need to worry about them. all in hexadecimal. Now that we know about the address operator. This is exactly the same as if we just had: numbers The array variable. Each element is an int. The type of the variable numbers is a "pointer to int". all of these address calculations are handled for us by the compiler. 4. This is calculated by taking the size of each element in the array (in this case 4). numbers &numbers[0] equivalent What about the addresses of the other elements in the array? The address of the sixth element in the array. 3.

EngGen 131 S2 2013 Pointer "+" operator The + operator can be applied to a pointer variable. 2. 7. 3. We can visualise these variables as in the diagram below: p x x x numbers 1 0 2 1 3 2 4 3 5 4 6 5 7 6 8 7 Let's initialise the pointer as follows: p = &numbers[1]. 6. int numbers[8] = {1. 8}. and the type of the pointer. The diagram now becomes: p numbers 1 0 2 1 3 2 4 3 5 4 6 5 7 6 8 7 Lecture 21 – 119 – Course Manual (C Programming) . 5. The result is also a pointer. The value of the new address depends on the value that was added to the original pointer. For example. consider the declarations below: int *p. which points to a new address. 4.

say n. will make the pointer p point to the next element in the array. which is equivalent to p = p + 1. the expression: p + 5 evaluates to a pointer to the element 5 places further on in the array. the result is a pointer to the element at the address which is (n * element size) bytes past the original pointer value. to a pointer variable. the statement: p++. as shown below: p numbers 1 0 2 1 3 2 4 3 5 4 6 5 0 6 8 7 Lecture 21 – 120 – Course Manual (C Programming) . in this case the element at index 6. For example. For example.EngGen 131 S2 2013 If we add an integer. this will update the array as follows: p numbers 1 0 2 1 3 2 4 3 5 4 6 5 0 6 8 7 We can modify a pointer using arithmetic. We can treat this like any pointer variable – for example we can dereference it and assign a new value to it: *(p + 5) = 0.

6. *(numbers+1). – 121 – Lecture 21 Course Manual (C Programming) .. whereas: numbers + 3 is a pointer to the element numbers[3]. It points to the first element in the array. 3. 8}. For example. numbers[1]. numbers 1 0 2 1 3 2 4 3 5 4 6 5 0 6 8 7 So what's the difference between numbers[3] and (numbers + 3)? The expression: numbers[3] is the int value stored at index 3 in the array numbers. numbers[3] = 10. Expression numbers[3] numbers + 3 Type int pointer to int Evaluates to the value of the element at index 3 a pointer to the element at index 3 Any array expression that can be written with the "[]" notation. 7. We can refer to the elements of this array as: numbers[0]. .EngGen 131 S2 2013 Pointers and arrays ─────────────────────────────────────── An array variable is essentially a pointer. consider the declaration: int numbers[8] = {1. as: *numbers. numbers[2]. For example. is equivalent to *(numbers + 3) = 10. can also be written using the pointer "+" notation and a pointer dereference "*".. *(numbers+2). ... 4. 5. 2. or equivalently.

5.EngGen 131 S2 2013 Array to pointer assignment We can assign an array variable to a pointer variable. This would be very inefficient as arrays can be quite large. 2. This makes the pointer variable p point to the first element (at index 0) of the array numbers. 7. 5. 3. p = numbers. int *p. and a function called SumElements() is called which returns the sum of all the elements in the array: int values[8] = {1. int *p. It is equivalent to assigning: p = &numbers[0]. An array called values is declared and initialised. 8}. Instead. it does not really distinguish between array variables and pointer variables. 8}. How would this SumElements() function be defined? What is the type of the parameter? – 122 – Lecture 21 Course Manual (C Programming) . int sum. the entire array is not copied. p = numbers. Subscripting on pointers As far as the compiler is concerned. the parameter stores a pointer to the array. 5. 6. We can use the [] notation with a pointer variable in exactly the same way that we use it with an array variable. 8}. 4. 7. 6. 6. sum = SumElements(values). So. 3. The following are all equivalent ways of referring to the int value stored at index position 3 in the array numbers: numbers[3] *(p+3) p[3] Arrays as parameters ────────────────────────────────────── When we pass an array to a function as a parameter. For example: int numbers[8] = {1. 2. 3. 4. 7. given the same declarations as before: int numbers[8] = {1. Consider the following code. 4. 2.

It means that we can only use this function to add up the first 8 elements of any array – and it means that if the actual array has fewer than 8 elements then the program will crash. The number 8 which appears in the body of the SumElements() function is a bit inelegant. A more reusable version of the SumElements() function that does this is defined below: int SumElements(int *numbers. the parameter numbers is going to store the address of the first element of the array. for (i = 0. int numElements) { int i. the prototype of the SumElements() function could be declared in either of the following two ways: int SumElements(int numbers[]). any changes that are made to the array in the body of the function will affect the original array. } Of course. sum = 0. } return sum. when the function is called. i++) { sum += numbers[i]. To resolve this problem. Either way. } The compiler allows us to define the parameter to this SumElements() function either of the type "pointer to int" or of the type "array of int". int numElements) { int i. sum. } } Lecture 21 – 123 – Course Manual (C Programming) . int SumElements(int *numbers). for (i = 0.EngGen 131 S2 2013 We now know that an array variable is really just a pointer to the first element of the array. consider the IncrementArray() function defined as follows: void IncrementArray(int *numbers. sum. i++) { sum += numbers[i]. the body of the SumElements() function would look something like this: { int i. i < numElements. Either way. for (i = 0. i++) { numbers[i]++. For example. because a function parameter stores a pointer to the first element of an array. i < numElements. } return sum. sum = 0. i < 8. a function like SumElements() would be passed two parameters – the array and the number of elements in the array. Therefore.

values[i]). } return 0. strcpy(copyOfGreeting. for (i = 0.h>. } the output would be: 2 3 4 5 6 7 8 9 String functions ─────────────────────────────────────────── C provides a number of functions for manipulating and working with strings. greeting). the destination array contains 100 elements. Prototypes for the string functions are defined in <string. which is easily large enough. as follows: int main(void) { int i. 8). 6. Several of the common string functions are described below: strcpy() The strcpy() function takes two parameters.EngGen 131 S2 2013 If we called this function from the main() function. 4. 2. If we call: strcmp(wordOne. wordTwo). IncrementArray(values. 3. and copies the string from the second parameter into the first. the return value will be: 0 a negative number a positive number if wordOne is identical to wordTwo if wordOne “comes before” wordTwo in standard alphabetical ordering if wordOne “comes after” wordTwo in standard alphabetical ordering Lecture 21 – 124 – Course Manual (C Programming) . strcmp() The strcmp() function compares two strings alphabetically. In this example. 8}. i++) { printf("%d ". char copyOfGreeting[100]. Notice that the destination array must be allocated to be large enough to store the entire string. 5. 7. char greeting[] = "hello". int values[8] = {1. i < 8.

printf("%d". char *p. p = greeting. For example: char phrase[100] = "the quick brown". which has the elements of the string animal appended to it. For this reason. it is very common to use the type "pointer to char" when working with strings. strlen(word)). *s. s = p. strcat(phrase. has been allocated to be easily large enough to store the appended characters. char animal[] = "fox". phrase). or number of characters.EngGen 131 S2 2013 strlen() The strlen() function returns the length. so any changes made to the string through one pointer will also be seen by the other pointer. animal). Lecture 21 – 125 – Course Manual (C Programming) . Also notice that the array phrase. It is important that we have allocated enough space in the array to store all of the characters of the appended string. printf("%s". This does not include the null character (which is just an indicator of where the string ends). Consider the following code: char greeting[] = "hello". both p and s point to the same string. The following code: char word[] = "cat". greeting 'h' 'e' 'l' 'l' 'o' '###BOT_TEXT###' 0 1 2 3 4 5 p s In this case. would print the value: 3 strcat() The strcat() function appends one string onto the end of another. char * An array variable is simply a pointer to the first element in the array. would produce the output: the quick brownfox Notice that no space is appended between the two strings (we could explicitly include this if we wanted). in a string.

s). here is how we could define our own function for calculating the length of a string: int MyStrLen(char *string) { int i = 0. p). MyStrLen("correct")). while (*string != '###BOT_TEXT###') { string++. greeting). For example. for a function that is passed a string. are all correct and would all produce the same output. String as parameters If we pass a string to a function as a parameter. i++. to be of type "pointer to char". } return i. an alternative way of defining the MyStrLen() function would be as follows: int MyStrLen(char *string) { int i = 0.EngGen 131 S2 2013 We can use either the pointer variables. would print the value: 7 Making use of pointer arithmetic. printf("%s". while (string[i] != '###BOT_TEXT###') { i++. printf("%s". } The function call: printf("%d". It is therefore common to declare the parameter. or the array variable to access the string. so the following statements: printf("%s". } Lecture 21 – 126 – Course Manual (C Programming) . we are passing a pointer to the first element in the array. } return i.

int main(void) { char secretWord[100].txt" void GetRandomWord(char *w).txt".h> <time. char *g). the following program plays a simple game of hangman. void InitialiseGuess(char *w. word n The first line of the file stores the number of words in the file.the word was: %s\n". while (!gameOver) { ProcessOneGuess(secretWord. gameOver = WordGuessed(guess). void ProcessOneGuess(char *w. secretWord). For example. } Lecture 21 – 127 – Course Manual (C Programming) . int n). char guess[100]. guess). It starts by selecting a random word from a dictionary file called "words.EngGen 131 S2 2013 Lecture 21 Summary Program ───────────────────────────── We can now write programs that work with Strings.h> <stdlib. and the words themselves are stored one per line. GetRandomWord(secretWord). int gameOver = 0. int WordGuessed(char *g).. InitialiseGuess(guess. The format of this file is as follows: n word 1 word 2 . (int)strlen(secretWord)). here is a small dictionary file: 4 apple banana orange pear The complete source code for this hangman program is below: #define _CRT_SECURE_NO_DEPRECATE #include #include #include #include <stdio. return 0. } printf("\nWell done .h> #define DICTIONARY "words.. For example..h> <string.

char input[10]. int numWords. for (i = 0. pos = rand() % numWords. i < n. } void ProcessOneGuess(char *w. i < pos. w[n] = '###BOT_TEXT###'. } } void InitialiseGuess(char *w. g[i] != '###BOT_TEXT###'. &numWords). g[i] != '###BOT_TEXT###'. "r"). char *g) { int i. srand((unsigned int)time(NULL)). "%s". for (i = 0. i++) { printf("%c ". for (i = 0. g[i]). int n) { int i. } void GetRandomWord(char *w) { FILE *fp. input). } fscanf(fp. "%d". w). for (i = 0. scanf("%s". i++) { if (g[i] == '_') countBlanks++. } ────────────────────────────── – 128 – Lecture 21 Course Manual (C Programming) . w). i. } return countBlanks == 0. i++) w[i] = '_'. i++) { fscanf(fp. i++) { if (w[i] == input[0]) g[i] = input[0]. g[i] != '###BOT_TEXT###'. "%s". } printf("\nEnter guess: "). fp = fopen(DICTIONARY. pos. int countBlanks = 0. fscanf(fp.EngGen 131 S2 2013 int WordGuessed(char *g) { int i. for (i = 0.

end Recursion ──────────────────────────────────────────────── Recursion is the concept of defining an algorithm in terms of itself. consider how we could define an algorithm for computing the sum of the integers from 0 to n: Algorithm to "compute the sum of integers" from 0 to n: • if n is 0. For example. What happens if the function that is called is the function itself? Learning outcomes ──────────────────────────────────────── After this lecture. For example. "compute the sum of integers" from 0 to n-1. repeat(x-1). the following function will print the greeting "HELLO!" as many times as specified by the parameter x: MATLAB function [] = repeat(x) if x > 0 disp('HELLO!'). The function definition simply needs to contain a call to itself.EngGen 131 S2 2013 Lecture 22: Recursion When we define the source code for a function to perform some task. we know we can make a call to another function to help solve part of the task. you should be able to: • • • take a simple recursive definition (consisting of a base case and a recursive case) and convert that to a recursive function draw a diagram representing the function calls made when a given recursive function is called with a small input value work out the output of a program which calls a simple recursive function with a small input value MATLAB Comparison ──────────────────────────────────── Recursive functions can easily be defined in MATLAB. and then add n – 129 – Lecture 22 Course Manual (C Programming) . the answer is 0 • otherwise.

int result = 0. value = Sum(3). printf("The sum of the first 3 integers is %d\n". In this example program. non-recursive function. int main(void) { int value. the function is called with an input value of 3: #include <stdio. In order for a definition of this type to be valid. } int Sum(int n) { int i. value). i <= n. return 0. it must consist of at least two parts: 1) 2) one or more base cases (which do not contain any self-reference) one or more recursive cases (which do contain self-reference) Many mathematical operations have recursive definitions: Sum of the first n natural numbers • base case: sum(0) = 0 • recursive case: sum(n) = n + sum(n-1) Factorial • base case: • recursive case: 0! = 1 n! = n × (n-1)! Defining recursive functions Let’s start with a very simple. This function calculates the sum of the integers from 0 up to and including the parameter n.h> int Sum(int n). } The output of this program would be: The sum of the first 3 integers is 6 Lecture 22 – 130 – Course Manual (C Programming) . } return result. i++) { result += i. Consider the Sum() function in the program below. for (i = 0.EngGen 131 S2 2013 Recursive definitions Many different algorithms (along with other things) have natural recursive definitions.

New memory is allocated for the new function and its local variables. and the loop iterates four times (for i = 0. the values of the local variables would be as shown.EngGen 131 S2 2013 We can visualise the memory for this program as follows. Immediately before the Sum() function returns. passing the value 3 as an input argument. The value stored in result is finally returned to the main() function.1. The parameter. Memory for this local variable is allocated on the stack. is initialised to 3. the main() function is called. Now the Sum() function executes. When the program first starts.3). stopping when i becomes 4.2. n. The value of result becomes 6. called value. Lecture 22 – 131 – Course Manual (C Programming) . and the memory allocated for the Sum() function disappears (is returned back to the system). The main() function then calls the Sum() function. The main() function only has one local variable.

i++) { result += i.EngGen 131 S2 2013 We know the Sum() function works correctly. } int Sum(int n) { int i. int result = 0. value). } It is very easy to understand how the Sum2() function works. it uses the Sum() function (which we know works correctly) to compute the sum of the integers from 0 to n-1. } int Sum2(int n) { return n + Sum(n-1). return 0. it does not call itself. value = Sum2(3). int main(void) { int value.h> int Sum(int n). So the Sum2() function will also work correctly. However. Look carefully at the definition of Sum2() in the following program. We could now define another function. and then simply adds n. called Sum2(). How does memory change? Well. } return result. Note that the Sum2() function above is not recursive – because although it does call another function. and notice that the main() function now calls Sum2(): #include <stdio. i <= n. again we start with the main() function: Lecture 22 – 132 – Course Manual (C Programming) . int Sum2(int n). for (i = 0. in this new function we could make use of the Sum() function. which also calculates the sum of the first n integers. printf("The sum of the first 3 integers is %d\n". To compute the sum of the integers from 0 to n. because the code is very simple to follow.

Memory is allocated on the stack for this new function call. Memory is allocated on the stack for this new function call. Now when the Sum() function returns. all three functions occupy space in memory on the stack. anywhere we call the Sum() function. Notice that at this point. that do exactly the same thing – they both compute the sum of the integers from 0 to n. Lecture 22 – 133 – Course Manual (C Programming) . it passes the value 3 back to the Sum2() function. So the value returned by the Sum() function call is added to the value stored in the local variable n – and this will then be returned back to the main() function.EngGen 131 S2 2013 This time it calls the Sum2() function. memory will be organised as follows. Finally. Sum() and Sum2(). we could equally well call Sum2() and get the same result. the Sum2() function returns the result of 3+3 to the main() function. The Sum2() function now calls Sum(). But now what we have are two correctly working functions. The only statement in the Sum2() function is the return statement followed by an arithmetic expression: return n + Sum(n-1). Immediately before the Sum() function returns. So presumably. but with an input value of 2. and passes the value 3 to it as an input value.

But computing sums is exactly what the Sum2() function does! We could replace that function call to Sum() with a call to Sum2(). int main(void) { int value. The base case for this problem will be that the result 0 should be returned if the value of the parameter n is 0. } else { return n + Sum(n-1). The problem is it will never finish. } else { return n + Sum2(n-1). printf("The sum of the first 3 integers is %d\n". We would then have: int Sum2(int n) { return n + Sum2(n-1). } } Lecture 22 – 134 – Course Manual (C Programming) . value).EngGen 131 S2 2013 The reason the Sum2() function calls the Sum() function. return 0.h> int Sum(int n). } } Now consider the original program again. correct. It will keep calling itself with smaller and smaller values (which will eventually become negative) until we run out of memory for storing the local variables that are allocated each time the function is called. value = Sum(3). We can now write our first. recursive function: int Sum2(int n) { if (n == 0) { return 0. The thing that is missing is the base case. but this time using just a recursive version of the Sum() function: #include <stdio. is to compute the sum of the integers from 0 to n-1. } This is almost a correct recursive method. } int Sum(int n) { if (n == 0) { return 0.

how does memory change when we run the previous program? Well. as always we start with the main() function: Every time the function calls itself. So. At this point the functions begin to return.EngGen 131 S2 2013 One of the best ways to understand recursion is to visualise how memory changes when a recursive function executes. freeing the memory used on the stack: Lecture 22 – 135 – Course Manual (C Programming) . memory is allocated on the stack for the new function call: Eventually the base case is reached (when the function is called with an input value of 0).

However.. it is equally important that the recursive step makes progress towards that base case. although it is important to have a base case. is defined to be 1: 0! = 1 n! = n * (n-1) * (n-2) * (n-3) * .… In fact. Successive calls to the Sum() function will be passed larger and larger parameters: Sum(11). or recursively. So. } } The logic here seems OK: the sum of the integers from 0 to n is the sum of the integers from 0 to n+1 with (n+1) subtracted. } else { return Sum(n+1) . Sum(12).EngGen 131 S2 2013 Incorrect recursion As indicated by the previous example. It is easy to see that this function will never finish: void Bad(void) { printf("very bad\n"). Consider the following incorrect method: int Sum(int n) { if (n == 0) { return 0. The recursive code follows easily from the definition: Lecture 22 – 136 – Course Manual (C Programming) .(n+1). * 3 * 2 * 1 In other words: 0! = 1 n! = n * (n-1)! If we were to write a function to compute the factorial of a number. Factorial The factorial of a number. Let’s say we call Sum(10). the function below is incorrect because there is no base case defined. n. For example. this function will not work.. a recursive function must have a base case – without one the function will be incorrect and will not finish. we could easily do it iteratively (using a loop). is the product of all integers from 1 up to and including n. the value of n will never be 0 and so the base case is never reached. Bad(). } But just having a base case is not enough. The factorial of 0.

This sequence can be defined recursively as follows. The following diagram shows how the rabbit population would grow. one male. are put in a field. one female. } else { return n * Factorial(n-1). Each row in the diagram shows the total number of pairs of rabbits for a given month: The Fibonacci sequence lists the number of pairs of rabbits in the population every month: 1 1 2 3 5 8 13 21 34 55 89 144 233 . Fibonacci investigated how fast rabbits could breed in ideal circumstances. Every number is the sum of the previous two numbers in the sequence.EngGen 131 S2 2013 int Factorial(int n) { if (n == 0) { return 1. Rabbits are able to mate at the age of one month so that at the end of its second month a female can produce another pair of rabbits. one female) every month from the second month on.. There are two base cases: Fibonacci(1) = 1 Fibonacci(2) = 1 Lecture 22 – 137 – Course Manual (C Programming) .. Suppose that our rabbits never die and that the female always produces one new pair (one male. He posed the following problem: Suppose a newly-born pair of rabbits. } } Fibonacci sequence In 1202.

Again.EngGen 131 S2 2013 and the recursive case is: Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2) ie. This memory is only deallocated when a function returns. the amount of memory used is proportional to the number of nested calls that are made to the same function which is often much larger than if the solution was coded iteratively (using loops rather than recursion). Space: Every time we call a function. this overhead is often significant compared to an iterative solution. which doesn't happen until we reach the base case. } else { return Fibonacci(n-1) + Fibonacci(n-2). Time: There is a certain amount of time overhead in calling functions – local memory is allocated and parameters are assigned their initial values. Typically. the number of rabbits in any given month = the number of rabbits in the month before + the number of rabbits there were two months ago (which is the number of newly born rabbits this month) Using this definition. } } Efficiency ──────────────────────────────────────────────── Is recursion an efficient way of solving problems? When we discuss efficiency. we are usually interested in how much of a particular resource (space or time) is used. Lecture 22 – 138 – Course Manual (C Programming) . space is allocated for its parameters and local variables. we can write a method to calculate the nth Fibonacci number in the sequence as follows: int Fibonacci(int n) { if (n <= 2) { return 1.

This grows extremely quickly.529 function calls. To calculate the 20th Fibonacci number requires 13.817. We can visualise the function calls being made as in the diagram below: 5 4 3 2 1 2 2 3 1 As we can see.402. Consider the following function call: Fibonacci(5). } else { return Fibonacci(n-1) + Fibonacci(n-2). } } This is actually extremely inefficient.465 function calls. To calculate the 44th Fibonacci number requires 1.EngGen 131 S2 2013 Consider the Fibonacci example again: int Fibonacci(int n) { if (n <= 2) { return 1. 9 function calls are required to calculate the 5th Fibonacci number. Lecture 22 – 139 – Course Manual (C Programming) .

printf("Backwards: "). then solves the smaller problem recursively by calling the function using the smaller problem.EngGen 131 S2 2013 Lecture 22 Summary Program ───────────────────────────── We can now write programs that solve simple problems recursively. } else { PrintReverse(word+1). The process of printing the string in reverse is done recursively. printf("Enter a word: "). and then takes the solution to the smaller problem and processes it in some way to generate a solution to the original problem. the following program prompts the user to enter a string. according to the following rules: Base case: if the string is empty. then print nothing Recursive case: print the reverse of the string consisting of all except for the first character print the first character The code for this program is below: #define _CRT_SECURE_NO_DEPRECATE #include <stdio. PrintReverse(word). scanf("%s". } } int main(void) { char word[100]. printf("%c". The basic idea is to define a function which decomposes a problem into a smaller problem. *word). } Output from this program is shown below (user input is in bold): Enter a word: programming Backwards: gnimmargorp ────────────────────────────── Lecture 22 – 140 – Course Manual (C Programming) . For example.h> /* Recursive function to display a string in reverse */ void PrintReverse(char *word) { if (*word == '###BOT_TEXT###') { return. and then displays the string in reverse. word). return 0.

as listed in the next section. It is usually an on-going process. As the requirements become known.EngGen 131 S2 2013 Lecture 23: Software Engineering Overview Software Engineering is the discipline of applying engineering principles to the design. User Interface Engineering User interface engineering is related to requirements engineering. and detailed planning and the application of theories is not necessary large scale theories of development are required to provide cost effective and reliable construction What is Software Engineering? ───────────────────────────── "Software is becoming as important as oil for making the world go round" Software engineering encompasses the theory. as the clients begin to better understand how a system can help them achieve what's required. technology. they are carefully specified in a document which is checked by the clients before the design phase starts. practice and application of software development. A number of important steps are involved in the development process. creation and maintenance of large software systems. Software Development Steps ─────────────────────────────── Requirements Engineering Requirements engineering involves working with the people who are going to use the software (the clients) to understand exactly what it should do. Analogy ────────────────────────────────────────────────── small scale development is simple. but focuses closely on the actual interface through which the clients will use the software. Lecture 23 – 141 – Course Manual (C Programming) . The capabilities and needs of the different users will be taken into account to design an interface which is intuitive and easy to use.

each describing how and when the above software development steps are applied in order to complete a software project. Support and Maintenance Once a software product is ready. Iterative models There are several different iterative models in which the software development steps are repeated in cycles. which includes identifying the individual components from which the system will be built. the overall design of the software can be developed. in which the software development steps are carried out sequentially. Detailed Design and Programming Once the software architecture is clear. and more recently eXtreme Programming (which relies on feedback to drive the design. as satisfied users can see how it could be extended to help them even more.EngGen 131 S2 2013 Software Architecture and Design As the requirements get clearer. it needs to be installed so that it can be used. from requirements gathering through to installation – especially with large and/or complex systems. and with thorough reviewing and testing. Support can be provided through a combination of "help" within the software as well as dedicated "help desks". reliability and performance. Software Development models ────────────────────────────── There are several different models of software development. Examples of iterative models include the spiral model (which is essentially a sequence of waterfall models where additional design goals are added in each cycle). Quality Assurance Errors and misguided decisions inevitably creep in during all phases of software development. Installation. ────────────────────────────── Lecture 23 – 142 – Course Manual (C Programming) . If the design is good. detailed design and programming (coding) can occur. The requirements are analysed to generate a plan for the structure and organisation of the system. there are still many local design decisions required. This can lead to software products that don't do what is required or are difficult to use. Successful software is very likely to be changed. While many of the larger decisions have been made. the components that make up the system can be coded and tested independently. Quality assurance is achieved through setting measurable requirements for correctness. as well as introducing practices such as pair programming and test driven development). in the order they were listed above. Waterfall model The oldest model is the waterfall model. A small part of a software project is developed and thoroughly tested before additional functionality is added in subsequent cycles.

EngGen 131 S2 2013 EngGen 131 2013 Lab 7 An Introduction to Visual Studio GOALS FOR LAB 7 After successfully completing the compulsory exercises for this lab. It is important in this course that you are comfortable with how to use BOTH environments.zip” from Cecil. This file contains all of the resources that you will need to complete this lab. we can “run” the executable file which represents our program. a program called a “compiler” converts the source code that we write (the actual statements that we type that define our program) into an executable file that contains instructions the computer can actually perform. Assembler. This process is known as “compiling”. THE BASIC IDEA To develop programs using the C language.g.zip file called “Lab7Resources. Linker ) Executable file e. you will: • • • • • be able to write simple C programs that perform basic arithmetic and text-based input and output via the command line be able to use the “cd” and “dir” commands to navigate your way around directories from a Windows command line be able to compile C programs using either the command prompt interface (text-based interface) or Visual Studio (graphical-based interface) understand how a structure type is defined in C. C source file e. Lab 7 – 143 – Course Manual (C Programming) .c “compiling” ( Preprocessor.g. Once this conversion process is successfully completed. and visualise structure variables know what happens when one structure variable is assigned to another GETTING STARTED Download the .exe In this lab. you will gain experience compiling very simple C programs using both the Visual studio Command Prompt tool (this is a text-based interface) and the full graphical Visual Studio environment. hello. Compiler. hello.

and for simple programs you may find it faster and more convenient than launching the graphical interface and creating a new “project”. It is quick to use. from the Start menu: Microsoft Visual Studio 20xx > Microsoft Visual Studio 20xx Lab 7 – 144 – Course Manual (C Programming) . three videos have been created – you do not have to watch them. To launch the graphical Visual Studio environment. This environment gives us the choice of a powerful graphical based interface. or a very simple text based interface. For this lab. The text-based interface (which we will begin working with) provides a very simple way of compiling source code. but you may find them useful to refer to if you get stuck at any point. Programs are organised into “projects” which make it easy to manage a large number of source files (although most of the programs we write in this course will involve just one or two). Links to the videos are available on Cecil. like writing and compiling a program using the Visual Studio Command Prompt. or you can access them directly here: http://youtu.be/iEv7GiwiODw Using the Command Prompt Tools We will be using the Microsoft Visual Studio environment to develop our C programs.be/wpBQSY3WNEc http://youtu. To launch the Command Prompt tool. from the Start menu: Microsoft Visual Studio 20xx > Visual Studio Tools > Visual Studio 20xx Command Prompt The graphical interface provides an excellent editor for writing source code and a debugger that allows you to step one statement at a time through the execution of your program and inspect the values of variables as you do so.be/0wgJmmbjI-g http://youtu.EngGen 131 S2 2013 REFERENCE VIDEOS Sometimes videos provide the best way to illustrate certain mechanical processes.

Open the file in a text editor (you can use any editor you like for this first exercise.) – most errors that are made in this first stage happen when you are not sure where the file that you are working with is located. even something very basic like Notepad) and write the source code for a program which prints out "hello.txt” or “.EngGen 131 S2 2013 OK. the network drive.c”): STOP! Are you sure you have created a file with a “.g. it would be an excellent idea to have Windows explorer open (just like in the screenshot that follows) so that you can visualise where on disk your files are stored.txt” or “. and then rename the created file to “hello. let’s write our first C program To begin. we must write the source code for our program.cpp” or anything other than “. world": #include <stdio. your USB stick. Write your source code We are going to create a file (and a folder).c”. return 0. If you are working in the labs. All your C source files must end with a “. and will just display a basic greeting (we will follow tradition in this example.h> int main(void) { printf("hello world\n"). create a file inside this folder called hello. } Lab 7 – 145 – Course Manual (C Programming) . make sure you know where this folder is located! Then.c” extension? Take care that your file does not end with “. etc. Alright.c” extension. Start by creating a folder called Hello. the local hard drive of the computer. Again.c. Our first program is going to be very simple. now the easy part. and display the words “hello world”).c (one simple way to do this on Windows is to right-click and select “New > Text Document”. It is extremely important that you know where the file is located (e.

/out: hello.obj Lab 7 – 146 – Course Manual (C Programming) . This will bring up a command prompt window which looks similar to the following: Start by changing the drive displayed by the prompt to the drive on which your file is located. You can then use the "cd" command to navigate to the directory which stores your source file. All rights reserved. For example.30729.c As the source file is stored on the H:.EngGen 131 S2 2013 Compile the program Launch the Visual Studio Command Prompt tool. C:\Program Files\Microsoft Visual Studio 9. assume that we have stored our source file in the following location: H:\EngGen131\Hello\hello. Setting environment for using Microsoft Visual Studio 2008 x86 tools.01 Copyright (C) Microsoft Corporation. we would select this drive by typing "H:" at the command prompt.0\VC> H:###BOT_TEXT###gt; H: cd EngGen131 cd Hello _ H:\EngGen131> H:\EngGen131\Hello> Once the current directory is: "H:\EngGen131\Hello" you can compile the source file in this directory using the command: cl /W4 hello.c Microsoft (R) Incremental Linker Version 9. hello.exe hello.00. All rights reserved.c.30729. you should see output similar to the following appear in the command prompt window: Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.01 for 80x86 Copyright (C) Microsoft Corporation. Assuming all goes well.00. hello.c The purpose of the /W4 option is to ask the compiler to warn you about any problems it detects in your source code.

and obviously the program should display YOUR name!). An example of the output that your running program may produce is shown below (user input is in bold.e. Summary of useful commands (change drive. cd.obj” file which was produced by the assembler and passed to the linker to create the “.. how to navigate to the directory that contains your source file. you should be comfortable with how to open the command prompt window.exe”).e. to change to the H: C:###BOT_TEXT###gt; H: List files in the current directory For example. Change to a child directory (i. An equation that displays the sum of the two integers must then be displayed. H:\EngGen131\Lab7\ex1> ex1 Welcome to Lab One by Paul Denny! Enter two integers: 12 34 12 + 34 = 46 BONUS exercise: Remember. the int data type has a fixed size (typically 4 bytes) and therefore supports only a limited range of values. up one level) For example. to list files in H:\temp H:\temp> dir Change to the parent directory (i. What happens? Lab 7 – 147 – Course Manual (C Programming) . at the command prompt: H:\EngGen131\Hello> hello. how to use the cl tool to compile the code and how to run the resulting executable. You can run the program by typing the name of the executable file. "hello". down one level) For example. The program you demonstrate must display your name and prompt the user to enter two integers at the command line.EngGen 131 S2 2013 Run the program If you look inside the directory: H:\EngGen131\Hello you should see that a new file called "hello. to move from H:\A to H:\A\B H:\A> cd B EXERCISE ONE: Demonstrate to the lab tutor that you are able to open a Visual Studio Command Prompt window and compile and execute a simple C program.exe" has been created (there will also be a “. world hello Success! Notice that the output from the program appears directly in the command prompt window. to move from H:\A\B to H:\A H:\A\B> cd . Try adding together two numbers that are so large you generate an integer overflow. In particular. dir) Change drives For example.

or alternatively... Lab 7 – 148 – Course Manual (C Programming) .EngGen 131 S2 2013 Using the command prompt is very convenient and reliable. Creating a new project Visual Studio organises all of the files that are related to the program that you are working on into what it calls a Project.. select "New > Project" from the "File" menu. Next we will look at how to compile programs using Visual Studio’s graphical interface. To create a new Project. you can create one project and change the files that it contains each time you develop a different program. Launching the Visual Studio Application The screenshot below shows the main menu of Visual Studio. You can either create a brand new Project for every program that you develop. Under the “File.” menu you will see the option “New Project.”. The look and feel of the version that you are using may differ slightly from this (the version in the screenshot is Express 2012 for Windows Desktop)..

Visual Studio supports programming in a range of languages. Finally. when you were working from the command prompt. Make sure the box labelled "Create directory for solution" is NOT ticked: Click OK and you will be shown the "Application settings": IMPORTANT: Make sure to choose “Empty project” under Additional options above. Select "Win32 Console Application" from the templates listed under the Visual C++ Win 32 project type. make sure you know where this location is. We will be writing C programs that get input and produce output via a text window. you will run into problems when you try to compile the project. If you didn’t. click "Finish" and your new Project will be created. and choose a location (just like before. Lab 7 – 149 – Course Manual (C Programming) . it would be a good idea to view this in Windows Explorer). These are known as Console Applications. Enter a name (such as “Lab” or “Lab7”) for your project. If you are working in the labs.EngGen 131 S2 2013 A dialog box will appear when you create a new project. and hence there are many different types of Projects that you can choose from.

or to explicitly add ". and compile and run the program from within the Visual Studio interface. This is INCORRECT as Visual Studio will NOT link against the correct standard libraries when compiling your program.c" extension (NOT “.c" extension to the end of the filename. the full filename is "hello.cpp". A common mistake is to forget to include the extension. You will then be shown the "Add New Item" dialog box below. locate the folder on disk where the new project has been created. select the "C++ file" type: C++ and C are different languages.cpp”) IMPORTANT: when you create a new source file you must explicitly add a ". NOTE: Visual Studio does not list "C source files" explicitly as one of the installed template file types. alternatively. Or. you need to add a source file to the project. In this example. which in some situations can lead to frustrating errors. As you can see. Creating a new source file To develop a program. STOP! Before you go on. a project is comprised of a number of files. Lab 7 – 150 – Course Manual (C Programming) .EngGen 131 S2 2013 You will then be taken back to the main Visual Studio window. We can then write our code in the source file. Have a look at the new files that have been created. "Resource Files" and "Source Files".c". To do this. you can select "Add > New Item…" from the Project menu. The only one that really matters to us will be the source file that we will add to the project. This is an empty project – our next step will be to add a source file to this project. right click on the "Source Files" folder inside the Solution Explorer window. and the Solution Explorer pane will display the name of your project (in this example "Lab") along with folders "Header Files". All C source files should end with a ". Instead. and select "Add > New Item…" from the menu.

select "Save hello. Double-click “hello.c") and added to your project.c". a new empty file will be created (called "hello.c” in the Solution Explorer to open the source file and type the source code for the C program directly into the editor as shown on the right. This will save the source code you typed into the file "hello. select the option Start Without Debugging from the “Debug” menu: Lab 7 – 151 – Course Manual (C Programming) . The Solution Explorer pane displays the name of the file "hello. When you have finished writing the source code. Compiling and running your program To compile the code.c" in the "Source Files" section of the project. select the option Build Solution from the "Build" menu: To run the program. From the "File" menu. The editor displays the contents of the "hello.c" file (initially it is empty) – this is where you type your source code.EngGen 131 S2 2013 When you click the "Add" button. you should save it.c".

One error that may occur when you try to run your program is the following: This application has failed to start because MSVCR80D. Every program you write should include a comment which describes the purpose of the program – even if the program is very simple. Lab 7 – 152 – Course Manual (C Programming) . one fix is the following: Go into the project settings and change the "Code Generation" option under "Project Properties" from either MDd to MTd or from MD to MT. and end with the */ symbol. but if you do. Commenting your code makes it easier for others to read and understand what your program is doing.EngGen 131 S2 2013 Trouble shooting You may encounter problems from time to time that are no fault of your own – this can be frustrating but fortunately most problems have simple solutions. as shown in the screenshot below: Comments Comments begin with the /* symbol.dll was not found. to make it obvious that they are comments and will be ignored by the compiler. Re-installing the application may fix the problem You may not encounter this problem. You will notice that Visual Studio automatically colours any text between these symbols in green.

y = 20. . For example. #include <stdio. or typedefs. } Point. Lab 7 – 153 – Course Manual (C Programming) . In C. int main(void) { Point a. we might want to write a program that processes points on a 2-dimensional plane. } <name>. } The definitions of structures. usually occur just after the #include and #define statements (if there are any) at the top of the source file. a. a. b. grouped together under a single name.. return 0. Before we can store anything using this structure. This structure definition does not allocate space for any variables.h> typedef struct { double x. the basic user-defined data type is the structure (sometimes referred to as a record).x = 10.. For example. <type> <fieldName2>.y = 40. int y. so we can define our own data type for this. b. b. to define a structure to store our point data.x = 10.EngGen 131 S2 2013 Structures in C It can be convenient to compose new types of data by combining the basic data types. All that it does is define a new type called Point. } Point. we could declare the following structure: typedef struct { int x. We can define a new structure type using the following syntax: typedef struct { <type> <fieldName1>. we need to declare a variable of this new type. A structure consists of a collection of fields (also called components or members) which can be of different types. There is no predefined data type that allows us to store a point. each of which consists of an x and a y value. For example. the program on the left defines and uses Point structures. This allows us to work with variables which more closely match the basic kinds of data that we are manipulating in our programs. double y.

": Point p1. This assignment statement copies the values stored in each field of variable p1 into the fields of p2. p1.y = 150. which each require 4 bytes) Accessing fields To access the fields of a structure we use the structure selection operator. p2. So in this case.y = 150. p1 x 100 y 150 Structure assignment The assignment operator copies all of the fields from one structure to another: Point p1. x 100 p1 y 150 p2 y 150 x 100 Lab 7 – 154 – Course Manual (C Programming) . which is a ". p1. both p1 and p2 would require 8 bytes of storage (two variables of type int. We simply specify the type of the variable and give it a name. we could declare two variables called p1 and p2 of type Point as follows: Point p1.x = 100.x = 100. p1. p2 = p1. We would visualise these variables as follows: x p1 y p2 x y The amount of memory that is allocated to store a structure is just the sum of the amount of memory required to store each of the fields.EngGen 131 S2 2013 Declaring a structure variable Declaring a variable of a structure type is done in the same way as declaring a variable of one of the basic types. p1. p2. For example.

h> #define #define #define #define #define #define #define #define ACE JACK QUEEN KING 1 11 12 13 10000 20000 30000 40000 Remember. int main(void) { Card card1. card2.suit. clearly show how the values stored in the fields of these variables would change as the code above executes. } Notice that the main() function declares two variables (called “card1” and “card2” of type Card) – these are visualised as in the diagram below. printf("Card 1 = (%d %d)\n". Think about the effect this will have on the actual values that are stored in the fields of the structure. card1. return 0.suit.value = KING.value). card2 = card1. card2. SPADES HEARTS CLUBS DIAMONDS typedef struct { int suit. } Card. card1. Lab 7 – 155 – Course Manual (C Programming) .EngGen 131 S2 2013 EXERCISE TWO: Carefully read through the following code: #include <stdio. card1. card1. card1.value = ACE.suit = SPADES. Directly on the diagram below. printf("Card 2 = (%d %d)\n". and the values that are printed out. int value. card1.suit = HEARTS. the #define preprocessor directive performs a text search-and-replace BEFORE the code is even compiled.value). card2.

you can either create a new source file just as you did for "hello. you could create a brand new project. This will remove the source file from the Project.EngGen 131 S2 2013 Before running the code. it is often more convenient to simply reuse an existing project – all you need to do is swap the source file currently in your project with the new source file that you want to run. predict what you think the output is going to be.c" or you may have an existing file that you would like to add (select “Add > Existing Item”). right click on the source file in the Solution Explorer and select the "Exclude from Project" option. Create a new project in Visual Studio and add a new. To add a different source file. Lab 7 – 156 – Course Manual (C Programming) . Type the code exactly as it appears above into this source file. empty source file to this project (call the source file “ex2. Changing source files What should you do if you want to run a different program? Well. Then build and run the program. Write the output in the space provided below: Now. confirm that your prediction is correct.c”). To do this. However.

.....6 ... If you are unsure of the rules of Othello. If you like... you do not need to win the game! However.. so that others can look at your code and understand what your program is doing.8 To make your move..OX....5 .org/wiki/Reversi Good luck trying to beat this game on level 10 (although you may have to be patient with the time it takes the computer to move)! For this lab exercise. have a look at the Wikipedia entry: http://en... Have a quick look at the source code for this program. you should be comfortable demonstrating to the tutor that you can remove a specific source file from your project ("Exclude from Project") and add a new one ("Add > Existing Item... Although it is impossible to make any sense of the source code. Can you guess what this program will do when you run it........ you can reuse your project for the other lab exercises in this course......... This is an example of an obfuscated C program – it has been deliberately written to be very difficult to understand.....EngGen 131 S2 2013 EXERCISE THREE: Inside the “ex3” folder of the Lab7Resources..XO.. Then play the game of Othello (sometimes called Reversi): 12345678 .3 .7 ..1 ... just by looking at the source code? (Let me answer that for you: no) Run the program and have a look.wikipedia.. or a 99 to pass...zip file you will find a source file named “othello.... quite remarkably the program still functions correctly! It is a good example of how NOT to write programs in this course! The source code that you write should be as clear as possible.c”.2 . enter a number between 11 and 88 (representing the row and column in which you want to place your piece)...4 .")... COMPULSORY LAB TASKS END HERE Lab 7 – 157 – Course Manual (C Programming) . Begin by entering a difficulty level: 0-10 (easy-hard).

EngGen 131 S2 2013

EXERCISE FOUR:
The “Roomba” is a robotic vacuum cleaner developed by the iRobot company. Millions of Roombas have been sold since they were first available in 2002 (this is probably because vacuuming is not much fun!) The unique feature of a Roomba is that it uses sensors to navigate its way around a room avoiding obstacles. In this exercise you will program a robot called “picobot” which attempts to cover the entire floor space of a room using just local sensors (that can detect obstacles in the North, South, East and West directions).

Start by reading through the rules for using picobot. You will find these in the “PicobotRules.pdf” file in the Lab7Resource.zip file. The picobot environment is also available on Cecil – just choose the appropriate link depending on which browser you are using. How does this relate to programming? Abstractly, we can think about a running program as being in a particular “state” (as represented by the current values stored in the program’s variables) and transitioning from one state to the next by executing program statements (that use and modify the values stored in variables). Picobot is a very simplistic version of this – at any point in time picobot has a “state” that is a single number. As it senses its environment, it can transition from one state to another and move in one of four directions. NOTE: This exercise is a challenging puzzle that requires you to understand and interact with a simple computational system. If you solve it, and want an extra challenge, have a look at some of the other maps that picobot can attempt to explore!
Lab 7

– 158 –

Course Manual (C Programming)

EngGen 131 S2 2013

EngGen 131 2013 Lab 8 Conditionals, Loops, Arrays and Structures
This lab provides a summary of some of the topics covered in the corresponding lectures (Lectures 15 and 16). You should read through these notes before your lab session as preparation for the lab.

GOALS FOR LAB 8
After successfully completing the compulsory exercises for this lab, you will: • • • • understand how to store and access data in 1-dimensions arrays (this includes both arrays of integers and arrays of structures) know how to use loops to systematically access all of the elements of an array be able to write basic conditional statements to make decisions in your program have practiced storing data values typed by the user into an array

GETTING STARTED
Download the .zip file called “Lab8Resources.zip” from Cecil. This file contains all of the resources that you will need to complete this lab. This resource file contains only source files. You will need to create a Visual Studio project in order to compile and run the programs (of course you can do this using the command prompt if you prefer). Feel free to work either from the command prompt (just like Exercise 1 of Lab 7) or using a Visual Studio project (just like Exercise 2 of Lab 7). Make sure you organise your files appropriately. If you choose to use Visual Studio, here is one approach you might like to take: • • • • create a new project called Lab 8 copy the source files (ex1.c, ex2.c, ....) into the folder that was created for the project you can then use “Add existing item...” to add a source file to the project you can only have one source file (containing a main() function) at a time in the project, so to work on another exercise you will need to remove the existing source file first

Lab 8

– 159 –

Course Manual (C Programming)

EngGen 131 S2 2013

Conditionals
You can make decisions about which code to execute using if and else statements. Conditions are formed by combining relational and logical operators. A very simple condition is below: int number = 12; if (number > 10) { printf("The number is greater than 10.\n"); }

this condition evaluates to true, so the printf() function will be executed. Below is a more complex example. See if you can work out what the output of the following code is, and then try it out to confirm your answer: int a = 10; int b = 15; if ((a > b) || !((a == 11) || (b < 1000))) { printf("First"); } else if ((a == 10) && (b > 0)) { printf("Second"); } else { printf("Third"); }

Notice that although each block consisted of only a single statement, curly braces were still used to define the blocks. This is a good habit to get into, as forgetting to include the braces when a block of code does consist of multiple statements can lead to frustrating errors.

Loops
You can use a for loop or a while loop to repeatedly execute a block of statements. The following loops both print out the values: 0 1 2 3 4 for int i; for (i = 0; i < 5; i++) { printf("%d ", i); } int i; i = 0; while (i < 5) { printf("%d ", i); i++; } while

Lab 8

– 160 –

Course Manual (C Programming)

EngGen 131 S2 2013

Arrays
An array is a collection of variables of the same type. An array of ints is declared as follows: int numbers[SIZE]; where SIZE specifies how many elements the array should store.

We can visualise an array as a set of boxes, lined up horizontally side by side, each labelled with unique, increasing, index numbers starting from 0. For example, given the following declaration:

int data[8];

we would visualise this array as below:

data
0 1 2 3 4 5 6 7

We can access individual elements of the array by specifying the index or subscript inside square brackets. For example, the following loop will calculate the sum of all the integer values stored in the array above: int i, sum; sum = 0; for (i = 0; i < 8; i++) { sum += data[i]; }

Lab 8

– 161 –

Course Manual (C Programming)

given any particular set of starting values. you need to calculate the very next reading for the odometer assuming that the car has travelled 1 more mile. the very next odometer reading would be: odometer 0 0 9 1 1 2 3 3 0 4 9 5 The very next reading after this one would be: odometer 0 0 9 1 1 2 3 3 1 4 0 5 Lab 8 – 162 – Course Manual (C Programming) . We can visualise this array as follows: odometer 0 0 9 1 1 2 3 3 0 4 8 5 To display the current odometer reading. In the case of the digits above. with the most significant digit stored in index position 0. The values that are stored in the array will be entered by the user when the program runs. For this exercise. you can use a loop to print out each element of the array. Assume that the digits in this odometer are stored in an array.EngGen 131 S2 2013 EXERCISE ONE: The following picture shows a 6-digit digital odometer in a car (in this case displaying miles).

zip file. an algorithm that you might like to consider is as follows: _____________________________________________________________________ start at the rightmost (least significant) digit of the array increase the value of this digit by 1 as long as the value stored in the element is 10 set the element to 0 move one position to the left increase the value at this new position display the odometer reading _____________________________________________________________________ Lab 8 – 163 – Course Manual (C Programming) . odometer[i]). i++) { printf("Enter the value for digit %d: ". int digit. } To update the digits stored in the odometer array correctly. for (i = 0. i. i < NUM_DIGITS. printf("Lab 8 . &digit). Here is the provided code in ex1. } printf("\nOdometer reading: "). odometer[i] = digit.c: #define _CRT_SECURE_NO_WARNINGS #include <stdio. i++) { printf("%d ".c from the Lab8Resources.Exercise 4\n\n").h> #define NUM_DIGITS 6 int main(void) { // The array for storing the odometer digits int odometer[NUM_DIGITS]. i < NUM_DIGITS. scanf("%d". i). int changePos.EngGen 131 S2 2013 You should start with the source file ex1. Some of the code for this exercise (for reading input and displaying the initial odometer reading) has already been written for you. } you need to complete the code here return 0. for (i = 0.

Exercise 4 Enter Enter Enter Enter Enter Enter the the the the the the value value value value value value for for for for for for digit digit digit digit digit digit 0: 1: 2: 3: 4: 5: 1 5 9 9 9 9 Odometer reading: 1 5 9 9 9 9 Odometer reading: 1 6 0 0 0 0 PLEASE NOTE: For this exercise. and displaying the odometer reading has already been written. the output from the program should look like this (user input is shown in bold): Lab 8 . However. Lab 8 – 164 – Course Manual (C Programming) . When you have completed this exercise.Exercise 4 Enter Enter Enter Enter Enter Enter the the the the the the value value value value value value for for for for for for digit digit digit digit digit digit 0: 1: 2: 3: 4: 5: 0 9 1 3 0 8 Odometer reading: 0 9 1 3 0 8 What you need to do is add the code that calculates the very next odometer reading (assuming the car has travelled 1 more mile) and then print the new odometer reading to the screen beneath the original reading.EngGen 131 S2 2013 The code for reading the initial set of values from the user.Exercise 4 Enter Enter Enter Enter Enter Enter the the the the the the value value value value value value for for for for for for digit digit digit digit digit digit 0: 1: 2: 3: 4: 5: 0 9 1 3 0 8 Odometer reading: 0 9 1 3 0 8 Odometer reading: 0 9 1 3 0 9 Here is one more example: Lab 8 . the user is asked to enter the digits one at a time. you DO NOT need to test the case where the input is: 9 9 9 9 9 9. When you run the program. you should think about what might be needed to handle this case. and the initial odometer reading is displayed as shown in the example below (user input is shown in bold): Lab 8 .

Therefore. Assuming the user entered the values 10000 and 5. We can now store this user input in the first position of the array using two assignment statements: cards[0]. we would probably want to use a loop. To keep a track of where this next available position is. The array itself. the array would now look like: That was easy enough. For example: Card cards[100]. but also a variable that will indicate how many values are currently stored in the array. cards[0]. for example. we should declare not only the array.suit = suitInput. We could visualise this array as below (only the first 8 elements are shown in the diagram): Let’s say the user enters suit and value information for a particular card and we store this information in the variables suitInput and valueInput. and inside the body of the loop we would assign a set of values to the next available position in the array. Instead. } Card. is declared as follows: Card cards[100]. This variable will also tell us the index position of the next available element. we could use a variable to store it.EngGen 131 S2 2013 Storing user input in an array An array can be used to store a series of data values (these data values could. int value. which consists of 100 elements of type Card. int numCards = 0. So now we have: Lab 8 – 165 – Course Manual (C Programming) . The structure definition on the right shows the fields for a variable of type Card: typedef struct { int suit. Let’s assume the user is entering information regarding a set of cards. be entered by the user or they could be read from file on disk).value = valueInput. but now what happens when the user enters a second set of values? We don’t really want to be assigning one value at a time into the array using individual assignment statements (imagine if hundreds of values were going to be stored – our source code would not look very nice).

.suit = suitInput. Now assume the user enters the values 30000 and 1. assume the user enters the values 10000 and 5. we would visualise the variables as follows: The very next time through the loop. and then the value of numCards will be incremented (from 2 to 3). The variable numCards always keeps a track of how many of the arrays elements are actually being used to store values. // get input from the user cards[numCards]. } For example. These values will be stored in index position 2.value = valueInput. Pay attention to how the variable numCards is being used: while (numCards < 5) { . the value of numCards is 1. the variables would now store the data as follows: Let’s do this one more time. let’s assume the user is going to enter information about 5 cards. Lab 8 – 166 – Course Manual (C Programming) . so the values entered by the user will be stored in index position 1 of the array. After these loop statements have been executed. The variables will now store the following values: You get the picture. This time.. We could use a loop that executes exactly 5 times. cards[numCards]. and each time through the loop we store the values entered by the user in the next available position of the array. the very first time through the loop. It also indicates the index of the next available element of the array. After the loop body is executed. numCards++. and numCards has been incremented from 1 to 2. assume the user enters the values 20000 and 13.EngGen 131 S2 2013 Now.

update the number of cards . etc. and will then print all 5 cards in the hand. Finally.prompt for and read the next values from the user .EngGen 131 S2 2013 EXERCISE TWO: For this exercise. Two examples of the program running are shown below (user input is in bold). which will both be integers). three of a kind. a “flush” is when all cards in the hand have exactly the same suit. Hint: an algorithm for this problem might be along the following lines: . Your program will store these 5 cards in an array (each card is represented by a suit and a value.use a loop to print the values in the array .use a loop to check if all of the suit values are the same COMPULSORY LAB TASKS END HERE Lab 8 – 167 – Course Manual (C Programming) . In this case. can you also check for other common poker hands? Consider displaying just the strongest hand that the user has – a pair. full house. For more of a challenge. straight. > ex2 Enter suit and value for card Enter suit and value for card Enter suit and value for card Enter suit and value for card Enter suit and value for card (20000 3) (20000 5) (20000 7) You have a flush! 0: 10000 1 1: 10000 2 2: 10000 3 3: 30000 4 4: 30000 5 (30000 4) (30000 5) 0: 20000 3 1: 20000 5 2: 20000 7 3: 20000 9 4: 20000 11 (20000 9) (20000 11) BONUS challenge: it is actually pretty easy to determine if the hand is a “flush”. you will write a program that asks the user to enter information regarding 5 playing cards (these cards will represent a “hand” in a game of poker).store these values in the next available position of the array . Note the following things: • the prompt should display the number of the card to be entered (between 0 and 4) • when the hand is displayed.while the number of cards stored is less than 5 . each card should appear inside parentheses • the last line of output should display whether or not the hand represents a “flush” > ex2 Enter suit and value for card Enter suit and value for card Enter suit and value for card Enter suit and value for card Enter suit and value for card (10000 1) (10000 2) (10000 3) You do not have a flush. the program should display whether or not the hand represents a “flush”.

from index numValues-1 to 0 Run through this algorithm on paper to convince yourself it works.prompt for and read the next value from the user .use a loop to print the values in the array.if this value matches the first value the user entered. It means we have to think a little more carefully about the stopping condition for the loop that we use to store the values in the array. all of the values entered by the user should be displayed (in the opposite order to which they were entered) and then the program should end. and then implement your solution! Lab 8 – 168 – Course Manual (C Programming) . Write a program that prompts the user to repeatedly enter integer values. The input should end as soon as the user enters the same value as the first value they entered.use a variable to record whether the input loop should finish (initially set this to “false”) . At this point. this time we do not know ahead of time how many elements will be stored in the array – we will leave this up to the user to decide.otherwise. store the value in the array .while the input is not finished . Several examples of the output that should be produced by this program are shown below (user input is in bold): Enter Enter Enter Enter Enter 8 6 4 value: value: value: value: value: 2 2 4 6 8 2 Enter value: 1 Enter value: 1 1 Enter Enter Enter Enter Enter Enter Enter 2 3 4 value: value: value: value: value: value: value: 3 2 1 1 2 3 4 3 2 1 Hint: an algorithm for this problem might be along the following lines: . unlike before when we knew exactly how many values were to be stored. However.EngGen 131 S2 2013 EXERCISE THREE: This exercise is similar to the previous one in that we will store a series of values entered by the user in an array (although this time the array is of type int). set the loop variable to “true” .

and inspect the values of variables as you do so. Visual Studio includes a good debugging tool. as shown in the screenshot below: To use the debugger. it should return a certain result • and so on. This process is known as debugging. A debugging tool usually allows you step one line at a time through your program code. the value stored in the variable x should be 42 • that when a certain if/then/else statement is evaluated. for some complex cases using a proper debugging tool is a good idea. However. when you compile your code.. for example maybe it produces unexpected output or it simply crashes. ensure that the current configuration is set to Debug rather than Release. Using the Visual Studio Debugging Tool Firstly. but it turns out not to be. you need to locate and correct the bugs. you should work backwards and locate the bug that is causing the error. the else part should be executed • that when you call a function and pass it a certain value. In many cases.. You can: • use a printf() statement to print out the value stored in the variable x at any point in your code • put a printf() statement in each block of an if / else statement to see which branches are being executed • use a printf() statement to display the value returned by a particular function call • and so on. The debugging process basically involves confirming all the things that you believe are true when your program executes.. Developing good debugging skills and effective debugging techniques are vital to becoming a successful programmer. Lab 8 – 169 – Course Manual (C Programming) . you may believe: • that at a certain point in your code. you can set a break point on the line of code where you would like execution to halt so that you may inspect the values currently stored in variables at that point. As soon as you encounter something that you believe should be true.EngGen 131 S2 2013 Debugging When your program does not work correctly.. For example. or errors. in your code. using printf() statements is a simple and highly effective way to confirm things that you believe are true.

The statement that is about to be executed is indicated by a small yellow arrow: Lab 8 – 170 – Course Manual (C Programming) . select "Start Debugging" from the "Debug" menu. The program will then execute up to the line of code with the break point. Once the break point is reached. you can inspect the values stored in each of the variables at that time: You can then choose to execute the program one line at a time and watch the values of the variables change.EngGen 131 S2 2013 To set a break point you simply click the mouse button in the left margin next to the line you want to set the break point on: Then.

Note: If for any reason you do not see these options in the Debug menu. If you have previously entered a function definition with the Step Into option. If this line of code is a function call. Step Over this executes the current line of code (pointed to by the yellow arrow). then you will simply step down to the next line of code. Continue this resumes normal execution of the program. then the debugger will take you into where the function is defined and you can continue stepping through the code inside the function definition. This can be done by selecting Tools > Customize and dragging the commands from the Commands list to the toolbar or menu: Lab 8 – 171 – Course Manual (C Programming) . you can add them by customising the menu. If this line of code is a function call. but will execute the function call automatically and then take you down to the next line of code. If this line of code is not a function call.EngGen 131 S2 2013 You have the following options: Step Into this executes the current line of code (pointed to by the yellow arrow). then the debugger will not take you into the function definition. this option will take you back out to the original line of code which made the function call. up until the next time a breakpoint is encountered. Step Out this executes the current line of code (pointed to by the yellow arrow).

you can open it from the menu under Debug > Windows > Autos: The "Autos" window displays the variables that you are currently using at this point of the function. A break point has been placed on the line of code that increments the variable numInputs: At the bottom left corner of Visual Studio is the "Autos" window which shows the variables of interest at this point of the program (notice the line of code above has just updated an element of the array).EngGen 131 S2 2013 Locals and Autos Consider the code below (this is the summary program from the end of Lecture 15). but if it doesn’t. This window should appear automatically when you start debugging. If you want to display a list of all of the variables that are available to the function (called the local variables of the function) you can select the "Locals" window: Lab 8 – 172 – Course Manual (C Programming) .

When you start to debug the program. view the “Autos” window of the debugger. To begin. You should see the value of an element of the array change. choose one of your previous programs that uses an array (or write a new one). which gives you practice using the Visual Studio debugger. an array called “values” is being inspected): Now “Step Into” the code. set a break point on any line of code that modifies the value of an element in the array. the updated value should be highlighted red in the debugger: Lab 8 – 173 – Course Manual (C Programming) . Conveniently.EngGen 131 S2 2013 EXERCISE FOUR: In this exercise. Then. which should execute the statement on which you have your break point set. you should explore the “Autos” window of the debugger which allows you to inspect the current values stored in your program’s variables. Make sure you can view the elements of your array (in the screenshot below.

EngGen 131 S2 2013 Lab 8 – 174 – Course Manual (C Programming) .

h> int Add(int a. 25). return 0. sum). printf("Sum: %d". and what type its return value is. we need to tell the compiler what the name of the function is. int b) { return a + b. you will: • • • • • be able to open and read input data from text files stored on disk know how to define and call your own functions have mastered conditional statements have practiced calling functions from an external library (LibBMP) have decoded a message hidden in an image using steganographic techniques Function Prototypes If we are going to call a function we have defined.EngGen 131 S2 2013 EngGen 131 2013 Lab 9 File I/O and Functions This lab provides a summary of some of the topics covered in the corresponding lectures (Lectures 17 and 18). what type of parameters it is passed. } int Add(int a. } Lab 9 the prototype of the Add() function is declared here the Add() function is called here the Add() function is defined here – 175 – Course Manual (C Programming) . This can be done by declaring a prototype of the function. GOALS FOR LAB 9 After successfully completing the compulsory exercises for this lab. int b). at the top of the program before the main() function is defined. #include <stdio. You should read through these notes before your lab session as preparation for the lab. int main(void) { int sum. sum = Add(10.

For example. It is common to call this function inside a loop. to open an output text file on disk called output. you could use: int value. to open an input text file on disk called words. which returns a value of type int representing the character read from the file. Writing A file on disk can be opened for writing by calling the fopen() function. fscanf(fp. "%d". For example. Lab 9 – 176 – Course Manual (C Programming) .EngGen 131 S2 2013 File I/O Reading A file on disk can be opened for reading by calling the fopen() function. "r"). "w"). b). This is just like scanf() except you also must pass it the file pointer. you can call the fgetc() function.txt". The return value of this function should be assigned to a FILE pointer variable. you can call the fscanf() function. Closing It is good style to close a file when you have finished with it: fclose(fp). a. "my formatted output %d %f\n". which stops when the end of file is reached: int c.txt. you can use the fprintf() function: fprintf(fp. You also need to provide the appropriate conversion specifier – for example to read an integer value from file. you can call: FILE *fp. while ((c = fgetc(fp)) != EOF) { /* process the character stored in c */ } To read one value of a particular type at a time (which may consume more than a single character from the file). fp = fopen("words. fp = fopen("output. &value). To write formatted data into the output file. you can call: FILE *fp. The return value of this function should be assigned to a FILE pointer variable.txt.txt". To read one character at a time from the file.

to store information about a single Uno card: typedef struct { int type. The diagram below shows an example of how we might visualise the values stored in these two variables after initialisation: Lab 9 – 177 – Course Manual (C Programming) . card1. int colour. These variables could be initialised with a set of assignments statements. card2. card1. card2. card2.value = 0.value = 7. card2. such as: card1.colour = GREEN.type = REVERSE. int value.EngGen 131 S2 2013 Displaying cards A series of #define directives has been created for you to represent information regarding a set of Uno playing cards: #define #define #define #define #define #define #define #define #define #define #define NUMBER SKIP REVERSE DRAW_TWO WILD WILD_D4 RED GREEN BLUE YELLOW NONE 0 1 2 3 4 5 10000 20000 30000 40000 50000 A new type has also been defined for you. Consider the follow two variables defined to be of this new type: Card card1. } Card.colour = YELLOW.type = NUMBER.

value = 7.colour = YELLOW.type = REVERSE. Assume the DisplayCard() function has been defined (this is what you need to do) and that our main() function makes a call to this function.. DisplayCard(card1). card1. } Notice that the function call in the main() function: DisplayCard(card1). the values in the fields of the variable card1 are all copied across to the input parameter c. Lab 9 – 178 – Course Manual (C Programming) . as follows: void DisplayCard(Card c) { . The function will have a return type of void (because it doesn’t actually return a value to the calling statement. card2..EngGen 131 S2 2013 Your first job is to write a function that displays these cards in a format that is easy to read. So.. So in this example. The function prototype declaration will therefore look like: void DisplayCard(Card c) Let’s have a look at some code.. card1. card1.. we are assigning the variable card1 to the variable c.value = 0. and it will take one input of type Card. This is illustrated in the diagram on the next page. Because these are both structures. passes the variable card1 to the DisplayCard() function as an input.colour = GREEN. the value in the calling statement is effectively assigned to the input parameter in the function definition. card2. card2.. The name of the function will be DisplayCard. it just produces output to the screen using printf()).type = NUMBER. } int main(void) { Card card1. . remember that when you pass an input to a function. card2. what actually happens here? Well.

For example. This time. DisplayCard(card2). the type followed by the colour is displayed Lab 9 – 179 – Course Manual (C Programming) . DisplayCard(card1).EngGen 131 S2 2013 The DisplayCard() function should print out the card information in a readable format. the output should be: Two cards: 7_GREEN REVERSE_YELLOW Pay attention to the following things: • • • • • • the output is all in upper case the DisplayCard() function itself does not print a new line or a space separate words in the display of one card are separated by an underscore character if the card is of type number. printf(" "). then the value followed by the colour is displayed if the card is of type wild or wild draw 4. the output from the function call illustrated above should be: 7_GREEN Now consider these two function calls: printf("Two cards: "). then only the type is displayed if the card is any other type.

use fscanf() in a loop to read the remaining values. the first set of 3 numbers after the first number (i. 7 cards are represented. colour and value information for a card. You should start by using fscanf() to read the first number from the file. This is the input file that contains the data representing a set of cards. displaying all 7 cards represented by this data would give: SKIP_RED 9_BLUE WILD DRAW_TWO_YELLOW 0_GREEN 4_GREEN WILD_DRAW_FOUR Open the file called “input.txt”. three at a time. The output should be as shown above. Then. The remaining numbers. Lab 9 – 180 – Course Manual (C Programming) . this represents the card SKIP_RED The next set of three numbers after this is: 0 30000 9 which represents the card: 9_BLUE In fact. 7) is: 1 10000 0 Interpreting this as the type. In this example.EngGen 131 S2 2013 EXERCISE ONE: Consider a text file that contains a list of integers: 7 1 10000 0 0 30000 9 4 50000 0 3 40000 0 0 20000 0 0 20000 4 5 50000 0 The first integer in the file represents the number of cards that are represented by the remaining values.h" which includes the header file that contains the constants representing the different cards.e. then represent a set of cards. when considered in groups of 3. Your program should begin with the preprocessor directive: #include "cards. For example. Write a program which reads this file as input. and displays each of the cards.

of the pixel • col: the column. channel) Once an image file has been loaded into memory. or horizontal position.bmp image: LoadBMPFile("fi. &width. 1 = green. of the pixel • channel: the colour channel (0 = red.bmp": is the name of the output image file – this will be created as output by the program and appear in the project folder • width: the width of the image • height: the height of the image Lab 9 – 181 – Course Manual (C Programming) .bmp": is the name of the input image file – this will already exist on disk in the project folder • &width: the address of the int variable that will be initialised to the width of the image once it is read from disk • &height: the address of the int variable that will be initialised to the height of the image once it is read from disk GetPixelValue(row. channel) Once an image file has been loaded into memory. Parameters: • "fi. or horizontal position. or vertical position. 2 = blue) SaveBMPFile("fo.bmp". col. 1 = green. or vertical position. 2 = blue) SetPixelValue(value. Parameters: • value: the intensity value (between 0 and 255) to be stored in the specified channel of the pixel • row: the row. this function sets the intensity value (between 0 and 255) of the specified channel of a pixel in the image. Parameters: • row: the row. row. height) This saves the image in memory out to a file on disk in BMP format. Parameters: • "fo. of the pixel • channel: the colour channel (0 = red.EngGen 131 S2 2013 The LibBMP library Recall from Lecture 16 that the LibBMP library provides the following methods that you can use to load and access the pixel values of a . &height) This loads an image file stored on disk in BMP format into memory. col. this function returns an integer value (between 0 and 255) representing the intensity of the specified colour channel of a pixel in the image.bmp". of the pixel • col: the column. width.

0). This image looks perfectly normal. row. SetPixelValue(0. red = GetPixelValue(row. green and blue components sum to an odd number). SetPixelValue(0.bmp" in the Lab9Resources. Hint: the message is encoded in the "odd" pixels (the pixels for which the intensities of the red. and: int blue. 1). however there is a secret message hidden in the pixels of this image. would return the intensity of the “red” channel for the pixel at position (row. row. col. see if you can decode the hidden message. would return the intensity of the “blue” channel for the same pixel. SetPixelValue() The colour of the pixel at position (row. COMPULSORY LAB TASKS END HERE Lab 9 – 182 – Course Manual (C Programming) . 0). col. row. 2). Have a look at the image "auckland. B=2) to 0: SetPixelValue(0. col. col). col) can be changed to black by setting each of the three colour channels (R=0. blue = GetPixelValue(row. Using the LibBMP library.EngGen 131 S2 2013 EXERCISE TWO: Read through the description of the LibBMP library on the previous page. Make sure you understand how the two functions for getting and setting pixels work: GetPixelValue() int red. 2). col. col.zip file. G=1.

h> header file. int r = rand().h> To generate a random integer value between a and b inclusive.com/ Lab 9 – 183 – Course Manual (C Programming) .0 inclusive. http://xkcd. you can use the formula: int r = (rand() % (b-a+1)) + a. you can use the formula: double r = ((double)rand() / RAND_MAX). and the prototype for the rand() function are defined in the <stdlib. The RAND_MAX constant. The value of RAND_MAX is typically 32. To generate a random double (floating-point) value between 0. so you must include: #include <stdlib.EngGen 131 S2 2013 Random numbers You can call the rand() function to generate a random number between 0 and RAND_MAX.0 and 1.767.

EngGen 131 S2 2013

Circuit Reliability Estimation The components that make up a system can be connected in series or in parallel, or a combination of the two. The system will work if there is a pathway of working components from one side of the system to the other. If you know the reliability of each individual component within a system, then you can determine the overall reliability of the system. Series When components are connected in series, for example:

A

B

both A and B must work for the system to work. In this case, the reliability of the system, RS, is related to the reliabilities of the components, RA and RB, according to the formula: RS = RA × RB For example, if the reliability of component A is 75% (i.e. component A will be working 75% of the time) and the reliability of component B is 40%, then the reliability of the system will be 30% (i.e. there will be a working pathway through the system 30% of the time). Parallel When components are connected in parallel, for example: A

B

the system will work as long as at least one of the components work. In this case, the reliability of the system, RS, is related to the reliabilities of the components, RA and RB, according to the formula: RS = 1 – ((1 – RA) × (1 – RB)) For example, if the reliability of component A is 75% (i.e. component A will be working 75% of the time) and the reliability of component B is 40%, then the reliability of the system will be 85% (i.e. there will be a working pathway through the system 85% of the time).

Lab 9

– 184 –

Course Manual (C Programming)

EngGen 131 S2 2013

Monte-Carlo estimation While an exact, theoretical measurement is ideal, it is not always possible in practice. One technique that can provide good estimates easily is a Monte-Carlo simulation. With a Monte-Carlo simulation random values are used to calculate one possible outcome – this is then repeated many, many times to get an overall, average measurement. Using our system reliability example, the basic idea would be: • • • for each component, generate a random number between 0 and 1. If the probability of the component working is greater than this number, then you can consider the component to be working if there is a pathway of working components, then the system is working repeat these steps many times and determine the ratio of how many times the system is working to the total number of trials

One approach you can use for determining whether there is a pathway of working components is to assign a value of 1 (true) to the working components, and assign a value of 0 (false) to the components that are not working. For example, if the components are connected in series:

A

B

we can determine which components are working using: a = ((double)rand() / RAND_MAX) < RA; b = ((double)rand() / RAND_MAX) < RB; and the system will be working if (a && b) is true.

If the components are connected in parallel:

A

B

we can again determine which components are working using: a = ((double)rand() / RAND_MAX) < RA; b = ((double)rand() / RAND_MAX) < RB; but now the system will be working if (a || b) is true.

Lab 9

– 185 –

Course Manual (C Programming)

EngGen 131 S2 2013

EXERCISE THREE:
Implement a Monte-Carlo algorithm to estimate the reliability of the following system:

C A D B E F

given that the reliabilities of the components are as follows:

RA = 0.4 RB = 0.9 RC = 0.6 RD = 0.5 RE = 0.2 RF = 0.7

Questions: What is the theoretical reliability of this system? What is the calculated reliability from your program when you run:

10 trials? 100 trials? 1000 trials? 10000 trials?

Approximately how many trials do you need to perform in the Monte-Carlo simulation before the calculated reliability is accurate to 3 decimal places compared with the actual reliability?

Lab 9

– 186 –

Course Manual (C Programming)

EngGen 131 S2 2013

EXERCISE FOUR:
Read the description of the following algorithm very carefully. This algorithm describes a process for plotting a collection of points. 1) Initialise point A to (100, 173), point B to (0, 0) and point C to (200, 0). The relative positions of these points is illustrated in the diagram below – they approximately form an equilateral triangle. Plot these points.

A
(100, 173)

(0, 0)

(200, 0)

B
Ask the user how many points they would like to plot.

C

2)

Define a fourth point (call it D) which should be randomly positioned anywhere – it does not need to be inside the triangle. Plot this point. Select either A or B or C at random, and plot the midpoint between this random vertex and point D. Set D equal to the last point plotted. Repeat steps 3 and 4 over and over again, until the number of points the user wanted to plot have been plotted ________________________________

3)

4) 5)

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #define FILENAME "points.txt" typedef struct { double x; double y; } Point; int main(void) { FILE *fp; Point a, b, c, d; int i, numPoints, pick;
Lab 9

For this exercise, you need to write a C program which implements this algorithm and which writes out to file the positions of all the points plotted. You should start by downloading the file ex4.c from the Labs website. The code for this file is listed on this page.

– 187 –

Course Manual (C Programming)

"%f %f\n".y = 0. numPoints).x.\n"). Open this file and have a look at the values it stores.796875 Lab 9 – 188 – Course Manual (C Programming) . The format of this output file should be one point to a line.y).140625 130.txt" you may see something like: 100.EngGen 131 S2 2013 /* Initialise the positions of points a. c.562500 4.125000 8. 4 and 5 of the algorithm The first two steps of the algorithm have already been implemented for you. b.\n". &numPoints).000000 0.250000 16. "w").000000 200.y = 173. b.x = 100.y = 0. c.750000 105.y).x = (double)(rand() % 100). b and c */ a.x = 0. } /* Output the initial three fprintf(fp. When you have finished writing the code that implements the remaining steps of the algorithm. a.y = (double)(rand() % 100). fprintf(fp.187500 76. return 0. "%f %f\n".x. d. You should begin by compiling and running the program and observing the output.000000 0. fp = fopen(FILENAME. c. if (fp == NULL) { printf("Error opening exit(EXIT_FAILURE).x.500000 33.000000 173. /* Read the number of points to plot */ printf("Enter number of points: ").000000 0.x.593750 88. fprintf(fp. "%f %f\n". You need to add the appropriate code in here to implement steps 3. scanf("%d". points */ a. then the y-coordinate of a single point. /* Close the file */ fclose(fp). Each line should store the x-coordinate. a. d. b. c. For example.y).000000 67.500000 10. d.txt".x = 200. b.375000 52.y). /* Initially point d is at some random location */ d. you should test your program by plotting a small number of points. } file. printf("%d points output to file. if you plot 10 points and then look at the contents of the file "points. "%f %f\n". A new file should have been created on disk called "points. then a space. Make sure you understand where the values have come from in the source code of the program.000000 41.281250 88.000000 20. fprintf(fp.

What does the pattern look like? Zoom in to certain areas of the plot and note the self-similarity. However.'). try plotting a large number of points.bmp": is the name of the output image file – this will be created as output by the program and appear in the project folder bo: is a two-dimensional array of Colour structures that stores the colour information for the output image to be written to disk width: the width of the image height: the height of the image Lab 9 – 189 – Course Manual (C Programming) . &width. bi[row][col]. where: • "fi. Image manipulation The GetPixelValue() and SetPixelValue() functions from the LibBMP library can be used to modify a BMP image. This file can be loaded into MATLAB and plotted using the commands: >> load points. but which give you direct access to the pixel data in memory. &height).bmp". as you would have seen in Exercise Three. points(:.2). col) can be accessed using: bi[row][col]. The LibBMP library includes two other functions.1). Next.bmp". width.green. '.blue. the image is stored internally in memory and cannot be accessed directly.EngGen 131 S2 2013 Finally.red. you should use MATLAB to visualise where these points are positioned when plotted. LoadColourArray("fi. bi[row][col]. bi. say 10.txt >> plot(points(:. height). SaveColourArray("fo. which require you to understand structures and arrays. the colour information for the pixel at position (row. bo.000 and visualise them again using MATLAB.bmp": is the name of the input image file – this will already exist on disk in the project folder • bi: is a two-dimensional array of Colour structures that will be initialised when the image is read from disk • &width: the address of the int variable that will be initialised to the width of the image once it is read from disk • &height: the address of the int variable that will be initialised to the height of the image once it is read from disk • once this function has been called. and: • • • • "fo.

You should compile and run it and have a look at the output file. without performing any rotation.h" Colour bitmapIn[MAXW][MAXH]. /* Read colour information */ LoadColourArray("vulture. int row. } } /* Save colour information */ SaveColourArray("vultureout. for (row = 0. bitmapIn. can be downloaded from the Labs website and will help you get started. } these arrays are declared outside of the main() function because they require a large amount of memory Lab 9 – 190 – Course Manual (C Programming) . row++) { for (col = 0. width. bitmapOut. &height). col < width. At the moment.c. called ex5. return 0. col.bmp".h> #include "LibBMP. row < height. Colour bitmapOut[MAXW][MAXH].EngGen 131 S2 2013 EXERCISE FIVE: Write a program which uses the LibBMP library and takes a BMP image file as input. this program simply duplicates the image file. int main(void) { int width = 0. and produces a BMP image file as output which is identical to the input image except it has been rotated by 180 degrees. col++) { bitmapOut[row][col] = bitmapIn[row][col]. #include <stdio. int height = 0.bmp". height). &width. The following skeleton file.

byte blue. These definitions are in the file LibBMP. so that the resulting colour is a shade of gray. you will need to set the red. } Colour. green and blue components for each pixel.59green + 0. but this will not produce a nice result for certain colours. where the byte type is a synonym for unsigned char. To do this. What is the correct intensity value to use? You could try calculating an average of the red. as defined by the following typedef: typedef unsigned char byte. The correct formula to use. the variables bitmapIn and bitmapOut are declared outside of the main() function. for example try converting the colour image to gray scale (so it looks like a black and white photograph). Lab 9 – 191 – Course Manual (C Programming) . green and blue components for each pixel to the same intensity value.3red + 0. and it is more efficient to store them outside of the function definition.EngGen 131 S2 2013 Note. byte green. which computes the luminance of a pixel is: luminance = 0.11blue The colour information for each pixel is defined by the structure: typedef struct { byte red. However.h. The amount of storage required for these variables is large. ordinarily you would declare your variables inside a function definition such as the main() function. Try manipulating the image in other ways.

com/ http://xkcd.com/ Lab 9 – 192 – Course Manual (C Programming) .EngGen 131 S2 2013 http://xkcd.

int result = *p. x = &a.EngGen 131 S2 2013 EngGen 131 2013 Lab 10 Pointers and Strings GOALS FOR LAB 10 After successfully completing the compulsory exercises for this lab. we use the & operator: To dereference a pointer variable. b). printf("%d %d\n". int temp. A simple example using pointers involves swapping the values stored in two variables without using an explicit assignment statement for either variable. a. /* Now let’s swap the values in a and b */ int *x. *y. The output of this code is: 20 10 Lab 10 – 193 – Course Manual (C Programming) . y = &b. *x = *y. int b = 20. we use the * operator: int *p. Consider the code given below: int a = 10. *y = temp. temp = *x. you will: • • • • understand how strings are represented in C as an array of characters have practiced passing strings to functions as parameters have an understanding of how memory is organised when function calls are made know how to write functions that accept pointers to structures as inputs Pointers To declare a pointer variable. we use the * operator: To initialise a pointer variable. p = &a.

this time when we call the SwapCoordinates() function. then a copy of the value stored in the variable is given to the function. but it cannot modify the original value back in the function from which it was called. you can use pointers to modify a variable that is passed to a function. The function can then modify the value stored in the variable by dereferencing the pointer.EngGen 131 S2 2013 Pointers as parameters If you pass a variable (of any type except for an array) to a function as a parameter. if you have a variable of type Point (a structure type). When you call the function. we pass it the address of the variable: main() SwapCoordinates(Point *p) x 100 p y 200 p function call: SwapCoordinates(&p) Lab 10 – 194 – Course Manual (C Programming) . For example. you pass it the address of the variable. For example. and you pass this to a function called SwapCoordinates(). the SwapCoordinates() function will store its own copy of the values which make up the structure variable: main() SwapCoordinates(Point p) x 100 p y 200 p x 100 y 200 function call: SwapCoordinates(p) However. The function may change this copy.

p->y = temp. return 0. p. p.x = 100.y).y = 200. } main() SwapCoordinates(Point *p) x 200 p y 100 p function call: SwapCoordinates(&p) The output of this program is: Point: (100. the program below swaps the values of the coordinates x and y that are stored in a Point structure: #include <stdio. int y.x.EngGen 131 S2 2013 As a complete example. printf("Point: (%d.y). 100) Lab 10 – 195 – Course Manual (C Programming) .h> typedef struct { int x. p.x. printf("Point: (%d. SwapCoordinates(&p). p. 200) Point: (200. void SwapCoordinates(Point *p). %d)\n". p. p. p->x = p->y. %d)\n". int main(void) { Point p. } void SwapCoordinates(Point *p) { int temp = p->x. } Point.

EngGen 131 S2 2013 Here is a slightly more complex example where a pointer is passed from one function to another: int main(void) { int myValue = 0. printf("%d ".. However. myValue). we must use the & operator to calculate the address of the variable myValue (which is declared in the main() function). on LINE Y. } The output of this is: 10 20 Notice that when we call the two “passing. // LINE X // LINE Y Lab 10 – 196 – Course Manual (C Programming) . } void passingAnIntPointerOne(int *value) { *value = *value + 10. the value is passed directly (without &). the parameter “value” already stores an address. return 0. However. The variable myValue is actually stored within the memory allocated for the main() function. See the diagram to the right. within the memory allocated to the passingAnIntPointerTwo() function.” functions from within the main() function.. myValue). when passingAnIntPointerTwo() calls passingAnIntPointerOne() it is not necessary to use the & operator because we already have the address of the myValue variable. Therefore. printf("%d ". passingAnIntPointerTwo(&myValue). Therefore on LINE X it is necessary to calculate the address of this variable (using &) to pass it to the function. Look carefully at LINE X in the program above. passingAnIntPointerOne(&myValue). } void passingAnIntPointerTwo(int *value) { passingAnIntPointerOne(value).

EngGen 131 S2 2013 Colour matching In this exercise you will write a program that finds a card (within a player’s hand) that matches the colour of another card (the top card of the discard pile). If the user has 3 cards in their hand (2_GREEN. int colour. } Card. Understanding how this structure is used in this simple example will help you with your project. consider the following two structure definitions: typedef struct { int type. Card topCard. int value. The GameState structure shown here is a simplification of the structure that is used in your project. then this structure would store this information as follows: Lab 10 – 197 – Course Manual (C Programming) . Card yourCards[MAX_CARDS]. } GameState. and the code for this part of the exercise is provided to you. 8_RED and 6_BLUE) and the top card on the discard pile is 2_RED. typedef struct { int yourNumberOfCards. Assume we have a variable called gameState declared: GameState gameState. The user will input the values and colours of all of the cards. To begin with.

&card. if (result == -1) { printf(" . scanf("%d".value). gameState. The Play() function should return the index position of a card in the player’s hand that matches the colour of the top card on the discard pile. gameState. DisplayCard(gameState. then the function should return -1. Please note: • • this function calls DisplayCard(). i++) { printf("Enter card: "). for (i = 0. You should reuse your DisplayCard() function in this exercise this function also calls Play() – you still need to write this function. Lab 10 – 198 – Course Manual (C Programming) . &card. Card card. int result. If no matching cards exist. // Get player's cards printf("How many cards? "). // Display the result printf("Top card: "). // Call the play function result = Play(&gameState).yourCards[result]).colour. int i.topCard). DisplayCard(gameState. scanf("%d %d %d".EngGen 131 S2 2013 The following main() function initialises this gameState variable using values entered by the user: int main(void) { GameState gameState.value). &card.topCard = card.no match"). &card. &card. which is the function you should already have written in Lab 9. numCards. } else { printf(" matches: "). &numCards).colour.yourCards[i] = card. } You should type this main() function into your program. &card. } gameState. i < numCards. } return 0.type. scanf("%d %d %d".type. // Get the top card of the discard pile printf("Top of discard pile: ").yourNumberOfCards = numCards.

The actual memory for the gameState variable is allocated in the main() function.no match Lab 10 – 199 – Course Manual (C Programming) . We would visualise this situation as shown in the diagram on the right. This function should return an integer. First. both cards should be displayed: Top of discard pile: 0 10000 2 How many cards? 3 Enter card: 0 20000 2 Enter card: 0 10000 8 Enter card: 0 30000 6 Top card: 2_RED matches: 8_RED If there isn’t a matching coloured card. EXERCISE ONE: Complete the program (for which the main() function has been provided) by providing the Play() function. simple display “no match”: Top of discard pile: 0 10000 2 How many cards? 3 Enter card: 0 20000 2 Enter card: 0 40000 8 Enter card: 0 30000 6 Top card: 2_RED . A couple of examples of how the program should behave are shown below.EngGen 131 S2 2013 Note: When the Play() function is called. if there is a matching coloured card. you can assume that wild cards (WILD and WILD_D4) will not be entered. it is passed the address of the gameState variable. It should return the index position of any card in the player’s hand that is the same colour as the top card on the discard pile. For this exercise.

so the & is not used when calling scanf() – 200 – Course Manual (C Programming) . If the input includes. } In this example. and is represented by the character constant '###BOT_TEXT###'. return 0.h> int main(void) { char greeting[100]. followed by the null character). tab. printf("%s\n". greeting). printf("Enter a word: "). Finally.EngGen 131 S2 2013 Strings in C Strings in C are stored as arrays of type char. then nothing after that character will be stored in the array. printf("The word you entered was: "). the characters that make up the string "hello" are stored in the elements of the array the end of the string is indicated by the null character The end of the string is denoted by a special character called the null character. for example. the content of this array is printed to the screen. the user is prompted to enter a word. Lab 10 The variable “greeting” is an array. The scanf() function is used to read the string the user types and store it into the array called greeting (one character will be placed into each element of the array. The null character has an ASCII code of 0. The output from this program would be as follows (user input in bold): Enter a word: hello The word you entered was: hello NOTE: When used with the scanf() function. newline). the “%s” conversion specifier will only read characters up to the first white space (space. a space character. greeting 'h' 'e' 'l' 'l' 'o' '###BOT_TEXT###' 0 1 2 3 4 5 6 7 . scanf("%s".. greeting). Example: Consider the following program: #define _CRT_SECURE_NO_WARNINGS #include <stdio..

if (IsPalindrome(input)) { printf("###BOT_TEXT###quot;%s###BOT_TEXT###quot; is a palindrome". using either of the following approaches: *(word + n) word[n] Lab 10 – 201 – Course Manual (C Programming) . } Make sure you visualise memory correctly. } else { printf("###BOT_TEXT###quot;%s###BOT_TEXT###quot; is not a palindrome". When an array is passed to a function as a parameter. } return 0. input). The main() function then calls the IsPalindrome() function. only the address of the first element of the array is actually passed. and false otherwise. The main() function declares the array of characters that will store the string the user enters. and passes the array to it as a parameter. The memory for this array is allocated within the block of memory for the main() function. The main() function has already been written for you: int main(void) { char input[100]. This function should be passed one parameter. you need to define a function called IsPalindrome(). The function should return true if the string is a palindrome. input). You can start by downloading the file ex2. which should be a string (an array of type char). The IsPalindrome() function can therefore access the nth character in the array by dereferencing the pointer. scanf("%s". input).c from the Labs website. printf("Please enter one word: "). The following are examples of palindromes: a noon redivider For this exercise.EngGen 131 S2 2013 EXERCISE TWO: A palindrome is a word which reads the same forwards and backwards.

how should you locate the first and last character? Well. Several examples of the program running are given below (user input is in bold): Please enter one word: deliver "deliver" is not a palindrome Please enter one word: noon "noon" is a palindrome Please enter one word: a "a" is a palindrome COMPULSORY LAB TASKS END HERE Lab 10 – 202 – Course Manual (C Programming) . the first character is easy – that is always going to be at index position 0. If the two characters being compared are different. So. If the characters being compared are the same. and compare that with the first character in the word. The last character is going to be to the left of the null character. Note: you can assume the string will not contain any punctuation.EngGen 131 S2 2013 So how should the IsPalindrome() function determine whether or not the string is a palindrome? The basic idea will be to locate the last character in the word. so you can either search for this. and so on. then the string will be a palindrome. Then compare the second to last character with the second character. or if you know the length of the string you can work out what the index position will be. then the string will not be a palindrome. all the way to the middle character(s) of the string.

performing ROT 13 on the phrase: “Jrypbzr gb RATTRA 131” would give: “Welcome to ENGGEN 131” Lab 10 – 203 – Course Manual (C Programming) . the phrase: “Welcome to ENGGEN 131” would be encoded to “Jrypbzr gb RATTRA 131” One feature of the ROT 13 cipher. For example.EngGen 131 S2 2013 Basic encryption One of the simplest possible encryption schemes for a plain text string is to replace each character in the string with the character that appears some fixed number of letters down the alphabet. The mapping from one character to the next is shown (for the lower case characters) below: The same mapping exists for the upper case characters. All other characters (punctuation. white space) are preserved. As an example. This is known as a Caesar cipher (named after Julius Caesar who used this kind of encryption when sending classified messages) and the most common variant of this is known as ROT13 – which is when the fixed number of letters used to replace each character is 13. a consequence of 13 being half the number of letters in the alphabet. Only the upper and lower case alphabetic characters are modified when the ROT13 cipher is applied. is that performing ROT 13 on an encoded phrase will restore the original phrase.

} The constant MAX_PHRASE_LENGTH represents the longest possible phrase. In particular. the main() function is complete: #define _CRT_SECURE_NO_WARNINGS #include <stdio. It makes use of the EncodeCharacter() function.h> #include <string.h> #define MAX_PHRASE_LENGTH 100 void EncodePhrase(char *original. gets(phrase). printf("Encoded: %s\n". char *encoded). EncodePhrase(phrase. which is responsible for encoding a single character. For this exercise you need to define two functions: EncodePhrase() EncodeCharacter() The EncodePhrase() function is responsible for encoding an entire phrase. Once completed. You can assume the user will not enter phrases longer than this. return 0. encoded). vg'f ab jbaqre Whyvhf Pnrfne jnf fb fhpprffshy Lab 10 – 204 – Course Manual (C Programming) . int main(void) { char phrase[MAX_PHRASE_LENGTH]. char EncodeCharacter(char c). encoded).EngGen 131 S2 2013 EXERCISE THREE: Write a program that encodes a phrase entered by the user using the ROT13 cipher. You should make sure that lower and upper case characters are encoded correctly. and is used to specify the size of the string arrays. an example of the output that should be produced is given below (user input in bold): Enter phrase to encode: Wow. NOTE: Some code is already provided to you for this exercise. char encoded[MAX_PHRASE_LENGTH]. it's no wonder Julius Caesar was so successful Encoded: Jbj. printf("Enter phrase to encode: ").

Inside the memory allocated for the main() function are blocks of memory for the local variables that it declares.EngGen 131 S2 2013 You need to have a clear picture of how memory is organised. We would therefore visualise this as follows: Any changes made to the arrays in the EncodePhrase() function will change the original arrays (back in the main() function. In this case. only the addresses of the arrays are passed as parameters to the EncodePhrase() function (whenever an array is passed to a function. Lab 10 – 205 – Course Manual (C Programming) . only the address of the first element of the array is actually passed). When the main() function calls the EncodePhrase() function. which is where the memory is actually allocated). memory is allocated for the main() function. two arrays are declared in the main() function. When the program first begins. visualised as in the diagram below.

there are lots of ways this can be done. One obvious way is to use a very large if/else statement (consisting of 46 options. See if you can make use of the ASCII character codes to develop a more elegant solution (have a look at an ASCII table).e. this would have no effect on the values stored in the arrays. one for each of the upper and lower case characters). assume the character ‘a’ is passed to the EncodeCharacter() function from the EncodePhrase() function. The character ‘a’ has an ASCII code of 97. The EncodeCharacter() function therefore needs to “return” a value back to the EncodePhrase() function. Lab 10 – 206 – Course Manual (C Programming) . NOTE: When you implement the EncodeCharacter() function. the value of the character (i. which can in turn modify values in the original arrays. For example. the corresponding ASCII code) is passed to the EncodeCharacter() function. so the memory would be organised as follows: If the EncodeCharacter() function were to change the value stored in the local variable “c”. when the EncodePhrase() function calls the EncodeCharacter() function. but this is a poor solution.EngGen 131 S2 2013 Finally.

Lab 11 – 207 – Course Manual (C Programming) . This lab exercise will give you practice designing tests for your project and provides you with a program that you can use to automatically run your tests on your abcd001_Play() function. you will want to test this using various different GameStates.EngGen 131 S2 2013 EngGen 131 2013 Lab 11 Project and Strings GOALS FOR LAB 11 After successfully completing the compulsory exercises for this lab. int directionOfPlay. the following structure has been defined to represent the state of a game of Uno at a particular point in time: typedef struct { int numberOfPlayers. int allPlayersScores[MAX_PLAYERS]. int yourPosition. When you have written your abcd001_Play() function. Card discardPile[MAX_CARDS]. int allPlayersCardsLeft[MAX_PLAYERS]. int allPlayersColoursCalled[MAX_PLAYERS]. Card yourCards[MAX_CARDS]. } GameState. int lastColourCalled. Your main task in the project is to define a function called abcd001_Play() which is passed a pointer to one of these GameState structures and which returns the index into the yourCards array that represents the card that you want play (of course. int numberOfDiscards. int yourNumberOfCards. change abcd001 to your UPI!). you will: • • have thought about an approach for testing the code you write for your project gain further practice working with strings and functions that accept string inputs GameState In the Project.

EXAMPLE 1: Top card: Your hand: List ALL index positions in “Your hand” for Example 1 that represent valid cards that could be played: EXAMPLE 2: Top card: Your hand: List ALL index positions in “Your hand” for Example 2 that represent valid cards that could be played: EXAMPLE 3: Top card: Your hand: List ALL index positions in “Your hand” for Example 3 that represent valid cards that could be played: – 208 – Lab 11 Course Manual (C Programming) .EngGen 131 S2 2013 Let’s start with three examples. the player’s hand consists of exactly 4 cards. For each example. In each case. and the top card on the discard pile is shown. write down ALL of the index positions in the player’s hand representing cards that could validly be played given the top card shown.

In particular. look at the last line of each test and you should be able to make sense of those numbers based on the values you just wrote down on the previous page.EngGen 131 S2 2013 One approach we can use for testing our abcd001_Play() function involves a “test file” that consists of a sequence of possible game states. Each game state in the file begins with an asterisk. * number of players direction of play 4 last colour called 7 50000 your position at the 0 table 4 0 10000 1 0 20000 2 0 30000 3 0 40000 4 the number of cards 1 in your hand 2 30000 0 4 4 4 4 your actual cards 50000 50000 50000 50000 0 0 0 0 the number of cards 1 2 on the discard pile the number of cards the cards in the each player has left discard pile * 4 the last colour called the current scores of by each player each player 7 50000 0 4 0 10000 1 0 30000 2 0 40000 3 0 30000 4 1 2 30000 0 all valid index 4 4 4 4 positions for your 50000 50000 50000 50000 hand 0 0 0 0 2 1 3 * 4 7 50000 0 4 0 10000 1 0 20000 2 0 40000 3 0 20000 4 1 2 30000 0 4 4 4 4 50000 50000 50000 50000 0 0 0 0 0 Lab 11 the number of valid index positions for cards you can play in your hand – 209 – Course Manual (C Programming) . Take a look at the example test file below (containing three separate tests) and make sure you understand what all the numbers mean. Each game state concludes with a list of all valid values that could be returned by the abcd001_Play() function for the corresponding game state. This is followed by all of the information for a GameState structure. The very last line of each test lists all valid index positions that could be returned when the abcd001_Play() function is called with the given game structure (the first value on this line is the total number of these valid positions that exist).

EngGen 131 S2 2013 EXERCISE ONE: An example test file is shown below. but they are incomplete – they are each missing the last line that displays the total number of valid index positions in the player’s hand. Three example test cases are defined in the file. * 4 7 50000 0 6 0 30000 1 0 20000 2 0 40000 3 0 20000 4 1 30000 0 2 20000 0 3 2 10000 0 3 10000 0 0 20000 6 4 4 4 4 50000 50000 50000 50000 0 0 0 0 * 4 7 20000 0 4 0 10000 1 2 40000 0 0 30000 3 0 40000 4 2 0 40000 8 5 50000 0 4 4 4 4 50000 50000 50000 50000 0 0 0 0 * 4 7 50000 0 5 0 10000 1 0 30000 2 0 20000 3 4 50000 0 1 10000 0 5 2 30000 0 0 30000 6 0 10000 6 1 10000 0 1 40000 0 4 4 4 4 50000 50000 50000 50000 0 0 0 0 Lab 11 – 210 – Course Manual (C Programming) . Complete each of these test cases by filling in the correct values that should appear in the last line and show your solution to the lab tutor. and the index positions themselves.

we can refer to an individual word by including the first index after the array variable (which essentially gives us access to one row of the array). printf("%s\n". remembering we have to leave space for the null terminating character!). For example. "orange"). "plum"). let’s declare a 2D array of type char that consists of 5 rows and 10 columns: char words[5][10]..EngGen 131 S2 2013 Storing a collection of strings We know that a string in C is represented as a 1-dimensional array of characters. strcpy(words[1]. We can visualise the results of these strcpy() function calls as: And we can display individual words in the list using appropriate printf() function calls. What if we want to store a list of strings? The solution is to use a 2-dimensional array – where each row of the array will store a different word. With this 2-dimensional array. "grape"). So. The second word in the second row.. strcpy(words[3]. and so on. For example: printf("%s\n". how do we actually get the words in there? There is a function called strcpy() that we can use to copy strings into arbitrary rows of the array. For example. printf("%s\n". In our code. words[1]). The first word will be stored in the first row of the array. we can store up to 5 words in our list (where each word is no longer than 9 characters. would produce the following output: grape orange plum Lab 11 – 211 – Course Manual (C Programming) . words[0]). words[3]). we can use it to copy string literals into some of the rows of the array: strcpy(words[0].

This has no effect though. because the null terminating character for the word “lemon” defines the end of the word.EngGen 131 S2 2013 We can also store user input using scanf(). This will store the users input in the third row (the row with index 2) of the 2-dimensional array. the old null terminating character for the word “orange” would still appear in the array. Now. For example. consider the following input statement: scanf("%s". words[1]). For example. These words are stored at row positions 1 and 2 respectively. – 212 – Lab 11 Course Manual (C Programming) . words[2]). We would begin by copying one of the words into the temporary storage location: strcpy(temp. The next step is to copy the word from row 2 to row 1: strcpy(words[1]. words[2]). This has copied the word “lemon” over the top of the word “orange”. then the array will now contain the values as follows: Swapping two strings in the list How would we swap two strings in the list? To do so. no other values in the array change. This has copied the word “orange” into the temporary storage location. we would need some temporary storage (as we always do when we swap the values stored in two variables). Note that once the null terminating character for the word “lemon” is copied across. if the user enters the string “lemon”. Because in this case the word “orange” is one character longer than the word “lemon”. Let’s declare the temporary storage (this will be a 1dimensional array because it will be used as temporary storage for a single word) and then visualise it along with the 2-dimensional array that stores our words: char temp[10]. let’s say we want to swap the words “orange” and “lemon” in our list.

printf("%d\n". strcmp("ghi". "def")). we just need to copy the word from the temporary storage location to row 2 of the array: strcpy(words[2]. For example.EngGen 131 S2 2013 Finally. And that’s it! We have now swapped the words at these two positions. temp). printf("%d\n". Lab 11 – 213 – Course Manual (C Programming) . or we would like to know which string would appear first in standard alphabetical order. strcmp("abc". strcmp("def". and a positive number (typically 1) when the first string appears alphabetically after the second string. a common operation we want to perform is comparison. Comparing strings When working with strings. we would like to know whether two strings are equal. For example. To compare two strings. consider the following comparisons: printf("%d\n". we can use a function called strcmp(). This function returns an integer value. "ghi")). The output produced by this program is as follows: -1 1 0 As you can see. when the two strings are the same. "abc")). the strcmp() function evaluates to 0. It evaluates to a negative number (typically -1) when the first string appears alphabetically before the second string.

we can sort integers: or strings: or any list of data values where two values can be compared. One simple algorithm (known as “bubble sort”) for sorting a list of values involves an operation called “Bubble”. It is very easy to describe sorting informally: the input is a list of data items. then compare element 1 and element 2. and the output is a reordering of the list such that all elements are in non-decreasing order (the ordering might be lexicographical or numerical. Some algorithms (like. then compare element 2 and element 3. Naturally. If you perform the Bubble operation again. initially compare element 0 and element 1. For example. the list of elements will be sorted correctly. Lab 11 – 214 – Course Manual (C Programming) . at the end of the operation the largest value in the array will be in the last position. depending on the type of elements being sorted). search algorithms) are inefficient when the data to be searched is unsorted but are extremely efficient on sorted data. Sorting is a widely researched topic and many different algorithms for sorting data have been proposed and studied. and so on) o if the pair of elements being examined is out of order then swap them If you carry out the Bubble operation on an unsorted array. for example.EngGen 131 S2 2013 Sorting Sorting data is one of the most fundamental operations in computing. then you are guaranteed that the second largest element will be in the second to last position. • Bubble: o examine each pair of elements in the list (for example. if you perform the Bubble operation enough times.

COMPULSORY LAB TASKS END HERE Lab 11 – 215 – Course Manual (C Programming) .h> at the top of your source file. write some small test programs to ensure you understand how the strcmp() and strcpy() functions work. make sure that you test the following input lists: aaa bbb ccc ddd eee eee ddd ccc bbb aaa eee aaa bbb ccc ddd bbb ccc ddd eee aaa aaaaa aaaa aaa aa a For this exercise you should define three functions: Sort(). If you need to. Bubble() and Swap(). A constant called NUM_WORDS should be defined at the top of your program to determine how many words will be in the list. The Sort() and Bubble() functions should be passed an array.EngGen 131 S2 2013 EXERCISE TWO: Read the previous description that explains how to store a list or collection of strings. Write a program that reads a list of words from the user and then displays those words in alphabetical order. Note that in order to use the string-related functions in C. with different values for NUM_WORDS. An example of the output of this program is shown below (user input is in bold): > ex2 Please enter 5 words: Enter word 0: cherry Enter word 1: banana Enter word 2: apple Enter word 3: kiwifruit Enter word 4: grape Sorted: Word 0 = Word 1 = Word 2 = Word 3 = Word 4 = apple banana cherry grape kiwifruit Test your program thoroughly. you must include: #include <string. and the Swap() function should be passed an array and the indices of the two items that are to be swapped. how to swap two strings in the list. and how to compare two string lexicographically. At the very least.

The “word” will be a completion of the “pattern” if all the non-hypen characters match. EXERCISE THREE: For this exercise. For example.EngGen 131 S2 2013 Crossword helper Sometimes when struggling to solve a crossword it would be nice to have some way of viewing all of the possible words that could fit in a particular place given the partial clues that have already been solved. you need to complete the function: int WordMatchesPattern(char *word. and a function to check if a word matches a given pattern. In this case. which reads all of the words from a provided text file of English words. if you already had the first two and the last two characters of a 6-letter word: ab--rd it might be useful to be able to produce a list of all possible words that could fit. The “pattern” string is a partial word where some of the characters have been replaced with hyphens (-). is already provided for you. there are just two: aboard absurd We can solve this problem using a word list. Lab 11 – 216 – Course Manual (C Programming) . char *pattern) which takes two strings as input. The program prompts the user for a pattern. For example: word: “apple” and pattern “a-p-e” is a match word: “apple” and pattern “a---e” is a match word: “apple” and pattern “--ple” is a match whereas word: “apple” and pattern “app--e” is not a match word: “apple” and pattern “---p-” is not a match word: “apple” and pattern “--l-e” is not a match The main() function. and returns true only if the string “word” is a possible completion of the string “pattern”. and should display all of the words that match the pattern along with a count of the total number of matching words.

scanf("%s". pattern). } printf("Enter pattern: ").EngGen 131 S2 2013 The main() function that is provided to you is given below: int main(void) { FILE *input. Enter pattern: p-uplug plum plus pouf pour pout 6 matches Enter pattern: apple apple 1 matches Enter pattern: a-b-c-d 0 matches Enter pattern: --------e-------compartmentalised compartmentalises compartmentalized compartmentalizes counterrevolution environmentalists intergovernmental plenipotentiaries 8 matches Lab 11 – 217 – Course Manual (C Programming) . } } printf("\n%d matches". word) != EOF) { if (WordMatchesPattern(word. input = fopen("wordlist. count). "r"). int count. char pattern[100]. } Below are some examples of how the program should behave if you correctly define the WordMatchesPattern() function (user input is in bold). count = 0. "%s". while (fscanf(input. return 0. exit(EXIT_FAILURE)."). if(input == NULL) { printf("Could not open file. char word[100].txt". word). count++. pattern)) { printf("%s\n".

You should define the IsPartialAnagram() function: int IsPartialAnagram(char *word1. is given below: Your word: apple ale ape apple lap leap pa pal pale pap pea peal pep plea There are 13 partial anagrams of apple To get started. one per line. The main() function has already been provided for you. You will also find the source file ex3. Here you will find a word list called “wordlist. It prompts the user to enter a word. This is a comprehensive list of English words.txt”.EngGen 131 S2 2013 EXERCISE FOUR: A partial anagram is a word that consists of a subset of the letters of another word.zip file. char *word2) Lab 11 – 218 – Course Manual (C Programming) . This will provide the set of candidate words that you can test to see if they are partial anagrams of the word the user provides as input. have a look in the Lab11Resources. it is also a full anagram) “off” is not a partial anagram of “food” (the letter “f” may only appear once) In this exercise.net/12dicts-readme-r5. An example of the output your program should produce. For example: “of” is a partial anagram of “food” “restful” is a partial anagram of “fluster” (in fact. taken from the “12dicts” repository (http://wordlist. assuming the user types the word “apple” as input.sourceforge. reads all of the words from the word list.c.html). you will write a program that displays all of the partial anagrams for a word typed in by the user. and calls the IsPartialAnagram() function to check for partial anagrams.

and the user supplied word as the second parameter. Each time it is called. exit(EXIT_FAILURE). char userword[100]. } } printf("\nThere are %d partial anagrams of %s"."). scanf("%s". count++. and returns true if the first word is a partial anagram of the second word. "r"). it is passed the next word from the word list as the first parameter. if(input == NULL) { printf("Could not open file. The source code that has been provided to you is below: #define _CRT_SECURE_NO_WARNINGS #include <stdio. userword). char *word2). return 0. count. userword)) { printf("%s\n". userword). "%s". – 219 – Lab 11 Course Manual (C Programming) . word) != EOF) { if (IsPartialAnagram(word. userword). } printf("Your word: ".h> #include <stdlib.EngGen 131 S2 2013 This function takes two strings as parameters. while (fscanf(input. input = fopen("wordlist. int count. } You can see that the IsPartialAnagram() function is called in a loop. char word[100]. count = 0.h> #include <string. word). int main(void) { FILE *input.txt".h> int IsPartialAnagram(char *word1.

How many partial anagrams are there for the word “programming”? Lab 11 – 220 – Course Manual (C Programming) . how can you implement this function? One way to implement the IsPartialAnagram() function is to use an array that records character counts. In the example above. If all of the resulting character counts are positive or zero.EngGen 131 S2 2013 So. Next. Each character in the user’s word can be examined. each character in the word being tested can be examined. consider that the user enters the word “faded” and that you are testing to see whether the word “deaf” (from the word list) is a partial anagram. You will need to decide how many elements this array should have. and the corresponding character count can be decremented. and the corresponding character count can be incremented. only the relevant part of the character count array is shown. the IsPartialAnagram() function would return true. then the word being tested is a partial anagram. For example. and how it should be declared. and the word “deaf” would be printed. The diagram below illustrates this process: Note.

} } Lab 12 – 221 – Course Manual (C Programming) . There are certain problems for which the solution can be defined in terms of solutions to smaller. The recursive case is quite simple. identical problems. If start and end are the same. A trivial example is printing all of the integers between a start value and an end value. The base case is also simple. } else { printf("%d ". start). it is often straightforward to write a recursive function to solve them. To print all the values between start and end. you will: • • be able to implement simple recursive algorithms be able to review your classmates solutions to the project. and provide feedback to them Recursion A recursive function is one which calls itself.EngGen 131 S2 2013 EngGen 131 2013 Lab 12 Recursion and Project Reviews GOALS FOR LAB 12 After successfully completing the compulsory exercises for this lab. int end) { if (start == end) { printf("%d ". A recursive function for printing the values between start and end could be defined as follows: void PrintValuesBetween(int start. For these kinds of problems. we can just print start. start). end). PrintValuesBetween(start + 1. and then recursively print all the values between start+1 and end. then we just print that value.

Lab 12 – 222 – Course Manual (C Programming) . there is only one way to pick zero things out of n: pick nothing. all distinct. then ⎜ ⎜m⎟ ⎟=⎜ ⎜ ⎟+⎜ ⎜ ⎟ ⎝ ⎠ ⎝ m ⎠ ⎝ m − 1⎠ ⎛n ⎞ Directly from this definition. n. int m) { if ((m == 0) || (m == n)) { return 1. } } Type this function definition into a program and call it with a variety of input values.EngGen 131 S2 2013 Combinations The number of combinations of m things chosen out of n is written: ⎛n ⎞ ⎜ ⎜ m⎟ ⎟ ⎝ ⎠ and is pronounced "n choose m". %d)\n". For example. ⎝ ⎠ ⎛n⎞ ⎜ ⎜n⎟ ⎟ = 1. there are 52 cards in a deck. That is. ⎝ ⎠ Recursive case ⎛ n ⎞ ⎛ n − 1⎞ ⎛ n − 1 ⎞ ⎟ ⎟ If 0 < m < n. } else { return Choose(n-1. m) + Choose(n-1. we can define a function to calculate ⎜ ⎜ m⎟ ⎟ as follows: ⎝ ⎠ int Choose(int n. The number of possible poker hands is the number of different ways we can pick five cards from the deck: ⎛ 52 ⎞ ⎜ ⎜5⎟ ⎟ ⎝ ⎠ ⎛n ⎞ There is an elegant recursive definition of ⎜ ⎜ m⎟ ⎟ as follows: ⎝ ⎠ Base cases ⎛n⎞ ⎜ ⎜0⎟ ⎟ = 1. and you can see exactly what function calls are made to calculate “n choose m” recursively. m-1). For example. you should be able to use this function to verify that: 6 choose 2 is 15 and 52 choose 5 is 2598960 Add the following printf() function call as the very first statement in your function definition: printf("Choose(%d. That is. m). the only way to pick n things out of n is to pick them all.

should print: 654321 The following diagram illustrates how we can solve this problem recursively: How should the PrintReverse() function be defined? void PrintReverse(int n) { } Base case: A good base case for this problem will be when the input value. is less than 10 (i. n. which can then be the input to the recursive function call. the digit can just be printed Recursive case: Step 1: the expression n % 10 gives you the right-most digit which can just be printed Step 2: the expression n / 10 gives you the number excluding the rightmost digit. In this case. the function call: PrintReverse(123456).EngGen 131 S2 2013 EXERCISE ONE: For this exercise you need to define a recursive function called PrintReverse() which should print an integer where the digits appear in reverse order. For example. Lab 12 – 223 – Course Manual (C Programming) .e. a single digit).

numbers that are four times an odd number have two factors of 2 and so on. For example. the function call: FactorsOfTwo(40) should return 3 Obviously. Write a recursive function called FactorsOfTwo() which takes an integer as input and returns the number of factors of 2 that the number has. will be one more than the number of factors of 2 that n/2 has COMPULSORY LAB TASKS END HERE Lab 12 – 224 – Course Manual (C Programming) . Another way of looking at this is that an odd number has no factors of 2. The prime factorisation of a positive integer is the list of its prime factors expressed as a product. are the prime numbers that divide n exactly without leaving a remainder.EngGen 131 S2 2013 EXERCISE TWO: The prime factors of a positive integer. you must not use any loops! How should the FactorsOfTwo() function be defined? int FactorsOfTwo(int n) { } Base case: If the input number is odd. For example. the prime factorisation of 288 is: 2x2x2x2x2x3x3 To find out how many times 2 appears in the prime factorisation of a number. because the function is recursive. we can repeatedly divide the number by 2 until the result is an odd number. we can just return 0 (an odd number has no factors of 2) Recursive case: the number of factors of 2 that n has. n. the number 40 has 3 factors of 2. numbers that are twice an odd number have one factor of 2. For example.

move disc n clockwise as required 3) finally. Each move will name a particular disc (the smallest disc is 1. There is a simple algorithm for solving this puzzle. int clockwise) n Here. the largest is n) and a direction (clockwise or anti-clockwise). which requires 2 -1 moves for n discs. move n-1 discs anti-clockwise Write a program that solves the “Towers of Hanoi” puzzle for a given n (where n is the number of discs that the user enters) by printing out a list of moves for the discs. The following two rules must be obeyed: 1) 2) only one disc may be moved at a time a larger disc must never be placed on top of a smaller disc Imagine looking down at the puzzle from above. Starting with all of the discs on a single rod. n is the size of the problem and clockwise is either true or false depending on the direction the disc should be moved. This algorithm can be defined recursively as follows: To move n discs clockwise: 1) first move n-1 discs anti-clockwise (this would leave disc n with no discs on top of it) 2) next. of different sizes.EngGen 131 S2 2013 EXERCISE THREE: The “Towers of Hanoi” is a puzzle consisting of three rods and a number of discs. the goal of the puzzle it to shift the entire stack of discs to a different rod. Lab 12 – 225 – Course Manual (C Programming) . which fit onto the rods. Discs can either be moved clockwise or anticlockwise. in increasing order of disc diameter. This program will make use of one important function with the following prototype: void Solve(int n.

EngGen 131 S2 2013 Consider some correct outputs for this program (user input is in bold): Please enter the number of discs: 1 1 clockwise Please enter the number of discs: 2 1 anti-clockwise 2 clockwise 1 anti-clockwise Please enter the number of discs: 3 1 clockwise 2 anti-clockwise 1 clockwise 3 clockwise 1 clockwise 2 anti-clockwise 1 clockwise Please enter the number of discs: 4 1 anti-clockwise 2 clockwise 1 anti-clockwise 3 anti-clockwise 1 anti-clockwise 2 clockwise 1 anti-clockwise 4 clockwise 1 anti-clockwise 2 clockwise 1 anti-clockwise 3 anti-clockwise 1 anti-clockwise 2 clockwise 1 anti-clockwise For what values of n does it take your program too long to solve? This is an example of exponential growth – the list of solutions grows extremely quickly as the value of n increases (it basically doubles every time n increases by 1). Lab 12 – 226 – Course Manual (C Programming) .

Friday 25th October. If you are not able to complete your reviews during the lab session. _______________________________________________ Lab 12 – 227 – Course Manual (C Programming) . In this lab. you will have access to a small number of projects developed by your peers.EngGen 131 S2 2013 Reviewing with Aropä The final project has now been handed in. Feel free to comment on the style of the code that you see and make suggestions for improvement. you may complete them outside of your scheduled lab time. and you are to review each of the projects and provide constructive feedback. up until the end of the week – the deadline is 10:00pm.

EngGen 131 S2 2013 Lab 12 – 228 – Course Manual (C Programming) .