190 likes | 350 Views
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.
E N D
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.h Header file - enums, structs, prototypes update.cpp #include "pay.h" Type in a new file for a new lecturer Change file for existing lecturer pay.cpp #include "pay.h" int main() Get user input Call appropriate routine printout.cpp #include "pay.h" Print a cheque run for all lecturers Print records of individual lecturers for inspection fileio.cpp #include "pay.h" Read records when called Writes records Make backup copies
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 multi-file 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 */ (*cantor).year_of_birth= 1845; (*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 */ Consider the peculiar syntax here
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"); . . . free(cauchy); This shorthand is always used by C programmers
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; }