C Course Lecture 4 - Richard G. Clegg's Webpage

Download Report

Transcript C Course Lecture 4 - Richard G. Clegg's Webpage

C Course Lecture 4
•
•
•
•
•
•
This lecture we'll talk about:
Multi-dimensional arrays.
Pointer arithmetic.
Pointers to structures.
Multi-file programming.
What is the halting problem?
Multi-dimensional Arrays in C
• Last week we dealt with 1 dimensional
arrays in C.
• C can also deal with 2 dimensional arrays
(although this is rarely done)
int array[3][6]; /* Declare a 2D array */
int i,j;
array[0][0]= 7; /*Set an element of it */
printf ("element 1,1 is %d\n",array[1][1]);
for (i= 0; i < 3; i++) {
for (j= 0; j < 6; j++) {
array[i][j]= 0; /* Blank the array*/
}
}
We can pass 2D arrays to and
from functions
• However, to do this, we must provide a size
for them
• Example prototype for function:
void process_array (int [3][6]);
Call the array with this (in main or other function)
int thearray[3][6];
process_array(thearray);
And write the function with
void process_array (int array[3][6])
{
/* Do stuff to the array */
}
Pointer Arithmetic
• Recall from the previous lectures that we
declare a pointer with a * use an & to get
the "address of" (and convert a variable to a
pointer) and use a * to get the value
"pointed at"
int *p;
int q= 5;
p= &q;
*p= 6;
printf ("q is now %d\n",q);
printf ("p is now %d\n",*p);
Pointer Arithmetic 2
• A pointer is another type of array and we
can mix between them in certain arrays
• If we define an array we can use pointers to
access it
int i[7]; /* An array of 7 ints */
int *j;
/* A pointer to an int*/
j= i;
/* j points at the start of i*/
*j= 3;
/* Same as i[0]= 3 */
j= &i[0]; /* Same as j= i */
j= j+1;
/* Move j to point at i[1]*/
Pointer Arithmetic Test
int i[7];
int *j;
j= i;
/* J points at i[0] */
j= j+1; /* Moves pointer */
*j= 3;
j= i;
/* Same as j= &i[0] */
*j= 10;
j[1]=4;
j= j+5;
j[1]= 5;
i= i+4;
/* This is an error */
j= j+7;
/* J points off end of array */
*j= 4; /* This is an error */
Multiple file programming - why
do it?
• It means that more than one person can work
on a program at once
• It means that when your program gets big, you
don't have to scout through lots of functions
• It means that when you change 1 file of your
huge program, you don't have to change it all
• (But on the other hand, it is more complicated)
Multi-file programming - how
• Create a "header file" (a file ending in .h) which
contains all the prototypes, enums, #defines,
structs, typedefs etc for your code
• Create a number of C source code files - they
should all #include your header file.
• Source files NOT header files contain the
functions.
• One (and only one) of your C source code files
contains main.
• In VC++ you have to add source files to a
workspace to get them to compile properly.
Example structure
pay.cpp
#include "pay.h"
int main()
Get user input
Call appropriate routine
pay.h
Header file enums, structs,
prototypes
fileio.cpp
#include "pay.h"
Read records when called
Writes records
Make backup copies
update.cpp
#include "pay.h"
Type in a new file
for a new lecturer
Change file for
existing lecturer
printout.cpp
#include "pay.h"
Print a cheque run for all lecturers
Print records of individual
lecturers for inspection
Things to note
• If a bit of source uses a function, it must have
access to its prototype
• This is why prototypes are in the header
• Similarly for enums, #defines and struct
definitions.
• Forgetting to #include the header file can seriously
cause problems
• The functions go in the .cpp file not the .h file.
• It is traditional to use "" instead of <> to indicate a
header file you wrote yourself
#include <stdio.h>
#include "myprog.h"
The extern statement
• If we want to use global variables, in multifile programming?
• If we define them in the header then there
will be multiple copies
• If we define them in one file, how will all
files see them?
• The key is to define them in one file and
declare them as "extern" in other files
Extern statement
• Only used with global variables in multi-file
projects.
• Says to compiler "don't worry, this is dealt
with elsewhere"
file1.cpp
int glob_array[100];
file2.cpp
extern int glob_array[100];
Pointers to struct example
typedef struct great_mathematician {
char name[80];
int year_of_birth;
int year_of_death;
char nationality[80];
} MATHEMATICIAN;
.
.
MATHEMATICIAN *cantor;
cantor= (MATHEMATICIAN *)malloc (sizeof (MATHEMATICIAN));
/* Check the allocation here */
Consider the peculiar
(*cantor).year_of_birth= 1845;
syntax here
(*cantor).year_of_death= 1918;
/* Remember to close comments with a diagonal slash */
strcpy ((*cantor).name, "Georg Cantor");
strcpy ((*cantor).nationality, "German");
free(cantor); /* Don't forget to free the memory */
Pointers to struct (2)
• C allows name->bit as a shorthand for
(*name).bit
MATHEMATICIAN *cauchy;
cauchy= (MATHEMATICIAN *)
malloc (sizeof (MATHEMATICIAN));
/* The sizeof Cauchy was quite large */
cauchy->year_of_birth= 1789;
cauchy->year_of_death= 1857;
strcpy (cauchy->name, "Augustin Louis Cauchy");
strcpy (cauchy->nationality, "French");
.
.
This shorthand is always used
.
by C programmers
free(cauchy);
Passing it to a function
int main()
{
MATHEMATICIAN *turing;
turing= (MATHEMATICIAN *)
malloc(sizeof(MATHEMATICIAN));
set_up_turing(turing);
/* Do stuff with the variable */
free(turing);
}
void set_up_turing (MATHEMATICIAN *turing)
{
turing->year_of_birth=1912;
turing->year_of_death=1954;
/* In tragic circumstances */
strcpy (turing->name,"Alan Mathison Turing");
strcpy (turing->nationality,"British");
}
What is the Halting Problem?
• Isn't it annoying when a program goes into
an infinite loop?
• Wouldn't it be great if your compiler could
tell if your program was going to stop
before you ran it?
• Why don't we write a program which will
look at the source code and check if it will
stop or carry on forever.
How could we tell if a program
would stop?
int thiscodestops (char *sourcecode)
/* Given source code return 1 if code
will stop and 0 if it won't */
{
FILE *fptr;
fptr= fopen (sourcecode, "r");
if (fptr == NULL) {
.
.
/* Lots of VERY complex code here */
.
return 1;
}
Then we could run our debugging
script
int main()
{
if (thiscodestops("testfile.c")) {
printf ("Congrats, your code's fine\n");
} else {
printf ("Your code has a bug!\n");
}
return 0;
}
Why can't it work?
Consider this program
doihalt.c
int main()
{
while (thiscodestops("doihalt.c")) {
printf ("Nope, I'm not stopping\n");
}
printf ("Actually I decided to stop!\n");
return 0;
}