300 likes | 390 Views
C. Slides and captured lecture (video and sound) are available at: www.cim.mcgill.ca/~jer/C/. Crash Course -- Review. Last week, we covered: variable declarations and assignments float x;double d = 5;int *p, i, a[100];char s[21]; y = z = 4 + 5; x += 1; ++x; y = x--; formatted I/O
E N D
C • Slides and captured lecture (video and sound) are available at: • www.cim.mcgill.ca/~jer/C/
Crash Course -- Review • Last week, we covered: • variable declarations and assignments • float x;double d = 5;int *p, i, a[100];char s[21]; • y = z = 4 + 5; x += 1; ++x; y = x--; • formatted I/O • int snum; float gr; char mark; char name[80]; • scanf ("%d %f %c %s", &snum, &gr, &mark, name); • printf (”%s\’s mark is %f or %c\n”,name, mark, gr); • loops • while (1) • printf ("hi"); • for (j = 0; j * j <= up; j++) • printf ("%d \n", j * j);
Exercise: Caesar's code • Input: sequence of capital letters • Output: another sequence of capital letters obtained by shifting each letter in the original sequence three places in the alphabet. Note: shifting wraps around. • Example: KENNEDY -> NHQQHGB • recall the use of this handy string function: • int strlen(char *); • example: • n = strlen ("there"); /* n is assigned 5 */
Crash Course -- Part II • Today, we will cover: • functions • types • pointers • arrays • structures • using linked lists • simple debugging
Functions • /* Increment; takes an integer argument and • * returns the argument plus one. • */ • int incr (int i) • { • int j; • j = i + 1; • return j; • } • main () • { • int k, m = 4; • k = incr(m); • printf ("k = %d, m = %d\n", k, m); • } • output: k = 5, m = 4
More about Functions • might have no return type, and no return statement: • void printhi () • { • printf ("hi\n"); • } • parameters are copied and can be modified • int incr (int i) • { • i++; • return i; • } • default (unspecified) return type is int
Variables within Functions • But this does not work: • void no_incr (int i) • { • i++; • } • void main () { • int x = 5; • no_incr(x); • printf ("%d\n", x); • } • beware that modifications are on internal copies of the parameters. • note: void main() since main does not return a value
Exercise • Write a function that checks whether a sentence has 'title case': • Arguments: sentence string • Assume the string consists of letters and blanks only. • Return true iff each word in the sentence starts with a capital letter and continues with lowercase letters.
C Preprocessor Directives • Operations before compilation phase: • include "header" files that contain pre-supplied functions: • #include <string.h> • this line will be substituted by the contents of the file • define symbolic constants: • #define MY_LARGE_NUMBER 12345 • #define MY_NIFTY_STRING "abc"
Make your own booleans • C has boolean operations on int: • == != && || ! • However, C has no boolean type. Make it! • #define boolean_t int; • #define TRUE 1 • #define FALSE 0 • Example: • boolean_t xIsFive, zAsBig, result; • xIsFive = (x == 5); • zAsBig = (z >= x); • if (xIsFive || zAsBig) { • result = TRUE; • }
Naming your own type • A better way: use typedef • typedef int boolean_t; • Syntax: • typedef existing-type new-type; • Comments: • typedef does not create a new type • only creates a new label for an existing type • makes your code easier to read
typedef in action • Example: • typedef char * string_t; • typedef int boolean_t; • string_t msg = "No more room"; • boolean_t full_class; • if (num_students >= MAX_SIZE) • full_class= TRUE;
Pointers • C relies heavily on pointers: • int i; • int *pi; • pi = &i; • *pi = 3; i == *pi 3 pi
Pointers and Arrays • An array name by itself is a pointer to the first element: • int a[100]; • *a = 5; /* same as a[0] = 5 */ • *(a + 3) = 10; /* same as a[3] = 10; */ • /* Note: *a + 3 means something else */ • Strings are arrays of char: • char s[3]; • strcpy (s, "hi"); /* same as following line */ • s[0] = 'h'; s[1] = 'i'; s[2] = '\0';
Call by reference • void incr (int *i); • /* • * increment i by 1 • */ • { • *i = *i + 1; • } • main() • { • int j; • j = 4; • incr (&j); • printf ("j = %d\n", j); • } • &j and i are pointers to the same integer: incr can change the integer (side effect), but not the pointer 4 j i
Dynamic Memory Allocation • Pointer errors can be nasty • void main () { • int *p; • *p = 5; • } • Reserve space for the "pointed to" object: • #include <stdlib.h> • void main () { • int *p; • p = (int *)malloc (sizeof (int)); • *p = 5; • printf ("value at p = %d\n", *p); • free (p); /* must do this yourself! */ • }
Finding Bugs • Insert "print" statements: • printf ("At point A, %s = %d\n", "x", x); • Use a debugger to help you catch bugs in the act: • run step-by-step • insert breakpoints • display variables
Programming Errors I • #include <stdio.h> • void main () • { • int i; • scanf ("%d", &i); • if (i = 0) • puts ("false"); • else • puts ("true"); • } • What’s wrong?
Programming Errors I • #include <stdio.h> • void main () • { • int i; • scanf ("%d", &i); • if (i = 0) • puts ("false"); • else • puts ("true"); • } • The assignment, i = 0, will return a value of 0, so the program will always output "true" • Use: if(0 == i) to be safe
Programming Errors II • #include <stdio.h> • void main () • { • int i; • /* echo one number */ • scanf ("%d", i); • printf ("input = %d\n", i); • } • What’s wrong? • Hint: Segmentation fault / Bus error
Programming Errors II • #include <stdio.h> • void main () • { • int i; • /* echo one number */ • scanf ("%d", i); • printf ("input = %d\n", i); • } • Must provide the address of an integer if the function is going to assign a value to it.
Programming Errors III • #include <stdio.h> • void main () • { • int *pc; • scanf ("%d", pc); • printf ("%d\n", pc); • } • What’s wrong?
Programming Errors III • #include <stdio.h> • void main () • { • int *pc; • scanf ("%d", pc); • printf ("%d\n", pc); • } • *pc is an uninitialized pointer so results are unpredictable --> use malloc
Programming Errors IV • #include <stdlib.h> • void main () • { • double *p; • p = malloc (sizeof (double *)); • } • What’s wrong?
Programming Errors IV • #include <stdlib.h> • void main () • { • double *p; • p = malloc (sizeof (double *)); • } • Insufficient memory allocated for a double (typically, 8 bytes) • Use malloc (sizeof (double));
Programming Errors V • #include <stdio.h> • void main () • { • char s[] = "hi"; • if (s == "hi") • puts ("Strings are equal"); • else • puts ("Strings are not equal"); • } • What happens?
Programming Errors V • #include <stdio.h> • main () • { • char s[] = "hi"; • if (s == "hi") • puts ("Strings are equal"); • else • puts ("Strings are not equal"); • } • Use strcmp() to compare strings, otherwise you are comparing addresses.
Structures • Use struct to create or define a new type: • struct str_data { • char *string; • int length; • }; • struct str_data s1, s2; • Syntax • struct structure_name { • type1 member1; • type2 member2; • … • }; • A member of a structure is referred to by: • structure_name.member
Structures, cont. • Example: • struct str_data { • char *string; • int length; • }; • struct str_data s1, s2; • s1.string = (char *) malloc(80); • strcpy (s1.string, "How now brown cow."); • s1.length = strlen(s1.string); • s2 = s1; /* can copy structures, pass to fcns */
Arrays of Structures • Example: • #define MAX_STUDENT 100 • typedef struct { /* define a new type */ • char name[80]; • int name_len; • int student_number; • } student_t; • /* create list of elements of type student_t */ • student_t class[MAX_STUDENT]; • for (i = 0; i < MAX_STUDENT; i++) { • gets(class[i].name); • class[i].name_len = strlen(class[i].name); • }