Title: Introduction to C Lecture 6: More on Arrays, Pointers and Strings
1Introduction to CLecture 6 More on Arrays,
Pointers and Strings
2Strings
- Strings are 1D arrays of type char. They are
terminated by the null character \0. So, abc is
a character array of size 4. Note that - a is a two-element string, whereas
- a is a character.
- As with other arrays, strings are treated as
pointers - char p abc
- printf(s s\n, p, p1) / abc bc is printed
/ - Note the difference, though, between arrays and
pointers - char p abcdehere, the compiler puts the
string constant abcde\0 somewhere in memory, then
allocates a pointer that points to its first
element. - char s abcde here, s is stored in 6
contiguous bytes and of course you cant make
s point anywhere else other than to the start
of that string.
3Example Word count
- / Count the number of words in a string (from K
P) / - include ltctype.hgt
- Â
- int word_cnt(const char s)
-
- int cnt 0
- Â
- while (s ! \0) / repeat until end of
string / - while (isspace(s)) / skip white space
/ - s
- if (s ! \0) / must have found a
word... / - cnt / count it, then ignore all the
- / rest of the
characs in it / - while (!isspace(s) s ! \0)
- s / skip the word /
-
-
- return cnt
4String-handling functions
- Various string-handling functions are available
in the standard library, if you include
ltstring.hgt - char strcat(char s1, const char s2) takes two
strings and concatenates (joins) them, putting
result in s1. Programmer must ensure s1 points
to adequate space. A pointer to the string s1 is
returned. - int strcmp(const char s1, const char s2)
Returns an integer that is lt, equal or gt 0
depending on whether s1 is lexicographically
(i.e. alphabetically) less than, equal to or
greater than s2. - char strcpy(char s1, const char s2)characters
in s2 are copied into s1 until \0 is moved.
Pointer s1 is returned. - size_t strlen(const char s) returns count of
number of characters before \0. (size_t is an
integral unsigned type usually unsigned int.)
5Writing to strings sprintf, sscanf
- The functions sprintf( ) and sscanf( ) are string
versions of the functions printf( ) and scanf( )
respectively they write to and from strings
instead of to and from the screen/keyboard. - sprintf( ) writes to its first argument, which
should be a pointer to char (string). - sscanf( ) reads from its first argument instead
of from the keyboard. - Â
- char str1 1 2 3 go, str2100, tmp100
- int a, b, c
- Â
- sscanf(str1, ddds, a, b, c, tmp)
- sprintf(str2, s s d d d\n, tmp, tmp, a, b,
c) - printf(s, str2)
- Â
- Here, sscanf( ) takes input from str1 it reads 3
decimals and a string, putting them into a, b, c
and tmp respectively. Then sprintf( ) writes to
str2 or, rather, it writes characters in memory,
beginning at the address str2. Note that str2
already has adequate memory allocated (100 bytes)
to write the whole of the string if this
werent the case there would be an access
violation (and crash). Its output is two strings
and three integers. Using printf( ) to print
str2 to the screen, we see that the output is - Â go go 1 2 3
- Â Note that if we use sscanf( ) to read from the
string again, it starts from the beginning, not
from where it left off.
6Multi-dimensional arrays
- Array elements are stored contiguously, one after
the other. Still, it is sometimes useful to
think of a 2D array as a rectangular collection
of elements. Example - int a35is like a rectangular array of 3
rows and 5 columns. It can also be thought of as
three arrays of five arrays of int. There are
numerous ways to access the elements aij
(ai j) ((a i))j (((a i))
j) (a00 5i j) - The array name a0 by itself is equivalent to
a0 it is a pointer to the array of arrays.
The base address of the array is a00, not a.
The mapping between pointer values and array
indices is called the storage mapping function. - The compiler needs to know sizes in advance,
because it needs to know that a new row starts
every n elements. - Initialization Example for a 3D
array int a223 1, 1, 0, 2, 0, 0
, 3, 0, 0, 4, 4, 0 From here the
compiler can work out that the first size is 2.
It is possible to initialize all array elements
to zero int a223 0
7Example Adding array elements
- int sum (int a7 9 2) / 7x9x2 matrix /
-
- int i, j, k, sum 0
- Â
- for (i 0 i lt 7 i)
- for (j 0 j lt 9 j)
- for (k 0 k lt 2 k)
- sum aijk
- return sum
-
- Â
- Exercise write a short program in which you
initialise a 3x3 matrix (you can use numbers 1-9,
for example), and then call functions that (a)
multiply, (b) add all of the elements together,
and print out the answer. You can if you like
base it on test2Darray.c in /lect7.
8How I did it...
- include ltstdio.hgt
- Â
- int sum(int a33)
- int product(int a33)
- Â
- int main(void)
- int i, j, a33
- Â
- / initialise matrix /
- for (i0 ilt3 i)
- for (j0 jlt3 j)
- aij 3i j 1
-
-
- Â
- / print out sum product /
- printf("Sum of elements d\n",sum(a))
- printf(" Product
d\n",product(a)) - return 0
/-------------------------/ int sum(int
a33) int i, j, sum 0 Â for (i0 ilt3
i) for (j0 jlt 3 j) sum
aij return sum
/------------------------
-/ int product(int a33) int i, j, product
1 Â for (i0 ilt3 i) for (j0 jlt3
j) product aij return
product
9typedef
- typedef allows the creation of new types of
variables in terms of old ones, thus - define N 3 / size of all vectors and
matrices / - Â
- typedef double scalar
- typedef scalar vector N
- typedef scalar matrix N N
- Â Incidentally, we could just as easily have set
- typedef vector matrix N
- Now we can think directly in terms of our
application. We can, for example, write - Â
- scalar dot_product(vector x, vector y)
-
- int i
- scalar sum 0.0
- Â
- for (i 0 i lt N i)
- sum xi yi
- return sum
10Ragged arrays
- A group of words may be stored as
- a two-dimensional array of type char, or
- a one-dimensional array of pointers to char.
Example - Â include ltstdio.hgt
- Â
- int main(void)
-
- char a215 "abc", "a is for apple"
- char p2 "abc", "a is for apple"
- Â
- printf("ccc s s\n", a00, a01,
- a02, a0, a1)
- printf("ccc s s\n", p00, p01,
- p02, p0, p1)
- return 0
11Ragged arrays
a is a 2D array, and its declaration causes space
for 2x15 30 chars to be allocated. Only the
first five elements a, b, c, and \0
are used in a0 the rest are initialized to
zero.
- A group of words may be stored as
- a two-dimensional array of type char, or
- a one-dimensional array of pointers to char.
Example - Â include ltstdio.hgt
- Â
- int main(void)
-
- char a215 "abc", "a is for apple"
- char p2 "abc", "a is for apple"
- Â
- printf("ccc s s\n", a00, a01,
- a02, a0, a1)
- printf("ccc s s\n", p00, p01,
- p02, p0, p1)
- return 0
12Ragged arrays
p is a 1D array of pointers to char. When it is
declared, space for two pointers is allocated.
p0 is initialized to point at abc, a string
requiring space for 5 chars. p1 is initialized
to point at a is for..., which requires space
for 15 chars. Thus, p does its work in less
space than a it is also faster, as no mapping
function is generated.
- A group of words may be stored as
- a two-dimensional array of type char, or
- a one-dimensional array of pointers to char.
Example - Â include ltstdio.hgt
- Â
- int main(void)
-
- char a215 "abc", "a is for apple"
- char p2 "abc", "a is for apple"
- Â
- printf("ccc s s\n", a00, a01,
- a02, a0, a1)
- printf("ccc s s\n", p00, p01,
- p02, p0, p1)
- return 0
An array of pointers whose elements point to
arrays of different sizes is called a ragged
array.
13Arrays of pointers
- Arrays can be of any type, including pointers.
In the next example, we use an array of pointers
to sort a list of words alphabetically. Two
advantages over the more obvious approach of
filling an array of words and sorting it directly
are apparent - It is much faster to move pointers around than to
copy elements of large arrays from place to
place. - It is trivial to have words of considerable
length without allocating huge amounts of memory
in advance. - The code is in lect7/sortwords/
14Example sortwords
- include "sort.h" / includes various
definitions etc / - / from Kelley Pohl /Â
- int main(void)
-
- char wordMAXWORDLEN / work space /
- char wMAXNOWORDS / an array of
pointers / - int n / no. of words to be
sorted / - int i
- Â
- for (i 0 scanf("s", word) 1 i)
- / original code here checks for errors...
then / - wi (char )calloc(strlen(word) 1,
sizeof(char)) - / original code checks memory alloc. is ok,
then / - strcpy(wi, word)
-
- n i
- sort_words(w, n) / sort the words /
- wrt_words(w, n) / write sorted list of
words / - return 0
15Example sortwords
Read in string of characters, one word at a time,
storing each word as character array called
word. (Note because the array is labelled by
its address, we dont need word in scanf
argument)
- include "sort.h" / includes various
definitions etc / - Â
- int main(void)
-
- char wordMAXWORDLEN / work space /
- char wMAXNOWORDS / an array of
pointers / - int n / no. of words to be
sorted / - int i
- Â
- for (i 0 scanf("s", word) 1 i)
- / original code here checks for errors...
then / - wi (char )calloc(strlen(word) 1,
sizeof(char)) - / original code checks memory alloc. is ok,
then / - strcpy(wi, word)
-
- n i
- sort_words(w, n) / sort the words /
- wrt_words(w, n) / write sorted list of
words / - return 0
16Example sortwords
Read in string of characters, one word at a time,
storing each word as character array called
word. (Note because the array is labelled by
its address, we dont need word in scanf
argument)
- include "sort.h" / includes various
definitions etc / - Â
- int main(void)
-
- char wordMAXWORDLEN / work space /
- char wMAXNOWORDS / an array of
pointers / - int n / no. of words to be
sorted / - int i
- Â
- for (i 0 scanf("s", word) 1 i)
- / original code here checks for errors...
then / - wi (char )calloc(strlen(word) 1,
sizeof(char)) - / original code checks memory alloc. is ok,
then / - strcpy(wi, word)
-
- n i
- sort_words(w, n) / sort the words /
- wrt_words(w, n) / write sorted list of
words / - return 0
Keeps going as long as scanf( ) returns 1, i.e.
as long as it is successful in reading in and
converting the word
17Example sortwords
- include "sort.h" / includes various
definitions etc / - Â
- int main(void)
-
- char wordMAXWORDLEN / work space /
- char wMAXNOWORDS / an array of
pointers / - int n / no. of words to be
sorted / - int i
- Â
- for (i 0 scanf("s", word) 1 i)
- / original code here checks for errors...
then / - wi (char )calloc(strlen(word) 1,
sizeof(char)) - / original code checks memory alloc. is ok,
then / - strcpy(wi, word)
-
- n i
- sort_words(w, n) / sort the words /
- wrt_words(w, n) / write sorted list of
words / - return 0
Use calloc to allocate enough memory to store
the character array, and...
18Example sortwords
- include "sort.h" / includes various
definitions etc / - Â
- int main(void)
-
- char wordMAXWORDLEN / work space /
- char wMAXNOWORDS / an array of
pointers / - int n / no. of words to be
sorted / - int i
- Â
- for (i 0 scanf("s", word) 1 i)
- / original code here checks for errors...
then / - wi (char )calloc(strlen(word) 1,
sizeof(char)) - / original code checks memory alloc. is ok,
then / - strcpy(wi, word)
-
- n i
- sort_words(w, n) / sort the words /
- wrt_words(w, n) / write sorted list of
words / - return 0
Use calloc to allocate enough memory to store
the character array, and...
... assign pointer (ith element in array of
pointers) to the address of the memory thus
allocated.
19Example sortwords
- include "sort.h" / includes various
definitions etc / - Â
- int main(void)
-
- char wordMAXWORDLEN / work space /
- char wMAXNOWORDS / an array of
pointers / - int n / no. of words to be
sorted / - int i
- Â
- for (i 0 scanf("s", word) 1 i)
- / original code here checks for errors...
then / - wi (char )calloc(strlen(word) 1,
sizeof(char)) - / original code checks memory alloc. is ok,
then / - strcpy(wi, word)
-
- n i
- sort_words(w, n) / sort the words /
- wrt_words(w, n) / write sorted list of
words / - return 0
Copy the word into the newly-allocated memory
20Example sortwords
- That completes the storage. Now we have
something like - Now lets have a look at the sorting algorithm.
The idea is that, instead of copying the arrays
of words down, we just use the pointers if a
word is out of order relative to another, we
simply swap their pointers. - We send down to the function sort_words the array
W of pointers, and its size.
W
21Example sortwords
- void sort_words(char w, int n)
- / n elements to be sorted / int i, j
for (i 0 i lt n i) for (j 1 i j lt
n j) if (strcmp(wi, wj) gt 0)
swap(wi, wj)
Compare strings at each pair of pointed-to
addresses...
22Example sortwords
- void sort_words(char w, int n)
- / n elements to be sorted / int i, j
for (i 0 i lt n i) for (j 1 i j lt
n j) if (strcmp(wi, wj) gt 0)
swap(wi, wj)
... and if they are out of order, swap the order
of the pointers.
23Example sortwords
- void sort_words(char w, int n)
- / n elements to be sorted / int i, j
for (i 0 i lt n i) for (j 1 i j lt
n j) if (strcmp(wi, wj) gt 0)
swap(wi, wj)
Note that the arguments passed to the swap
function are addresses of pointers to char or,
equivalently, pointers to pointers to char. Hence
they are declared in the swap function as being
of type char .
24Example sortwords
- The result looks like this
- So, as we read through the words pointed to by
the elements of W, we obtain - C
- fun
- in
- is
- programming
- in alphabetical order.
W
25Functions as arguments
- In C, pointers to functions can be passed as
arguments, used in arrays etc. Example suppose
we want to carry out a particular computation, - Â
- on a variety of different functions sin(k), 1/k,
.... Here is how we do it - include "sum_sqr.h"
- double sum_square(double f(double x), int m, int
n) - Â
- int main(void)
-
- printf("s.7f\ns.7f\n",
- " First computation ",
- sum_square(inverse, 1, 10000),
- "Second computation ",
- sum_square(sin, 2, 13))
- return 0
-
- ... and as long as the functions inverse, sin
are defined, they will be called. This is
obviously useful for doing calculations with
generic functions.