[epsf,html,12pt,a4]article
C
at_work.gif (Under Construction...)
[1]#1
[2]#1#2
[1]"#1"
---
htmlonly
[1]"#1"
-
htmlonly
http://www.eeng.dcu.ie/7Emcmullin/swe1/swe1root
../../swe1root/swe1root/labels.pl
Software Engineering 1: Laboratory Exercises
Barry McMullin
Last Modified: 30th April 1996
Note that this complete document is available in
LaTexswe1labs.tex and plain
ASCIIswe1labs.txt forms, to allow downloading and
offline browsing.
Introduction
This document is one component of the hypermedia documentation for the
course Software Engineering 1
../swe1root/swe1root.html. It
presents detailed instructions and background information for the
laboratory sessions.
In general, the notes for particular lab exercises will be added
to this document on an ongoing basis during the academic year,
with each new exercise being made available a few days before
the first section of the class is due to do it.
General Comments on Lab Work
The CAE laboratory itself should be used both for the scheduled
laboratory exercises, and also for private study: the primary
way of studying software engineering is to do it! The laboratory
exercises are crucial to this course: you should learn more from
the time you spend in the laboratory than from lectures and
tutorials combined.
Each student attends one three-hour scheduled lab session every
two weeks. You should aim to spend at least three
further hours of private study time in the lab over the same
period. The scheduled lab sessions are deliberately structured
so that each student has a separate PC; however, for private
study you may find it easier to get at a machine, and also more
effective, to work together with one or two othersprovided
that you spend time discussing what is happening, and taking
turns at actually operating the PC.
For the first lab session you are required to bring along a new,
unused, copybook or notebook to be used as your lab logbook.
However, in contrast to most other laboratory subject, this
logbook will not be used to hold formal lab reports.
Instead, you will maintain the logbook just with your own
personal notes; but these personal notes will serve as the basis
for writing separate formal reports, which will actually
be submitted (and archived) electronically. This
will be explained in more detail
during the lab sessions.
You should consult the
Software Engineering 1: Laboratory Report Guidelines
http://www.eeng.dcu.ie/7Emcmullin/swe1/rptfmt/rptfmt.html
for advice on how to prepare lab reports, and the criteria which will be
used in marking them.
Session 1: Week 1/2
This first several lab sessions are concerned simply with introducing
general purpose
hardware and software tools which will be used in the remainder
of the course. Given that you are reading these notes, you have
successfully completed the first phase of the exercise!
Stop at this point and read back over what you have written in
your logbook. Make sure you have a reasonably complete record
of what you have done so far (so that, if necessary, you could
redo it without further guidance).
In particular you should have some record of:
The rules
http://www.eeng.dcu.ie/eenghome/caerule/caerule.html
and timetable
http://www.eeng.dcu.ie/eenghome/caetime/caetime.html
applying to users of the
CAE laboratory.
The component physical parts of the PCstheir names and
functions.
The procedure for booting up a PC. In particular you should have
carefully read the notice
http://www.eeng.dcu.ie/eenghome/aup.txt
regarding acceptable use
of the School's computer facilities.
How to format a new diskette from the MS-DOS
command level.
How to check the integrity of a diskette from the
MS-DOS command level.
How to initialise a diskette as a Netscape
Configuration diskette from the MS-DOS command level.
How to start up the MS-Windows environment.
How to use the MS-Windows online Help
facility, including searching and using hypertext links.
How to start up the MS-Windows introductory
tutorial. How to move, minimize, maximize, and otherwise resize
windows. How to launch applications.
How to start Netscape, and use
hypermedia links. How does navigating with Netscape differ
from using MS-Windows Help?
If your logbook fails to mention any of these things, take time
now to make some additional notes.
At this stage you have created and are using
a Netscape Configuration Diskette.
You should always insert this diskette before starting up a
Netscape session. IMPORTANT: Do not remove it again until your
Netscape session is over, and the diskette light has gone
off. This configuration diskette will hold personal
information about your use of Netscape. For example, you
can record a bookmark file, identifying nodes that you have
visited, making it easy to revisit them.
For now, we want to configure Netscape to know your name and
email addressso that, if you originate email from within
Netscape, you will automatically be identified as the
author.You will not be able to receive email for
the time being. That will be dealt with in subsequent lab
sessions. Follow these steps, within Netscape:
Drop down the
Options menu.
Select Preferences.
Select the
Mail and News tab.
Fill in the fields labelled Your
Name and Your Email. Your email address will be something
like astudent@ugmail.eeng.dcu.ie, but instead of
astudent you have a username consisting of your first
initial followed by your surname, up to a maximum of 8
characters in total. Do not use any spaces or punctuation, and
keep it all in lower case.
Select OK.
Now, find out (using Netscape) as much as you can about
the Electronic Mailing List facility operated by the School of
Electronic Engineering. In particular, read the information about the
SOFTENG1-95
http://www.eeng.dcu.ie/7Emajordom/softeng1-95.info.html
list. Check out the archives
http://www.eeng.dcu.ie/7Emajordom/hmarchives.
Finally: compose a short message (one
paragraph) which summarises your opinion of this course
(Software Engineering 1) so far. Mail this message to
SOFTENG1-95@mjmail.eeng.dcu.ie
mailto:softeng1-95@mjmail.eeng.dcu.ie.If
you enter this address manually, omit the quotation marks.
But, in this particular case, you can just click on
the address and Netscape should bring up a mail
composition window, already addressed to the correct address, and with
your name and return address automatically recorded.
Check the
archives
http://www.eeng.dcu.ie/7Emajordom/hmarchives
again to see that your message has been archived
successfully.
Note that, due
to a defect in Netscape you may have to clear the caches,
before your message will become visible in the index. To do this, drop down
the Options menu, and select Preferences again.
Select the Cache and Network tab. Click on Clear
Memory Cache Now. You will be asked to verify thisclick on
OK. Similarly, clear the disk cache. Click on OK
again to exit the Preferences dialog. The archive index
will be automatically reloaded and is now guaranteed to be up to
date. If your message is still not showing up, then something
has gone wrong.
If your message is now visiblecongratulations:
you have successfully
completed the first lab exercise!And your
message is nowimmediately -
accessible to the entire world wide Internet
community!
Session 2: Week 3/4/5
Background
This session introduces the tools you need to create and
manipulate text files on the PC. Text files are just
textual documents. You might compose a letter or message
and save it on diskette in a text file. Subsequently you
might edit it to correct mistakes or add more information.
You might copy it from one diskette to another for backup
purposes (in case one diskette gets damaged or lost). You might
print it out or email it. You might delete it off your
diskette when you no longer have any use for it.
We will be dealing with very basic so-called ASCII
text documents. ASCII (American Standard Code for Information
Interchange) is a standardised way of expressing text in
electronic (binary) form. It essentially specifies a way of
encoding each possible character as an 8-digit binary number, or
byte. ASCII supports the lower and upper case alphabetic
characters (a to z and A to Z),
the digit characters 0 to 9, a variety of punctuation
characters such as ; : . ? ( ) [ ] etc., and finally a collection
of special characters such as + * etc.
ASCII provides roughly the same capability for representing text
as used to be available with an old fashioned typewriter.
ASCII does not support more advanced or complicated kinds
of text such as accented characters, mathematical symbols,
underlining, bolding, varying sized characters, etc.
As such, ASCII might be regarded as pretty primitive.
The great advantage of ASCII is that it really is a
standard. ASCII encoded text files can be read and printed
on virtually any computer system, and can be successfully
transmitted through any email system. ASCII is a sort of
Lowest Common Denominator of text file formats.
We will use ASCII files in this course for preparing lab
reports, and for preparing program files (in the programming
language). programs will,
in effect, be ASCII files, and will be manipulated with
the same tools as we manipulate any other ASCII files.
Managing Text: Using PFE
We will create and manipulate text files using an application
called the Programmer's File Editor or PFE for
short. PFE will allow you to enter text for a new file, save
it on your diskette, edit it again, save it again, print it,
and so on.
You will find PFE in the Tools group in Program
Manager. Start it up now. Once it is started up, you might
want to move and resize both its window and the Netscape window so
that they do not overlap too much, and you can see both easily.
Explore and experiment with the use of PFE for a while.
Have a look at the various menus. Read through the online help.
Try out the buttons on the button bar to see what (if any)
effect they have.
Now carry out the following exercise:
Create a new text editing window.Select New on the
File menu.
Type up a couple of paragraphs of text on any subject of
your choice.
Save the file on your diskette, under the
name TESTING.TXT.Select Save on the
File menu. This will bring up a file selection dialog. On
this you need to specify a disk driveA: for the
disketteand the file name.
Exit from PFE.
Start up PFE afresh.
Create a text editing window for the file
TESTING.TXT.Select Open on the File
menu. This will bring up a file selection dialog again.
Make some modifications to the file. In particular, insert a
line at the top with your own name, and today's date.This will
serve to identify your particular file when you come to print it out in
the next step.
Save the file again.
Note carefully that, while you are editing
the file within PFE, this is only changing a copy of the file
loaded into main memory. This is a kind of semiconductor memory, which is
completely volatilethe information will be lost is there is a
power failure or the machine is otherwise reset. The copy of the file
on your diskette is not being modified. To update the diskette
copy, you must save the file from within PFE. It is very
important to get into the habit of saving early and often.
Print your file out.Select Print on the
File menu. As everybody will be trying to print at more or
less the same time, you needn't wait until it is physically printed,
but continue on with the exercise.
Exit from PFE again.
At this point you should be satisfied that, using PFE you
know how to create, save, re-edit, and print, ASCII text files.
Managing Files: Using File Manager
PFE is adequate for basic creation and manipulation of
text files. However, for more general management of disks and
filesformatting diskettes,
organising files into directories, copying files, deleting
files etc.you need a different tool, File Manager.
File Manager has the further advantage that it can operate
on all kinds of filesnot just text files. This isn't
much of an issue in this course yet, but will become one in the
near future.
You will find File Manager in the Main group in Program
Manager. Start it up now. Once it is started up, you might
want to move and resize both its window and the Netscape window so
that they do not overlap too much, and you can see both easily.
Explore and experiment with the use of File Manager for a while.
Have a look at the various menus. Read through the online help -
particularly the section called What is File Manager?
Now carry out the following exercise:
Create a new directory at the topmost
level on disk drive D: with any name you wish (for
example, your own forename or surname etc.).If you manage this
successfully, you should be able to see the new directory listed by
File Managerfor example as D:MYDIR or
whatever.
Try to establish what, if any restrictions apply to naming
a directoryeither by experiment or by reading the help.
Delete the directory again.
Create a directory at the topmost level on your diskette
(drive A:) with the name TMP.
Move the file TESTING.TXT from the topmost level of
your diskette into the directory TMP.
Create a new directory on disk drive D: called
MISC. Copy the file TESTING.TXT from directory
TMP on your diskette into the MISC
directory.To achieve
this you need two (sub-)windows open in File Managerone
showing the contents of
A:TMP, the other showing
D:MISC. Then just drag the file
TESTING.TXT across.
Note how, when you drag a file,
File Manager moves the file if both the
starting and ending point are on the same disk, but copies
the file when they are on different disks.
Delete the whole directory MISC from drive D:
(including the file TESTING.TXT which it contains).
Exit from File Manager.
At this point you should be satisfied that you know how to use
File Manager to examine what directories and files are on a
disk, to create and delete directories, and to move, copy, and
delete files.
Managing email: Using Eudora Light
You have already seen, in session 1, how you can use
Netscape to send email messages to one of the mailing
lists archived on the School web site, and how to read these
messages. However, Netscape does not support accessing or
receiving
personal email.
To receive and manage email, in a general way, we will use the
Eudora Light application. Eudora allows email to be
prepared and sent; it allows you to download email from your
personal email-box on the School server; and it allows you to
manage and organise you own archives of email messages you have
received.
Like Netscape the effective use of Eudora relies on
using a configuration diskette where Eudora will
store specific information relating to your email account, and
will also store your received email messages. You can use a
single diskette as both the Netscape and Eudora
configuration diskette.
A notice, detailing how to set up and use a Eudora
diskette was posted to the Local-Notices mailing list
within the past few weeks. Find that message now in the web
archives
http://www.eeng.dcu.ie/7Emajordom/hmarchives.
In fact, look for all messages referring to Eudora Light
(also known as Freeware Eudora). Read these messages
carefully.
You will find Eudora in the Internet group in Program
Manager. Start it up now, and configure it, as described in
the message on Local-Notices.
Explore and experiment with the use of Eudora for a while.
Have a look at the various menus. Start up the viewer for the
online manual (also in the Internet program group). Browse
through it (there will not be time to read it in detail).
The demonstrator will tell you the assigned password for your
account. Verify that Eudora can check for mail received
into your mailbox. Try sending yourself email. Try exchanging
email messages with the person beside you. Send a message with
the following text:
to the address majordomo@mjmail.eeng.dcu.ie. See what
messages you receive back.
You must now change your account password to one of your
own choosing. Choosing a good password is not easyit must
be both hard for anyone (or any machine!) to guess, yet be
easy to remember. Briefly, your password should be 8 characters
long, use a mix of both upper and lower case letters (which are
considered to be distinct in passwords), some digits, and some
special or punctuation characters. You may not use the
space character in a password. Read through
this online advice on choosing
Good Passwords
http://www.alw.nih.gov/Security/Docs/passwd.html.
When you have made up a satisfactory new password, which you are
sure you will be able to remember, use the Change Password
option on the Special menu in Eudora to actually
change the password. Note that this may fail for a variety
of reasonsfor example, if you type in the old password
wrongly, or the new password is too short, or does not have a
mix of both upper and lower case, or does not have any non
alphabetics. If the password changing fails, the old password
will remain in effect, so just go through the procedure again.
When you have succeeded in changing your password, check again
that your email access is still OK by sending yourself another
test message and seeing that you can receive it.
You should change your password again at least once every term
or soand immediately if you have any reason to suspect
that it may have been compromised.
Finally, using Eudora, compose a short message (one
paragraph), summarising your experience of this lab exercise,
and mail it to SOFTENG1-95@mjmail.eeng.dcu.ie .
That completes the exercise; you can now shut down all
applications, take out your diskette, exit Windows, and power
down the PC.
Session 3: Week 6/7: Introducing C
Preparation
From this session onward it is essential that you study the notes
for the session carefully in advance. The lab exercises are
getting increasingly extensive and demanding. You will not be
able to study the notes for first time and carry out the required
exercises within three hours.
Background
In this session you will attempt, for the first time, to develop
an actual program. You will be using the language.
This is a so-called high-level language, so you will need to
translate the program into the low-level or machine language
that the Central Processing Unit (CPU) can actually directly execute.
You translate the program using a tool called a compiler.
There are a wide variety of compilers available for PCs, each with
their own particular strengths and weaknesses. We will be using
DJGPP
http://www.delorie.com/djgpp which is a
version of the GNU C Compiler or gcc for short. This is
very widely used both on PCs and Unix platforms. It has the further
advantage that it is free!
, and other languages closely related to it, are the de facto
industry standard programming languages for most general purpose
applications. is a very sophisticated language in certain ways.
This makes it a powerful programming tool for the experienced software
engineer. It also makes it a very dangerous and difficult tool for
beginners.
Therefore, in the first instance, you will be insulated from the full
complexities of the language by a specially developed device called
safe-c. This is, in effect, a package of pre-written building
blocks (or functions as they are called in ), together with
a few other ancillary elements. For the time being, the distinction
between safe-c and proper will not be apparent. But later
on in the course, we will begin to uncover exactly the role that
safe-c is playing, and separate it from standard .
Finally, this session is also the first to require you to prepare a
formal lab report. Before going any further, please read carefully
through the Laboratory Report
Guidelines
http://www.eeng.dcu.ie/7Emcmullin/swe1/rptfmt/rptfmt.html, paying
particular attention to the marking scheme. This is the format, and
marking scheme, that will be used in the lab exams by which this course
will be assessed. Now is your opportunity to practise writing reports
according to the required format, and doing it in the lab, under the
same conditions as will prevail in the exams. Think of every lab session
from now on as a mock exam. Reports from these mock exams will be
reviewed during lectures, to give an indication of what approximate mark
could be expected for it. You will get the maximum benefit from this if
you practise marking your report, according to the guidelines, yourself.
You must write the report as you go along in the lab session.
Start now, by using File Manager to create a working directory called
softeng1 in the root directory of drive D:. Use PFE
to create a file called report.txt in this directory. Insert into
this the required header text for the report, as specified in the
guidelines. Keep PFE running, with a subwindow open for this
file, throughout the lab session, so that you can add to it as you go
along. Remember to save back to disk every time you add any significant
amount of textotherwise you run the risk of losing this text
completely if, for example, there is a power failure in the lab.
At the end of the session you will be required to finish the
report and submit it by email.
Allow 15 minutes at the end of the session to do this.
Specifically, even if you have not completed the assigned exercises,
stop working on them and submit the report anyway. In the lab exams,
only the report is markedso if the report is not submitted you will
get zero marks!
Note that, because this particular lab session is very straightforward
and is largely concerned with introducing some new tools and procedures
it has relatively little technical content: you should therefore be
easily able to score over 80+ in your report for this session. If you
can't achieve that then it indicates that you are not keeping pace with
the course.
Exercise 1: Hello World! (60)
Here is the minimal Hello World program already discussed in the
lectures:
Use PFE to create a file called hello.c in the directory
D:softeng1 containing the program listed above.
Start up the MS-DOS Prompt application. MS-DOS
Prompt (or DOS
for short) is a command line interpreter. That is, it allows you
to type in textual commands which it then tries to carry out. This is
an alternative style of user interaction, compared to the graphical
style of using the mouse to point and click in order to get things to
happen. This textual type interaction will be more convenient for many
of the interactions involved in developing programs.
On some PCs in the CAE lab DOS is
configured to run full-screen. This means you can no longer
see the windows for other applications such as Netscape
and PFE. This is quite inconvenient. If this happens,
press Alt-Enter (i.e. hold down the Alt key and
press Enter). This will make DOS run in a window
instead.
Under MS-DOS Prompt you will have, at any given time, a default
disk drive and default directory on that drive. This simply means that
if you refer to a file, without explicitly stating what disk drive
or directory it is located in, then DOS will assume it is
on the default drive and in the default directory. The DOS
prompt will indicate the current default drive and directory.
We are going to be working with files on drive D: and in directory
softeng1, so it will be convenient to make these the
defaults.
To change the default drive, simply type in the desired drive letter
followed by a colon, and press Enter. The prompt should change to
reflect the new default. Try changing to drive A: and back to
drive D: now to see this happened.
To change the default directory (on the default drive) use the cd
command (short for Change Directory):
Note the leading backslash character here. This character is used
to separate drive specifiers from directory names, and directory names
from subdirectory or file names etc. In this particular case, the
signals that tmp is in the top-level or root directory of the
current drive. If the were omitted,
DOS would think that
tmp was intended as the name of a sub-directory of the
current directory (whatever that might be).
Experiment with changing the current directory to make sure that you
understand its operation fully. You can only change to directories that
exist. You can, of course, check what directories (and files) exist
using File Manager. Alternatively you can use the dir
command in DOS. You can get help on DOS commands by using the
help command. Its operation is pretty self explanatory.
Experiment with it now.
Note that case is not significant in DOS command, directory, file,
or drive namesso, for example, CD has the same effect as
cd etc.
Make D:softeng1 your current drive and directory. Use
dir to check that the file hello.c is present there. You
can use the command type in DOS to type the contents of a
text file on the screen. Try this now to check that hello.c does
indeed contain what you expect.
Compile your program by giving the command:
scc is part of the safe-c package. It invokes the
compiler in the appropriate way to ensure that the safe-c
components get automatically combined with your program.
The program should compile without any problemsif you have
entered it correctly. But if any problems are encountered try to figure
out what is going wrong and fix them. If you get stuck, seek help from
the demonstrator.
Check (using File Manager or the dir command in DOS)
what files now exist in your directory. There should be a new file
called hello.exe. This is the executable filethe file
containing the binary instruction codes that the CPU can directly
execute. Make a note of the size of this file in your report.
To execute the program under DOS you simply give its name as a
command:
In fact, it is enough to just say hello as the command name -
DOS will automatically search for a file with that name and the
.exe extension.
Check that the file executes as you expected. If it does not, try to
figure out why, and fix it. Again, if you get stuck, ask for help from
the demonstrator.
If all has executed correctly, then congratulationsyou have just
entered, compiled, and tested your first program.
Make a directory called lab3 in the root directory of your
diskette. Copy the file hello.c into this directory. There is no
need to copy the file hello.exe onto your disketteexplain why
in your report.
Exercise 2: Branching out! (40)
Here is the program insult.c introduced in the lectures:
Using this as a basis, or template, develop (plan, code, test, correct)
a program called sport.c which will behave as follows:
Display a suitable welcome/identification message.
Ask the user to type in his or her favourite sport.
If the topic is Tennis, display the message Tennis?
I used to play Cricket!.
If the topic is anything else, display the message
What a silly game! instead.
Finally display some suitable closing message.
Conclusion
That completes the exercise. As previously explained, the formal lab
report, which you have prepared during the session,
must now be submitted by email.
Carry out the following procedure to submit your report.
You need to allow at least the last 15 minutes of the lab session
for this.
Read quickly back through the report, correcting obvious errors,
and possibly adding some brief concluding remarks.
Close the PFE subwindow.
Using File Manager, make a copy of the report file in the
directory lab3 on your diskette. This gives you a permanent copy
of the report as a precaution against it somehow getting lost or
corrupted in the mail system.
Using Eudora, bring up a new message window to prepare to
email the report.
Fill in the To: field as:
Its a good idea to also include yourself as an additional recipient (in
the Cc: field) so that you get positive feedback that the message
successfully went into the mail system.
Fill in the subject of the message as simply Session 3 Report.
To include the report file in the message, drop down the
Message menu and select Attach File. This
will bring up a file selection dialog. Select the file where you have
saved the report
(D:softeng1report.txt).
BEWARE: Eudora has several possible mechanisms for
attaching files to a message, depending on the type of data in the
file (e.g. whether it is simply ASCII text, or some kind of word
processing format or whatever). Only one of them will work correctly
for your lab reports. If you get this wrong in the lab exam, the report
will not be correctly submitted and you will score zero.
The correct mechanism in this particular case is for Eudora to
simply include the text from the file as part of the text of the
message. It will do this if the button on the message window marked
TEXT->DOC is out or deselected. Check this now, and make
sure the button is in the correct state.You may find it
convenient to make this the default for Eudora. Drop down the
Special menu and select Settings. Scroll down through the
categories and select Attachments. Put a cross in the box marked
Put text attachments in body of message. Now, whenever you bring
up a new message window, the TEXT->DOC button will be deselected by
default.
Press Send to send the message.
If you have included yourself as an
additional recipient, then you should receive a copy back.
Wait about 30 seconds and then check this.
This submitted report should be automatically archived on the school Web
site, under the archives for the softeng1-95-reports mailing list.
However, this will only happen after the report has been previewed and
approved by the moderator, which should normally be within a couple of
hours. You should make a point of checking whether your report appears
correctly in the archives in due course. If not, do not submit it
again. First, post a message on the softeng1-95 list, querying
what has happened.
Session 4: Week 8/9: Quiz Time
Introduction
This session is concerned with developing and reinforcing the
basic tools of programming already introduced. The session
does not involve any significant new concepts, but merely
requires that you apply the techniques you have already learned
in slightly more elaborate ways.
You are again required to write a formal lab report, and submit
it by email, in exactly the same format and manner as in session
3. This session also again involves creating, editing and storing
files on your PC (in suitable directories),
and compiling source files to produce
executable files.
If you are unsure of any aspect of doing these things,
please review the
session 3 notessession3
again. The relevant instructions will not
be repeated here.
This session has two exercises. In the first you are give a
program and told what it ought to do. You are then asked to
test whether the program behaves as specified; and, if not, to
correct any defects you can identify. In the second exercise
you are asked to develop a more ambitious program, based on the
given program.
Exercise 1: Correction (60)
Consider the program mquiz0.c
../src/mquiz0.c. This should prompt for the user's name; then
print Hello followed by the user's name; then repeatedly ask
the user what the best album of all time is, unless and until
the answer Dark Side of the Moon is given.
Test whether this program behaves as specified.Note
that, once you are viewing the program file in Netscape,
you can use the Save as... option on the File menu of
Netscape to save a copy of the program in some suitably
named file on your PC.
If not,
identify and correct any defects. Carefully record each such
defect, and your correction, in your formal report.
Exercise 2: Enhancement (40)
The program mquiz0 will keep on repeating the question
unless and until the user is inspired to give the correct
answer.
Develop an enhanced version of this program, called
mquiz1. This should behave in the same way as mquiz0,
except that, if the user gives a wrong answer, the program
should then ask whether the user wants to try again. If the
user indicates that he or she does not want to continue
then the program should exit (remarking Good idea - `cos you
don't know much about music, do you?).
Session 5: Week 10/11: Ever Decreasing Circles...
Introduction
This session introduces the use of two new
safe-c data typesintegertype and
floatingpointtype.
A data type is a format for storing and manipulating some
particular kind of information in a program. So far
we have used just two data types: stringtype
and booleantype.
stringtype allows
the input, output, and comparison of
arbitrary strings of ASCII characters. The length of the
string is variable, up to a certain
maximum length. The only manipulations allowed (so far) on
objects of stringtype rely on using functions (or
subprograms) provided by the safe-c module:
putstring() : Allows a string to be be displayed
in the MS-DOS window in which the program is running.
getstring() : Allows a string to be read in from
the keyboard.
stringequal() : Allows two strings to be compared.
Generates a return value which is of booleantype.
This will be TRUE if the two strings
are exactly identical, and FALSE otherwise.
booleantype has only two
possible values (TRUE and FALSE) and is useful
in controlling if and while statements. Values of
booleantype can be manipulated with the following
operators:
In more detail, the meaning of these operators is as follows:
Boolean AND: Denoted by a double ampersand
(with no space between them). Takes two
operands. If both operands are TRUE it evaluates as
TRUE; otherwise it evaluates as FALSE.
Boolean OR: Denoted by a double vertical bar
"" (with no space between them). Takes two operands.
If either operand is TRUE it evaluates as TRUE;
otherwise it evaluates as FALSE.
Boolean NOT: Denoted by an exclamation mark
!. Takes one operand. If the operand is TRUE
it evaluates as FALSE; if the operand is FALSE it
evaluates as TRUE.
Test for equality: Denoted by a double equal sign
== (with no space between them). Takes two
operands. If both operands have the same boolean value it
evaluates as TRUE; otherwise it evaluates as FALSE.
This operator can be applied to operands of certain types other
than booleantype, but its result is always of
booleantype. When the operands are of
booleantype it is equivalent to the negation of the
boolean XOR (Exclusive OR) operator.
Assignment: Denoted by a single equal sign
=. Takes two operands. The left hand operand
must be a variable. The value of the right hand operand is
copied into, or assigned to, the variable named as the left hand
operand.The assignment operator also technically
generates an evaluation result, just as any of the other
operators do. This evaluation result will be the value of the
right hand operandi.e. the same value as is stored in the
variable named as the left hand operand. This allows an
assignment operation to be nested within a more complex
expression. That is sometimes useful, but its use is
beyond the scope of the current session.
The two new data types introduced in this session are both used
to represent, store, and manipulate numbers.
integertype can represent only whole numbers (positive
and negative); floatingpointtype can represent
fractional, or rational, numbers (positive or negative),
using a form of scientific
notation.
The most basic operation or manipulation that can be performed
with these data types is to assign a value to a variable of that
type. This uses the same assignment operator as for
booleantype. For example:
Note, incidentally, that the assignment operator
cannot be used with objects of stringtype. Thus,
it would quite wrong to say something like:
If you need to do something like that, use the function
assignstring instead:
Both the numerical data types allow
the four normal arithmetic operations:
These operators all accept two operands, and evaluate with a result
which is of the same data type as the operands. Note carefully
that when you divide two values of integertype the result
is just the quotient and will still be of
integertype. Any remainder
will be discarded. Thus, for example 5/3 would evaluate
as 1. You can use the special remainder operator,
denoted by , to separately calculate the remainder part
of an integertype division if you like. So 53
evaluates as the remainder after dividing 5 by 3, which is to
say 2. The remainder operator is not
applicable to floatingpointtype (for obvious reasons?).
These numerical data types also allow various comparison operations:
All of these comparison operators yield a result of
booleantype.
The detailed way that integertype and
floatingpointtype are represented internally will not
be discussed here, except to say that they both rely on a binary
notation, because this matches best the actual physical nature
of the computer's memory system.
Functions are provided to convert between values of
these binary numerical data types and stringtypewhich
indirectly allows input and output of these numbers (using
getstring() and putstring()).
All the data types and functions introduced here are specific to
the safe-c module and you will not find them discussed in
standard texts. However, all the operators
(arithmetic, boolean, assignment, comparison) are part of the
language definition and will be covered in the
textbooks.
More detailed information on these
new data types, and the facilities available for using
them, is
provided in the safe-c User Guide
../safe-c.
You are again required to write a formal lab report in this
session, and submit
it by email, in exactly the same format and manner as in
sessions
3 and 4. This session also again involves creating, editing and storing
files on your PC (in suitable directories),
and compiling source files to produce
executable files.
If you are unsure of any aspect of doing these things,
please review the
session 3 notessession3
again. The relevant instructions will not
be repeated here.
The overall format of this session is very similar to session 4.
It has two exercises. In the first you are given a
program and told what it ought to do. You are then asked to
test whether the program behaves as specified; and, if not, to
correct any defects you can identify. In the second exercise
you are asked to develop a more ambitious program, based on the
given program.
Exercise 1: Correction (50)
Consider the program circle0.c
../src/circle0.c. This should prompt for the user's name; then
print Hello followed by the user's name; then ask
the user to enter the radius of a circle (in m); the program should
then calculate and print out the circumference and area of the
circle.The circumference is given by the mathematical
formula ; the area by the formula .
The program is very poorly laid out and formatted. Reformat it
in a way that makes it easier to read and understand.Note
again that, once you are viewing the program file in Netscape,
you can use the Save as... option on the File menu of
Netscape to save a copy of the program in some suitably
named file on your PC.
Correct any obvious mistakes.
Of course, you should note
what changes your make, and include a copy of the reformatted
program, in your formal report.
Now test whether the program behaves as specified.
If not, identify and correct any defects. Carefully record each such
defect, and your correction, in your formal report.
Exercise 2: Enhancement (50)
The program circle0 calculates the circumference and area
of just one circle.
Develop an enhanced version of this program, called
circle1. This should behave in the same way as
circle0,
except that it should repeat the
sequence (of requesting a radius, then calculating and printing
out the circumference and area) exactly five times. Each time
the prompt should change (so the first time it should say
Enter radius 1:, the second time Enter radius 2 and so
forth).
Session 6: Week 12/13: Lab Examination 1
Please see the
General Examination Instructions
http://www.eeng.dcu.ie/7Emcmullin/swe1/95-96/exams/general, which
includes links to all the specific examination exercises for the
different sections of the class.
Session 7: Week 14/15: Functional Decomposition
Introduction
This session is concerned with practical experimentation with
the facilities for breaking down a program into smaller,
more manageable, pieces called functions.
The standard library makes available a large range of standard
mathematical functions. These include standard trigonometrical
functions, sin(), cos() and tan(). These three
functions each accept one argument (of
floatingpointtype) and
return a result (also of floatingpointtype). The
argument must be an angle measured in radians. Often it is
more convenient to work with angles measured in degrees instead.
The ultimate objective of this session is for you to write your own
trigonometric functions (exploiting the existing standard functions)
which will accept arguments in degrees rather than radians. However,
we shall get there through a series of smaller steps.
Before this session it is essential that you review and understand the
very basic example programs, already introduced in the lectures, which
illustrate functional decomposition. These are:
sum0.chttp://www.eeng.dcu.ie/7Emcmullin/swe1/src/sum0.c:
This program prompts for two numbers, adds them, and prints out the sum.
It does not use functional decomposition at all.
sum1.chttp://www.eeng.dcu.ie/7Emcmullin/swe1/src/sum1.c:
This is a modified version of sum0.c in which a new function has
been defined, called getfloatingpoint() which combines the
effects of the standard safe-c functions getstring() and
stringtofloatingpoint(). This illustrates how to define a
function which has to pass back, or return, some information to
the place which it was called from; and how to use, or access, that
information at the calling site.
sum2.chttp://www.eeng.dcu.ie/7Emcmullin/swe1/src/sum2.c:
This is a further modified version, in which a second new function has
been defined, putfloatingpoint() which combines the effects of
floatingpointtostring() and putstring(). This
illustrates how to define a function where some information has to be
passed from the calling site, into a function, and how that
information can be accessed within the function.
The session is divided into five separate exercises. Each of these
builds on the previous one. It is important that you read through the
instructions for all the exercises, in advance of the lab
session. None of the exercises is very complex in itself, and you should
be able to complete all five in the time available. However, it is more
important to fully complete as many of the exercises as possible than to
make an incomplete attempt at them all. So, it is essential that you
take the exercises in the order given, and do not attempt to go on to a
following exercise until you have fully completed its precursor.
Each exercise involves developing a program. Note carefully that
develop here means writing, compiling (with no errors or warnings),
and testing. The tests should exercise a reasonable range of
behaviour before you consider them complete. The report must
specify exactly (including actual numerical values, where relevant) what
tests you carried out, what results you expected, and what results the
program generated. If the actual results are not exactly the same as
the results you expected, you must comment on this.
Exercise 1: The sin() Function (20)
Develop a program, called trig1.c, which will prompt for an angle
value (in radians), and print out the sine of that angle.
Where appropriate, this program
should use the functions getfloatingpoint() and
putfloatingpoint() defined in the example program
sum2.c
http://www.eeng.dcu.ie/7Emcmullin/swe1/src/sum2.c. You
can simply cut and past the relevant section of that program
into your own program.
This program does not involve defining any additional
new functions of your own.
Exercise 2: Angle Conversion (20)
Modify trig1.c as follows, renaming it as trig2.c.
trig2.c should prompt for an angle in degrees. It should
then calculate the corresponding angle in radians, using the equation:
where and denote the angle expressed in degrees
and radians respectively.
Having converted the angle to radians, it should then calculate, and
print out, the sine (this behaviour is unchanged from
trig1.c).
The degrees conversion calculation should be carried out directly
by suitable statement(s) within the main() function.
That is, this program again does not involve defining any additional
new functions of your own.
Exercise 3: Function Definition (20)
Modify trig2.c as follows, renaming it as trig3.c.
trig3.c should behave exactly as trig2.c. However,
instead of carrying out the angle conversion directly within the
main() function, main() should invoke or call a new
function, called degtorad(), to do this conversion. This
should accept a single argument, of floatingpointtype,
representing an angle in degrees. It should return a result, also
of floatingpointtype, being the corresponding angle in
radians. Of course, you have to provide the definition of this new
function.
Exercise 4: Refinement (20)
Modify trig3.c as follows, renaming it as trig4.c.
trig4.c should behave exactly as both trig3.c and
trig2.c. However, instead of calling degtorad() and
then calling sin(), main() should simply call a single new
function, called degsin(). This should accept a single argument,
of floatingpointtype, representing an angle in degrees. It
should return a result, also of floatingpointtype,
being the sine of this angle. Again, you have to provide the
definition of this new function. It should use the
function degtorad() which you have already written.
Exercise 5: Finale (20)
Modify trig4.c as follows, renaming it as trig5.c.
trig5.c should prompt for an angle in degrees, and then print out
the sine, cosine and tangent of this angle. The
main() function should be structured to invoke functions called
degcos() and degtan() to calculate the cosine and
tangent respectively. You will have to add definitions for
these functions, similarly to the definition of degsin().
Hints
When defining a new function, you need to first prepare an adequate
specification. This will consist of answers, expressed in plain
English, to the following questions:
What will it be called?
function names, like variable names, consist of a sequence of
characters, including upper and lower case alphabetics, the digits
0 through 9, and the underscore character . The name
should always begin with an alphabetic. Names can be as long as
you wish, but anything much longer than 20 characters becomes unwieldy
and error-prone and should usually be avoided. All function names must
be unique within a given program. Most programmers use
only lower case alphabetics in function and variable names (i.e.,
no capitals). However, this is only a convention, and is not a
compulsory part of the language definition. Names of functions are
usually chosen based on verbs because they do something -
whereas names of variables tend to be based on nouns (they just
are). It is important to think carefully about the names of both
functions and variables in a program. While the compiler really
doesn't care (as long as the names are unique) these choices can make a
big difference to how easy or difficult it is for another human
being to understand how the program is intended to operate.
What (if any) information will be passed in from the
calling site?
Many functions can behave differently based on certain information
passed into them by their calling function. For example, the standard
function putstring() is able to print out any string on
the screen. Which particular string it will print out on any
particular occasion is specified by the calling sitethe invocation
specifies a particular string to be passed into the function.
The specification of the information to be passed into a function will
thus determine the layout of its argument list. The argument list
states how many arguments the function will accept, what types they must
be, and what names will be used within the body of the function
to refer to these arguments.
What (if any) information will be passed back to the calling
site?
Many functions generate a result of some sort, which must be made
accessible to its calling site, after the function has finished
execution.
In the special case of objects of stringtype, this can be
achieved by the calling site passing in a string variable to the
function; any changes which the function makes to this string, will
still be visible, after the function terminates, at the calling site.
This is called passing by reference, and is the mechanism used,
for example, by the getstring function.
However, this does not work for information of other types. Thus,
for example, if a variable of integertype is passed into a
function, all that really happens is that a copy of this
variable is made available to the function. Any changes which the
function makes to that value are lost when the function exits.
This is called passing by value. In this case, the idea of
passing in a variable for a function to modify cannot be used to allow a
function to pass information back to its calling site. In that case,
you should use the return value mechanism. If you place a
return statement in your function then, when that statement is
executed, the function will immediately terminate, and the specified
value will be made available at the calling site, in the
position where
the function was invoked. This is the mechanism used, for example, by
the stringfloatingpoint function. Typically, this
return value is assigned to a variable at the calling site, so
that it can be stored for use in subsequent statements.
The return mechanism cannot be used to pass back values of
stringtype. In that case, you must use the passing by
reference mechanism, where a string variable, belonging to the calling
site, is passed into the function as an argument, and modified by it.
The specification of the information to be passed back from a function
may thus lead to the specification of additional arguments (passing by
reference), or to the specification of a return type (or,
possibly, both).
What will the function actually do?
That is, having stated what, if any, information if passed in, and what,
if any, information is passed back, you need to state, in plain English,
what the effect of the function is supposed to be.
The idea of defining a new function usually arises in the context of
some higher level function which you are already writing.
Essentially, you want to defer coding some more detailed activity or
calculation. This is called top-down design, and is a typical
strategy for all forms of engineering design, not just software.
So, for the time being, you just want to put in a call to a
function, which, at some later stage, you will define in detail. The
coding of this function call will, implicitly, at least, answer all of
the questions we have just raised.
Having answered these questions, you should then enter the skeleton
definition of the function:
You then go back and fill in the slots. For example, suppose we decide
to define a function called foo, which will accept one argument of
floatingpoint type, and generate no return value, we can
immediately make out the following skeleton:
You need to minimally provide this skeleton, just to allow an
invocation of the function to even be compiled properly. You may well
temporarily put in a dummy body to the functioncalled a
stubjust to allow you to test out the higher level invocation. But,
eventually, you must come back and fill in the body of the function
definition with the actual statements which will make it, upon
invocation, carry out the activities specified for it.
Session 8: Week 16/17: Projectiles
Problem Specification
The purpose of this exercise is to calculate the theoretical trajectory
of a projectile in a constant gravitational field. In other words, we
want to calculate the path followed by, say, a ball thrown in the air.
We are going to make some simplifications. We will work in just two
dimensions (i.e. as if we are looking exactly side on at the path of the
ball). We will also neglect air resistance, and will treat the
projectile as a point mass. This allows a simple analysis of the motion
of the projectile, using newtonian theory.
In our two dimensional ( and ) coordinate system, will denote
horizontal position, and will denote vertical position.
The initial value of will be taken as zero.
A zero value will correspond to the projectile being on the ground.
The initial value of will be some positive value (in effect, the
height of the person throwing the ball).
will denote the horizontal component of velocity, and the
vertical component. We will assume that both and are
initially positive. Similarly, and will be the components of
acceleration.
The initial information provided for a particular run of the program
will be the initial
height () and initial velocity components ( and ) of the
projectile. These values will be assigned to suitable variables. You can
either code values directly into the program (in which case you will
have to change the program, and recompile, every time you want to try
different values) or you can have the program prompt for and read in
values when it starts running.
The output from the program will be a print out on the screen of
the numerical values
of and at successive, small, intervals of time. The program
should terminate when becomes zero again (i.e. the projectile falls
back to earth). This print out may be captured into a text file
and a graph plotted of versus (one way of doing this
is described in detail in
the Hintshints8 section below).
Informally, the motion of the projectile is pretty simple: it moves
steadily to the right (positive direction), simultaneously going up
for a while (positive direction), and then coming down again to
land.Technically, under the various idealizing assumptions we
have made, it can be shown that the trajectory will be
parabolic.
Formally, at each time step, the new co-ordinate can be calculated
as:
where (approximately):
In words, if the velocity in the direction is , then, in a time
, the projectile will move a distance of multiplied by
; and the new position is the old position plus this
movement. This calculation would be exact if were
constant; if is changing (as it will be in our case) then
the calculation will still be approximately correct, as long as
is smallnamely small enough that the percentage change
in in that time is negligible. Of course, you can only
estimate this once you have some idea of how quickly will be
changing...
The new co-ordinate may be calculated similarly.
Now, in principle, both and could also be
simultaneously changing, and have to be recalculated, at each time step.
But since we are neglecting air resistance, and since gravity works
straight down, there will be zero acceleration in the direction
( is zero), so that will actually remain constant, equal to
its initial value. There will be acceleration in the direction
however, of value , where is the acceleration due to gravity at
the surface of the earth (about 9.81 meters per second per second).
This is negative because our co-ordinate is positive in the upward
direction and gravity works downward (last time I checked anyway...).
This acceleration in the direction will be constant (since is
not changing). Thus, the new at each time step can be calculated
as follows:
where:
That is, the change in the (vertical) component of speed is simply the
(vertical) acceleration multiplied by the time it acts over; and the new
speed is simply the old speed plus this change.This change
will be negative, because is negative; to put that
another way, what goes up must come down!
You should test your program carefully. Explain, in your report, what
tests you carry out, how the program behaves, and whether it has passed
such tests.
Hints
The main() Function
Your main() function should declare variables to
represent the values of all the relevant quantities. Think
carefully about naming these variablesnote, for example,
that variable names cannot involve subscripts, or greek
characters. Think carefully about the type of each
variable: is it to be used to represent a numerical
value? If so, will that value be strictly integral, or
may it have a fractional part?
The overall structure of your main() function will
consist of some initialisation (assigning initial values to
appropriate variables), followed by a while loop
which carries out the repeated calculations of the new
and co-ordinate values. This loop should continue
just so long as the value is greater than zero.
The repetition, or iteration, in your program should
be achieved using a while statement.
It might be a good idea to start off with a highly simplified
version of the main() function, having only a
variable to represent
and which just (for example) decrements
the value by a fixed amount each iteration. This would
allow you to check, at this early stage, that you have
correctly implemented the while loop and that it
terminates when appropriate.
Functional Decomposition
Try to use functional decomposition to break your program
into smaller, more manageable pieces. This will make it
easier to write, test, and debug.
Where appropriate,
consider using the functions getfloatingpoint() and
putfloatingpoint() defined in the example program
sum2.c
http://www.eeng.dcu.ie/7Emcmullin/swe1/src/sum2.c. You
can simply cut and past the relevant section of that program
into your own program.
Define a new function of your own, which deals with printing
out the results, for one cycle of your calculations. This
can then be simply called or invoked from within the
while loop of your main() functionwhich
should make the main() function shorter and easier to
follow. Note that this function will have to accept two arguments
(being the current values for the and co-ordinates).
Command Line Redirection
If you want to plot a graph of the trajectory calculated by your
program, you will need to capture the program output in a file, rather
than having it simply displayed on the screen.
Perhaps the simplest way of arranging for a program to route its output
to a file (or, indeed, to take its input from a file), is to use
so-called command line redirection.
Suppose your program is in a file called foobar.c. After
successful compilation, you will have a executable file called
foobar.exe. Normally you would execute this simply by giving the
name foobar as a command. However, if you want to use command line
redirection, you would give a command somewhat like this instead:
The serves as the input redirection character in an MS-DOS command
line. The effect is that the input for foobar will no
longer be taken from the keyboard, but from this file instead.
Similarly, the character in an MS-DOS command provides for output
redirection, to direct output to a file instead of the screen.
With any given command invocation you can choose to use no redirection
at all (as we have been doing up to now), or to use input redirection
only, or output redirection only, or both together.
Plotting a Graph
Sometimes you may find it useful to view the output of a program in the
form of a graph. There are a variety of ways of doing this. One simple
way is using a utility program, provided on the PC's in the CAE Lab,
called graph. This program should be run as a full-screen
MS-DOS application. To do this, first open an MS-DOS window by double
clicking on the relevant icon in Program Manager. Then make this window
take over the full screen by pressing Alt-Enter
(i.e. press and hold the Alt key while you press the Enter
key also).
If your program's output has been stored in a file
called out.txt, you can then see a graph of this simply by giving the
following command:
Note that graph expects each line of its input file to contain
just two numbers. The first is taken as the x co-ordinate, and the
second as the y co-ordinate, of a single point to be plotted.
graph will automatically scale the axes in order to fit in all the
data points.
You can exit from the graph program by pressing the Esc key.
You can make the MS-DOS application revert from full-screen to a window by
pressing Alt-Enter again.
Session 9: Week 18/19: Encryption
Exercise 1: The Caesar Cipher (50)
Encryption is the process of disguising a message or text so that its
meaning will not be apparent to anyone who may intercept it,
accidentally or otherwise.
In this exercise you will work with a very simple encryption procedure.
This is called a substitution cipher, in which each letter of the
original message (the plaintext) is replaced by a different letter to
generate the coded message (the ciphertext).
To simplify matters further, we will restrict our plaintext to use only
the upper case letters A to Z, together with the space and
newline characters; furthermore, space and newline characters will be
left unchanged by the encryption.
In each case, the replacement letter will be a fixed number of letters
later in the alphabet compared to the original letter (and wrapping
around back to A again after Z, as necessary). The number
of letters to count forward will be called the encryption
key.
Thus, with a key of 3, we would replace A by D, B by
E and so on, with, finally, W being replaced by Z,
X by A, Y by B and Z by C.
This simple kind of cipher is sometimes called a Caesar Cipher
after Julius Caesar, who is said to have used it for secure battlefield
messages.
To implement a Caesar cipher with a program, note that, when
accessing individual characters in , what you are really dealing
with are numeric codes for the characters. As such, you
can do any normal arithmetic (addition, subtraction etc.) and comparison
(greater-than, less-than etc.) operations on them.
The relationship between the characters, as displayed on your screen or
in your editor, and the numeric codes accessed within your
program is strictly arbitrary. It is not specified by the
language standard. It is thus open to anyone developing a compiler
to adopt any character numbering scheme they like; you cannot reliably
assume that the numbering scheme in effect for one compiler will be
the same as for another. Strictly, you need to check the documentation
for your particular compiler to find out what the numbering scheme is.
However: there is one particular numbering scheme which is the most
widely used, and to which most compilers conform (including
DJGPP): this is the so-called ASCII scheme.If you
really want to know, ASCII is an acronym for American
Standard Code for Information Interchange.
In ASCII, the upper case letters A to Z have
consecutive numeric codes from 65 to 90. Thus, given a particular key
value (a number from 1 to 25) simple addition will encypher a letter as
requiredexcept that if the sum is greater than 90 you must wrap
around to the start of the alphabet again by subtracting 26.
You are required to develop a program which will input a series of lines
of characters, and encode them with a Caesar cipher; as each line of
plaintext is input, the corresponding line of ciphertext should be
output. It is up to you to devise a mechanism whereby the user can
indicate that all lines have been input, and to implement the program in
such a way that it will then terminate.
The key for the encoding should be hard coded into your program (as
opposed to be being read in at run time). Thus, changing the key will
involve modifying the source program and recompiling.
You may find it handy to be able to run your program on an input
file (and producing an output file) rather than working only
with the keyboard and screen. Use command line
redirectionredirection to achieve this.
Exercise 2: Crytanalysis (20)
Now think about the problem of cryptanalysis: that is, suppose you
are the enemy and have intercepted a transmission known to have
been encyphered with a Caesar cipher. How would you set about trying to
decipher it? You may wish to challenge a colleague in the class to see
who can decipher the other's ciphertext message most quickly. Record
your conclusions in your report.
Exercise 3: The Vigenere Cipher (30)
Finally develop a program to implement the somewhat more sophisticated
Vigenere cipher, invented in the 16th century by Blaise de
Vigenere. This has the same basic idea as the Caesar cipher, but the key
no longer stays the same throughout the message: instead it follows some
periodic cycle. A Vigenere key is thus not a single number but a
sequence of some fixed lengthsay 10, 3, 25, which would mean the
first letter should be shifted by 10, the second by 3, the third by 25,
and then back to 10 again etc.
Session 10: Week 20/21: Letter Frequencies
In a world where there are code makers there will, inevitably,
also be code breakers. One of the simplest tools in the armoury
of a code breaker is a program to count the relative frequency of each
letter appearing in the cyphertext. For any given language there will be
a characteristic distribution of letter frequencies in the uncoded
message (the plaintext). The most commonly used letter in English is
e, by a wide margin; t is in second place, with a and
o nearly tied for third; i, n and r are also
very commonly used.
If we know that a coded message uses any kind of
simple substitution cypher (such
as the Caesar cypher we saw previously) then a simple count of the
relative frequencies will allow us to make a fairly good guess as to the
letters which have substituted for the most common english letters.
Often this would be enough to allow the remaining substitutions to be
easily guessed.
Of course, real cyphers are much more sophisticated and harder to
break than this (how would you tackle a Vigenerevigenere
cypher for example?).
But letter frequency counts still form an essential tool for code
breaking, albeit in conjunction with many other techniques.
Try to develop the programs for this session without using
safe-c. You should use
standard library
http://www.eeng.dcu.ie/7Emcmullin/swe1/stdlib
functions declared in stdio.h
for doing input and outputfor example, use getchar()
for reading in the input file and use printf() for printing
out results. Use functions declared in ctype.h for testing
(or possibly altering) the characteristics of character code data
(e.g. distinguishing alphabetic from non-alphabetic characters;
or changing between upper and lower case etc.).
Exercise 1: Counting A! (30)
Your first task in this session is to write a program which will
read a file, and count how many times the character A (or
a) occurs. The program should ignore the distinction
between upper and lower case, and should ignore all characters
other than A (and a). When the file has been
completely read, the program should output the total number of
A characters found.
Redirectionredirection should be used to cause the
program to read the appropriate file via stdin.
As usual, you should test your program carefully, and document any
problems etc. in your report.
Exercise 2: More Counting... (30)
Now enhance your program to count how many times each separate
alphabetic character occurs. Again, it should ignore
distinctions between upper and lower case, and should ignore all
non-alphabetic characters. So it should generate 26 distinct
count values, one for each letter of the alphabet, and not
counting non-alphabetic characters at all.
Note that you can use a single array,
with 26 elements (where the elements
are of type int, say), to hold all the counts.
You will need to think carefully about how to access the
correct position or slot in this array to get the
correct count for any given letter found in the file.
When the file has been completely read, the program should output a
table showing the count for each of the letters A to Z.
Again, you should test your program carefully, and document any
problems etc. in your report.
Exercise 3: Statistics (20)
Next you are required to enhance the program further so that it
will also calculate the total number of all alphabetic
characters read, and output, for each character, both the actual
number of times it occurred, and the percentage this
represents of the total number of alphabetic characters
encountered.
Again, test and document the program carefully.
Exercise 4: Plotting a Histogram (20)
Finally: develop a further version of the program, which, instead of
outputing the relative frequencies as numbers, outputs a
histogram. This will be made up of lines of varying width (made up of
asterisk characters) one line for each letter, from A to Z.
The letter with the most occurrences should be scaled to give a line
with, say, 60 *'s. Then the lines for all the others should
be shorter in proportion. The display might look somewhat as
follows:
and so on.
Note that histograms would normally be plotted with the
independent variable oriented vertically, whereas I have
described an horizontal orientation here. If you have
time, try to alter your program again, to yield a histogram with
a vertical orientation (this is a substantially more challenging
task).
Session 11: Week 22/23: Simulating an RC Circuit
The program(s) developed in this session
must not use any facilities of the
safe-c librarythey must rely on the
facilities of the Standard C Library
http://www.eeng.dcu.ie/7Emcmullin/swe1/stdlib
instead.
Consider the following
schematic diagram of a simple RC circuit:
The capacitor is assumed to be initially charged up to some
voltage denoted v(0), corresponding to a charge level of:
The switch is closed at time
t = 0. The capacitor then discharges by causing a current
to flow through the resistor.
Denote the instantaneous signals in the system as follows:
: The instantaneous charge on the capacitor at
time t.
: the instantaneous voltage
across the capacitor at time t.
: the instantaneous
current discharging from the capacitor through the resistor,
at time t.
Suppose that, at some time t,
the value of q(t) is known. It then follows that
the following values may be calculated:
Consider now what happens over a small interval of time,
which I shall denote . If this interval is small
enough we can take the current to be approximately constant over
this interval. Thus, the change in the value of q over this
interval can be approximated by:
and the value of q at the end of the interval
can be calculated (approximately) as:
Since we now know the value of q, one time step later, we
can now repeat all the calculations to calculate the values of
v, i and q one time step later also and thus
calculate how much q will change by over one further
time step. And so on. By repeating this procedure, one can
calculate the state of the circuit (at least approximately) into
the indefinite future, once we know the state at some
initial time.
In fact, this basic method is so powerful that it can be
extended to (approximately) predict the time behaviour of
arbitrarily complex electronic circuits under arbitrary
stimulation and such simulations are a crucial tool in
the design of all modern electronic circuits.
Exercise 1: Basic Simulation Program (60)
Develop a program which will simulate the
behaviour of a simple RC circuit, in the sense of providing
predictions of how the charge on the capacitor will vary over
time.
The program should prompt for and read in values
for the following parameters from the user:
: Resistance (in ).
: Capacitance (in F).
: Initial value of q (in C).
: The duration (in s) of one time step.
(In practise, choose to be a small fraction
less than 1 sayof the circuit time constant, which
will be given by .)
: The value of t at which the program should stop.
When the program is executed, it should print one line on the
screen for each time step. Each line should show the time and
the calculated value for q(t) at that time.
Exercise 2: Enhanced Simulation Program (40)
Now enhance your program in the following ways.
Instead of automatically prompting for the required parameter
values, the program should offer the user a choice of reading
the values from the keyboard or from a file (which would have
been prepared in advance). When the user opts for reading from
the keyboard, the program should prompt for, and read the
parameters just as before. Where the users opts for a file, the
program should prompt for the file name, and then read the
parameter values from the file (without issuing any prompts). If
the program encounters any difficulty reading the parameters
from the specified file, it should offer the user a choice
between giving up, or respecifying the file to read from, or
reverting to reading the parameters from the keyboard.
Once the program has successfully got a set of parameter
values, it should offer the user a choice between output to
the screen, or output to a file. Again, in the former case,
the program should continue as before; but in the latter
case, it should prompt for the name of the file to output
the results to.
Session 12: Week 24/25: Exploring Pointers
Note that in this exercise you are not required to generate any
new programs of your ownthough you may wish to modify the
programs you are given.
This exercise is concerned with exploring the use of pointers in .
Specifically, you will examine programs where pointer variables are
created using pointer data types. Thus, for example:
declares a variable, i, of type int; whereas the
declaration:
declares that i is a variable of type pointer to int or
(int *). That is, i itself does not hold an int
value, but the thing it points at does.
Note that you can happily declare variables which point at other pointer
variables. Thus:
declares that i is a variable of type pointer to pointer to
int. The value of i is a pointer; the thing it
points at is now another pointer variable; but the thing
this points at is an int. And so on!
A pointer value can be produced using the address-of operator, denoted
with the ampersand character . Thus, the following code
fragment might make sense:
The net effect is that ptr now points at a.
You can display a pointer value using the p format
specification with printf():
With our particular computer platform, addresses can be
thought of as binary numbers with 32 bits. By convention,
they are displayed by printf() in hexadecimal,
or base-16, notation (where the digits 0 to 9
as used as normal, but the letters A through F
are used to represent the base-16 digits for the numbers
10 to 15). So a typical result from executing the printf()
above might be something like:
The 0x prefix is a standard C notation for showing that
a number is in hex; this is then followed by 8 hex digits
(since one hex digit represents a number between 0 and 15, it
is equivalent to 4 binary digits; so a 32 bit number is
equivalent to 8 hex digits). In any case, your only use for
looking at pointer values will be to assess whether or not
different pointer values are equaland you can do
that without knowing any of the details of interpreting
hex notation.
A pointer value is dereferenced with the dereference
or indirection operator, denoted with the asterisk
character, *. A dereferenced pointer may be used
anywhere a variable name can be used.
Thus, normally, a variable name evaluates as the value of a
variable; so a dereferenced pointer normally evaluates as
the value of the thing pointed at. But a variable
name can also be used in an assignment, in which case its
value is altered (overwritten); similarly, a dereferenced
pointer can be used in an assignment, and the value of the
thing pointed at will be changed.
Note very carefully that, whenever you are dealing with a
pointer variable, you must be very clear about whether it
is its own value that is being referred to, or the
value of the thing pointed at; these are generally
very different things (they are usually even of different
types, never mind values).
A simple use of dereferencing is this:
In this simple fragment, there are two variables of type
int, and one of type pointer to int. The
variable ptr is given the value i, so it
points at i; i is given the value 25; so
when j is given the value 2 + *ptr, this means
2 plus the value of the thing ptr is pointing at
and this evaluates as 27; finally, *ptr, which
is to say i, is given the value j + 2 which is
to say 29.
Take a copy of the file ptr0.c../src/ptr0.c. This
is a basic test program for investigating the idea of
pointers. Note that this program (and all the other
programs introduced in this session) is totally
contrived. It does not do anything useful whatsoever. It
is intended purely as a vehicle for you to experiment with
pointer variables and pointer operations.
First analyse the program by hand, and predict what you
think the outcome will be. Record this analysis in your
report. Then execute it and test your predictions. Add
extra printf() statements as you deem necessary in
order to check the values of variables at different stages
during execution. If the results differ from your
predictions then test more carefully until you can explain
the discrepancies. Note your results in your report.
Repeat the procedure described above for the file
ptr1.c../src/ptr1.c.
Now consider the file ptrnet.c../src/ptrnet.c.
The is again a contrived program. It does not do anything
useful. It merely serves to illustrate some further ideas
on the use of pointers.
To understand this example you will first need some
elementary understanding of structures. Only the
basic ideas will be introduced here. For more detailed
information consult a textbook.
The idea of a structure in is that you can group a
number of distinct data items, of distinct types, together
into one unit. That collection of data items can then (for
some purposes at least) be manipulated as a unit. In
particular, having once described the format or
shape of the unit, one can declare, in a single step,
structured variables which have separate slots for all
the constituent parts or members. Look at this
simple example:
struct is a keyword which introduces the declaration
of structured variables. This is followed by braces which
enclose a detailed description of the members of each
structured variable. Finally come the names of the actual
variablesfive of them in this case. The effect of this
declaration is to create five variables, each of
which has two distinct members, one called age the
other called IQ. To access these members we use the
dot operator, thus:
and so on. But we can also, to a limited extent, manipulate
a structured variable as a wholefor example, by
assignment:
This would assign the values of the members of john
to each of the corresponding members of henry in
turn. Thus, it would be exactly equivalent to:
So far, so good. It should be clear that structures might
be useful whenever you have information that naturally
divides into groups or units with a certain similarity.
This next point is that, if you are using structures at
all, it is often handy to be able to declare structured
variables (or function parameters for that matter), having
a given shape (i.e. a given set of members) in several
different places in your program. Now you can certainly
do this in the obvious way by simply repeating the
detailed declaration of all the members in each different
place. But it would be nicer if the compiler could let you
declare the shape once, and then refer back to it later.
And, fortunately, it doesactually in a couple of
different ways. But I will just show one:
This time I have put an identifier (person)
immediately after the struct keyword, and before the
left brace. This does not create a structured
variable called person. Instead, person acts
as a tag or identifier for this particular shape of
structured variable. Once I have given this declaration,
then, at any subsequent point in the program, I can use
simply struct person as a shorthand for the full
declaration. So I could write, for example:
This would then create variables barry, john
and mary with the same shape as before. Then
somewhere later on (or inside some other function) I might
write:
Be clear on the advantage of adding an identifier, such as
person to a particular shape of structure: it just
saves having to re-enter the detailed description of the
shape in several different parts of a program.
One slight difficulty might be evident here: in reading a
program one can easily become confused between identifiers
such as henry, which refer to actual variables, and
person which simply identifies an abstract shape for
variables which might get declared at some stage. It
would be ridiculous, for example, to try to refer to
person.age because there is no such variable as
person. Rather, person simply provides a name
for a template from which variables might be created.
Once you get used to using structures this should not cause
any problem. Once you see the keyword struct you will
expect to see it followed either by a left brace or a name
for a particular shape of structure. But when you are just
starting off, it may be a good idea to adopt some kind of
systematic identifier conventioni.e. to choose your
identifiers so as to clearly distinguish between those that
refer to actual variables and those that simply refer to an
abstract shape. One simple convention that I sometimes use
is to append s (for structure) to the end of
any identifier that refers to a structure shape. So I
would actually use the identifier persons. But
note carefully that is only a convention: it has no
significance for the compiler at allit is purely a
device to remind a reader of what's going on.
OK, now we can declare a structure shape, and give it an
identifier; we can declare variables or parameters of that
shape; and we can access the members of such variables. We
now join these ideas up with the idea of a pointer.
Roughly speaking, we can embed, within a structured
variable, a pointer member that points at something else.
In particular, we can embed a member that can point to
another structured variable of the same type or shape. And
once we can do that, we can create indefinitely large
networks of structured variables that are linked together
by pointers. This turns out to be an immensely powerful
programming ideawhich, regretfully, we shall not be able
to pursue properly in this introductory course. For now,
you simply have to take it on faith that this idea is
potentially useful. The question for us is simply what
language features we need to use to do it.
At this stage, look again at the example program
ptrnet.c../src/ptrnet.c. This first introduces the
declaration of the structure shape called buckets:
This says, simply, that any structure of this shape will
have three members, called black, white and
quantity. The quantity member is simply of type
int; but black and white are pointers to
(other?) structures of the same shape. Of course, they do
not automatically point at any particular other structures:
but they potentially can, if suitable assignments are
made.
Four actual variables of this structured type or shape are
then declared:
Each of these will have the three separate members
already described. They have been declared outside of any
function so they are visible and accessible to all
functions.
The rest of the program then involves setting up particular
linkages between these structures (via the black and
white members) and using these linkages to indirectly
access various members in different ways. I repeat that
none of this achieves any useful purpose: the only purpose
of the exercise is for you to test whether you have a
sufficient grasp of what's going on to be able to
accurately predict what members will be accessed in each
case. There is one final facility of you need to
understand in order to to this: the so-called arrow
operator. Consider this fragmentary program:
In this program there is a structured variable called
barry, and a pointer variable called p. For
the purposes of the example, p is made to point at
barry, and then the age member of barry
is indirectly accessed via p. This is done with the
construction (*p).age. That is, p is first
dereferenced using the * operator; this yields the
thing p points at (namely barry), and the dot
operator is then used to access the age member of
this structure. The parentheses around *p are
necessary here because the dot operator takes precedence
over dereferencing by default. So if I simply write
*p.age, the compiler thinks I want to first take the
age member of p and then dereference that. Now,
since p isn't even a structured variable, and
therefore has no members at all (never mind a particular
one called age) this cannot make sense, and the
compiler would simply generate an error. But in more
complicated cases the compiler might not even diagnose the
error effectively. Anyway, the point is that if you are
starting with a pointer, and you want to get at a member of
the object being pointed at by that pointer, then you must
use something like (*p).age. This is moderately
convoluted; worse still, it turns out that this kind of
operation or access is actually needed very commonly in
programs that operate on complicated data structures. The
language therefore provides a single operator, the
arrow operator, which combines the effects of
dereferencing and accessing a member of the structure
thus accessed. It is written like this:
But try to get clear that p->age is simply shorthand
for (*p).age: if you ever find the arrow operator
confusing, then try replacing it by the longhand
version, with an explicit dereferencing and explicit dot
operator.
Now, with all that in mind (!) let's return to the final
part of the exercise, and the program
ptrnet.c../src/ptrnet.c.
First try to draw out on paper the relationships between
the structures n0, n1, n2 and n3
immediately after execution of the statement at line
77 (the invocation of the function
redconnections()). Do this by analysing the
program manually, not by executing it. The
diagram should show graphically what each pointer member of
each structure is pointing at.
Next attempt to predict the values of the quantity
members of each structure immediately after execution of
the statement at line 78 (the first invocation of the
function massage()). Check your predictions by
executing the program (you'll have to add some printf()
statements to print out the values you are interested in).
Explain any discrepancies.
Note that I really do mean thatdo not go any further
unless and until you can explain all discrepancies between
your predictions and the actual results.
Now draw a new diagram showing the relationships between
the structures immediately after execution of the statement
at line 79 (the invocation of the function
blueconnections()). Repeat this diagram one last
time for the situation immediately after execution of the
statement at line 80 (the invocation of the function
yellowconnections()).
Finally, predict the values of the quantity members
of each structure immediately after execution of the
statement at line 81 (the second invocation of the
function massage()). As before, check your
predictions by executing the program, and explain any
discrepancies.
Copyright
This Hypermedia Document is copyrighted, 1994--1996, by
Barry McMullinhttp://www.eeng.dcu.ie/7Emcmullin/home.html.
Permission is hereby granted to access, copy, or store this work, in
whole or in part, for purposes of individual private study only. The
work may not be accessed or copied, in whole or in part, for
commercial purposes, except with the prior written permission of the
author.
Listing 1: mquiz0.c
Listing 2: circle0.c
Listing 3: ptr0.c
Listing 4: ptr1.c
Listing 4: ptrnet.c