560 likes | 599 Views
More Pointers and Arrays. Kernighan/Ritchie: Kelley/Pohl:. Chapter 5 Chapter 6. Lecture Overview. Strings and characters String functions in the standard library sizeof Revisited Multidimensional arrays Pointers to pointers and pointer arrays Pointers to functions. Strings.
E N D
More Pointers and Arrays Kernighan/Ritchie: Kelley/Pohl: Chapter 5 Chapter 6
Lecture Overview • Strings and characters • String functions in the standard library • sizeof Revisited • Multidimensional arrays • Pointers to pointers and pointer arrays • Pointers to functions
Strings • As we have seen before, strings in C are one-dimensional arrays of type char • By convention, strings end with a '\0', thus memory allocated to hold a string should include one additional space • A string constant is treated by the compiler as a pointer to the string's base address
Strings • p can be used like any other pointer: • To further emphasize this point: • Note that such code should never be usedin any real program! char *p = "abc"; printf ("%s %s\n", p, p + 1); abc bc printf ("%c %c\n", "abc"[1], *("abc" + 2)); b c
The Character Type Library • The library ctype.h provides macros to check whether a character belongs to a certain character class • Some examples: • isspace– Checks for white-space • isalpha– Checks for an alphabetic character • isdigit– Checks for a digit (0 through 9) • islower– Checks for a lower-case character
Example –Counting Words in a String #include <ctype.h> int count_words (char *s) { int cnt = 0; while (*s != '\0') { while (isspace (*s)) /* skip white space */ s++; if (*s != '\0') { /* found a word */ cnt++; while (!isspace (*s) && *s != '\0') s++; /* skip the word */ } } return cnt; }
Lecture Overview • Strings and characters • String functions in the standard library • sizeof Revisited • Multidimensional arrays • Pointers to pointers and pointer arrays • Pointers to functions
String Functions in the Standard C Library • The standard C library provides several functions for handling strings • The function prototypes for string handling functions are given in the standard header file string.h • Functions are available for comparing, copying or concatenating strings
String Functions in the Standard Library • All string functions take arguments and return values of type char * • Some of the parameters also include the const qualifier, which means: • The characters pointed to cannot be changed • The pointer itself can be changed • Allocating enough memory to store the results is the responsibility of the caller
String Concatenation • This function takes two strings as arguments, concatenates them, and puts the result in s1 • The programmer must ensure that s1 points to enough space to hold the result • The string s1 is returned char *strcat (char *s1, const char *s2);
String Comparison • The strings are passed as arguments, and neither one is changed by the function • An integer is returned that is less than, equal to, or greater than zero, depending on whether s1 is lexicographically less than, equal to, or greater than s2 int strcmp (const char *s1, const char *s2);
String Copy • The string s2 is copied into s1 until (and including) the character '\0' • Whatever exists in s1 is overwritten • It is assumed that s1 has enough space to hold the result • The value s1 is returned char *strcpy (char *s1, const char *s2);
String Copy • The strdup() function returns a pointer to a new string which is a duplicate of the input string s • Memory for the new string is obtained with malloc(), and can be freed with free() char *strdup (const char *s);
String Length • This function simply counts the number of characters in the string • The character '\0' is not included in the count • Note that in C the size of the string is not kept, and must be recomputed every time size_t strlen (const char *s);
Finding a Character within a String • Looks for the first occurrence of the character c inside the string s • Returns a pointer to the position in the string where c was found • Returns NULL if c was not found char *strchr (const char *s, int c);
Finding a Sub-string within a String • Looks for the first occurrence of the sub-string s2 inside the string s1 • Returns a pointer to the beginning of s2 within s1 • Returns NULL if s2 was not found char *strstr (const char *s1, const char *s2);
Example – String Functions #include <string.h> int main() { char *question = "Do you want to understand?"; char answer[80], *q_mark, *you; strcpy (answer, "If "); you = strstr (question, "you"); strcat (answer, you); q_mark = strchr (answer, '?'); strcpy (q_mark, " something,\ntry to change it."); printf ("%s\n", answer); } If you want to understand something, try to change it.
Lecture Overview • Strings and characters • String functions in the standard library • sizeof Revisited • Multidimensional arrays • Pointers to pointers and pointer arrays • Pointers to functions
sizeof Revisited • As we have seen, the sizeof operator can be applied to variables or to types • sizeof can also be applied to arrays • In this case, it returns the size of the memory occupied by the complete array • This only works for static arrays – will not work for pointers
sizeof String – Example #include <stdio.h> int main() { char *question = "Do you want to understand?"; char answer[80]; printf ("question size: %d\n", sizeof (question)); printf ("answer size: %d\n", sizeof (answer)); return 0; } Size of question: 4 Size of answer: 80
sizeof Example Explained • sizeof is a compile-time operator • It cannot know in advance where question will point to during run-time • answer is an array, which is essentiallya constant pointer to static memory • Therefore, answer will always point to the same 80 character memory block
sizeof Array – Example 1 int main() { int a[] = {12, 32, 434, 43, 26, 873, 43}; int array_size = sizeof (a) / sizeof (int); int i; printf ("Size of a: %d\n", sizeof (a)); for (i = 0; i < array_size; i++) printf ("%d ", a[i]); printf ("\n"); } Size of a: 28 12 32 434 43 26 873 43
Wrong! sizeof Array – Example 2 int main() { double a[] = {12, 32, 434, 43, 26, 873, 43}; int array_size = sizeof (a) / sizeof (int); int i; printf ("Size of a: %d\n", sizeof (a)); for (i = 0; i < array_size; i++) printf ("%.0f ", a[i]); printf ("\n"); } Size of a: 56 12 32 434 43 26 873 43 0 -1 0 -1 0 0 -1
sizeof Array – Example 3 int main() { double a[] = {12, 32, 434, 43, 26, 873, 43}; int array_size = sizeof (a) / sizeof (a[0]); int i; printf ("Size of a: %d\n", sizeof (a)); for (i = 0; i < array_size; i++) printf ("%.0f ", a[i]); printf ("\n"); } Size of a: 56 12 32 434 43 26 873 43
Lecture Overview • Strings and characters • String functions in the standard library • sizeof Revisited • Multidimensional arrays • Pointers to pointers and pointer arrays • Pointers to functions
Multidimensional Arrays • The C language allows arrays of any type, including arrays of arrays • With two bracket pairs, we can obtain a two-dimensional array • This idea can be iterated to obtain arrays of higher dimension int a[100]; /* a one-demensional array */ int b[2][7]; /* a two-dimensional array */ int c[5][3][2]; /* a three-dimensional array */
Two-dimensional Arrays • Elements of a two dimensional array are stored contiguously one after the other • However, it is convenient to think of the array as having rows and columns • To define an array with 3 rows and 5 columns: int a[3][5];
Two-dimensional Array Initialization • Like simple arrays, multidimensional arrays can be initialized with a list of literals: int main() { int array[3][5] = { { 1, 3, 5, 7, 9 }, { 11, 13, 15, 17, 19 }, { 21, 23, 25, 27, 29 } }; printf ("sum: %d\n", sum (array)); return 0; } sum: 225
Two-dimensional Arrays – Formal Parameter Declaration • The compiler only needs to know the number of elements in each row, so the parameter could be defined as either of: int sum (int a[3][5]) { int i, j, sum = 0; for (i = 0; i < 3; ++i) for (j = 0; j < 5; ++j) sum += a[i][j]; return sum; } int a[3][5] int a[][5] int (*a)[5]
Two-dimensional Array Access • To access an element in the array, we use: • The following expressions are equivalent: a[i][j] *(a[i] + j) (*(a + i))[j] *((*(a + i)) + j) *(&a[0][0] + 5*i + j)
Two-dimensional Array Access – Example a[0][0] (*(a + 1))[4] a[1][2] *a[1] *(a[2] + 1) *(a[0] + 12) *(&a[0][0] + 5*2 + 4)
Two-dimensional Array Access – Example • a is an array of size 3 • Each element of a is an array of size 5 • For example, a[1] is an array of 5 integers • a[1]+2 moves two integers (or 8 bytes) forward – the result is an array of integers • a+2 moves 10 integers forward, since each element of a is an array of 5 integers
Lecture Overview • Strings and characters • String functions in the standard library • sizeof Revisited • Multidimensional arrays • Pointers to pointers and pointer arrays • Pointers to functions
Pointers to Pointers • In C, pointers are just another type of variables • Therefore, they can be stored in arrays,or pointed to by other pointers • A pointer which points to another pointer will have a special type, such as: int **ppi;
Pointers to Pointers – Example • When we wanted to swap between two variables, we used pointers • Similarly, when we want to swap between pointers, we will need pointers to pointers: void swap_char_ptrs (char **ppx, char **ppy) { char *tmp; tmp = *ppx; *ppx = *ppy; *ppy = tmp; }
Pointers to Pointers – Example int main() { char *first = "Hello, world!\n"; char *second = "Goodbye, world...\n"; swap_char_ptrs (&first, &second); printf (first); printf (second); return 0; } Goodbye, world... Hello, world!
Pointer Arrays • The array used in the sum example could have been defined as a pointer array: b[0] b[1] b[2]
Pointer Arrays Compared to Multidimensional Arrays • The syntax of C may cause some confusion between a two-dimensional array and an array of pointers • Both a[1][2] and b[1][2] are syntactically legal references to a memory location of type int int a[3][5]; int *b[3];
Pointer Arrays Compared to Multidimensional Arrays • The definition of a allocates 15 int-sized memory locations • The space of any unused array slots is wasted • The definition of b only allocates 3 pointers, which should be initialized • The space allocated for the pointers themselves is wasted, but the (larger) space for array slots can be accurately allocated
Ragged Arrays • A ragged array is an array of pointers used as a two-dimensional array • Requires allocating memory for each row • Advantages: • Can save space when row sizes differ • Makes it possible to operate on complete rows, and not only on individual cells
Ragged Arrays – Example int main() { char in_word[MAX_WORD_LEN]; char *words[MAX_WORDS]; int len, cnt = 0; while (scanf ("%s", in_word) == 1) { len = strlen (in_word); words[cnt] = malloc ((len+1) * sizeof(char)); strcpy (words[cnt], in_word); cnt++; } sort_words (words, cnt); print_words (words, cnt); }
Ragged Arrays – Example void sort_words (char *w[], int n) { int i, j; for (i = 0; i < n; i++) for (j = i + 1; j < n; j++) if (strcmp (w[i], w[j]) > 0) swap_char_ptrs (&w[i], &w[j]); } void print_words (char *w[], int n) { int i; for (i = 0; i < n; i++) printf ("%s ", w[i]); printf ("\n"); }
Initialization of Pointer Arrays • Pointer arrays may be initialized not only dynamically, but also statically: • The syntax is similar to the initializationof a two-dimensional array: char *words[] = { "this", "is", "a", "list", "of", "words" }; char words[][10] = { "this", "is", "a", "list", "of", "words" };
Initialization of Pointer Arrays – Example • We could have written our word sorting program to work on a static list of words: int main() { char *words[] = { "this", "is", "a", "list", "of", "words" }; int cnt = sizeof (words) / sizeof (char *); sort_words (words, cnt); print_words (words, cnt); } a is list of this words
Lecture Overview • Strings and characters • String functions in the standard library • sizeof Revisited • Multidimensional arrays • Pointers to pointers and pointer arrays • Pointers to functions
Pointers to Functions • In C, pointers can point to anything, including functions • Pointers to functions can be used just like any other pointers. They can be: • Used in assignments • Placed in arrays • Passed as arguments • Returned by functions
Pointers to Functions • To define a variable of type pointer to function, we use a definition such as: • This sets up f_ptr as a pointer to a function that accepts no arguments, and returns int • The parenthesis in the definition are mandatory int (*f_ptr)();
Pointers to Functions – Example #include <math.h> #define PI 3.14159265358979323846 double my_tan (double x); int main() { double x = PI / 4; double (*f)(double x); f = sin; printf ("f(x): %f\n", (*f)(x)); f = cos; printf ("f(x): %f\n", (*f)(x)); f = my_tan; printf ("f(x): %f\n", (*f)(x)); } ...
Pointers to Functions – Example • The printf lines are similar, but the result is different each time, because the value of f changes ... double my_tan (double x) { return sin(x) / cos (x); } f(x): 0.707107 f(x): 0.707107 f(x): 1.000000