Arrays, Pointers, and Stringdsiva.weebly.com/uploads/5/2/7/8/5278587/chap07.pdf · Pointer...

Preview:

Citation preview

Arrays, Pointers, and Arrays, Pointers, and StringStringJun Ni, Ph.D.M.E.

Department of Computer ScienceThe University of Iowa

jun-ni@uiowa.edu

http://www.cs.uiowa.edu/~jni/

OutlineOutlineOne-dimensional ArraysPointersCall-by-ReferenceThe Relationship between Arrays and PointersPointer Arithmetic and Element SizeArray as Function ArgumentsExampleDynamic Memory Allocation with calloc() and malloc()

Outline (continued)Outline (continued)

ExampleStringsString-Handling Functions in the Standard LibraryMultidimensional ArraysArrays of PointersArguments to main()

Outline (continued)Outline (continued)

Ragged ArraysFunctions as ArgumentsExampleArrays of Pointers to FunctionThe Type Qualifiers const and volatile

OneOne--dimensional Arraysdimensional Arrays

Array is a date type, which can be used for a large number of homogeneous values.Array and pointer are close related concepts.

OneOne--dimensional Arraysdimensional Arrays

In order to store homogeneous data, we need have a sequential storage. It is used to store same data type values shared with the same variable name.instead of using

int grade0, grade1, grade2, …

int grade[3];

OneOne--dimensional Arraysdimensional Arrays

For one dimensional array, we need to specify one constant integral for the size (total number of elements)

int a[size];

The size should be specified before declaration.

#define N 1000

int a[N]; space for a[0], a[1], …a[N-1] is allocated.

OneOne--dimensional Arraysdimensional Arrays

The element of an array can be accessed using subscript variable

Arrays can be initialized when declaration.There are several way to initialize an array.

for (i=0; i<N; i++)sum+=a[i];

OneOne--dimensional Arraysdimensional Arrays

Both size and initialized values are provided

Initialize a constant value

float f[5]={0.0, 1.0, 2.0, 3.0, 4.0}

int a[]={0};

OneOne--dimensional Arraysdimensional Arrays

Only initialized values are provided

char array can use alternative initialization, besides of the regular initialization methods

float f[]={0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0}

char s[] "abcd";

char s[] ={ 'a', ;b', 'c', 'd'', '\0'};

OneOne--dimensional Arraysdimensional Arrays

Array's subscript or index can be an integral expression. The subscript is used to referr each element. It starts with 0!

PointersPointers

Each variable is stored in a certain number of bytes at a particular memory location.Pointer is introduced to access memory and manipulate addresses and the corresponding value stored.Access address or location

if v is a variable, &v is the location of the variable in memory

PointersPointers

Pointer variables can be declared in programs and then used to take addresses as valueDifferent pointer variables of data type are used take the different variables' addresses.

int *p; declare a pointer variable of int data-type.It can be used to take the address of an int variables.

PointersPointers

float *p; declare a pointer variable of float data-type.It can be used to take the address of a float variables. It can not be used to take int variable's address

PointersPointers

Initialization of pointer variable

p=0;p=NULL;p=&i;p=(int *) 1776 /* take the address of absolute address in

memory) */

pointer variable of int type is referring to int variable i, or is pointing to the variable i

PointersPointers

Indirection or dereference using unary operator *

*p is the value of variable of which p is pointing to.

*p is the value of variable to which p is pointing to

if we have p=&i,

*p i

#include <stdio.h>

int main(void){

int i = 7, *p;

p = &i;printf("%s%d\n%s%p\n",

" Value of i: ", *p,"Location of i: ", p);

return 0;}

Example

int a=1, b=2, *p;

p=&a;

b=*p; b=a;

Value of i: 7Location of i: 7bff07c0

PointersPointers

A pointer can be initialized in a declaration.

int i, *p=&i;

int i=3, j=5, *p=&i, *q=&j, *r;double x;

p==&i p==(&i) 1**&p *(*&p) 3r=&x r=(&x) illegal7**p/*q+7 (((7*(*p)))/(*q)+7 11*(r=&j)*=*p (*(r=(&j)))*=(*p) 15

PointersPointers

Explanation: **&p *(*&p)

&p is the address of p,

*(&p) p (the value associated with the address of p

*p value if i

PointersPointers

generic pointer void *

int i, *p=&i;

int *p;float *q;void *r;legal illegalp=0; p=1;p=(int *) 1; v=1;p=v=q; p=q;p=(int *) q;

PointersPointers

do not point at constants, except 0;&3

do not point at ordinary expression&(k+99)

do not point at register variableregister v;&v

CallCall--byby--ReferenceReference

Passing the addresses of variables from the calling function to the called function

#include <stdio.h>

void swap(int *, int *);int main(void){

int i = 3, j = 5;

swap(&i, &j);/* 5 3 is printed */printf("%d %d\n", i, j); return 0;

}

void swap(int *p, int *q){

int tmp;

tmp = *p;*p = *q;*q = tmp;

}

5 3

The Relationship Between The Relationship Between Arrays and PointersArrays and Pointers

Array name itself is an address of the first element. It is fixed. However, array can use pointer notation.Pointer can points different address of variable of the same type.Pointer can use array notation

array a[i] *(a+i)pointer p[i] *(p+1)

array notation pointer notation

#define N 100int a[N], i, *p, sum=0;

p=a; p=&a[0];

p=a+1 p=&a[1];

for (i=0;i<N;i++)sum+=a[i];

for (p=a;p<&a[N]; p++)sum+=*p;

for (i=0;i<N;i++)sum+=*(a+i);

p=a;for (i=0;i<N;i++)

sum+=p[i];

illegal: (since a is a constant or static pointer)

a=p; a++ a+=2; &a

Pointer Arithmetic and Pointer Arithmetic and Element SizeElement Size

Pointer arithmetic is one of the power features of C. If the variable p is a pointer to a particular type, then the expression p+1 yields the correct machine address for storing or accessing the next variable of that type. p+i, ++p, and p+=i all make sense.pointer expression and arithmetic expression have a difference

double a[2], *p, *q;

p=a;q=p+1;printf("%d\n", q-p); output is 1printf("%d\n", (int) q-(int) p)); output is 8, since double

has 8 byte

I should say the unit is different.m The different in terms of array element is 1, but the different in memory location is 8.

Arrays as Function ArgumentsArrays as Function Arguments

If you want to pass whole array to function, you actually pass the value of address to the called function.

double sum(double a[], int n){int i;double sum=0.0;

for (i=0;i<n;++i)sum+=a[i];

return sum;}

double sum(double *a, int n){int i;double sum=0.0;

for (i=0;i<n;++i)sum+=a[i];

return sum;}

#define N 10

double sum(double [], int);

int main(){

int i;double v[N];for (i=0;i<N;++i)v[i]=(double) i;

printf("%lf\n", sum(v,N));printf("%lf\n", sum(v,8));printf("%lf\n", sum(&v[5],3));printf("%lf\n", sum(v+3,3));printf("%lf\n", sum(v+3,2*2+1));

}

double sum(double a[], int n){int i;double summation=0.0;

for (i=0;i<n;++i)summation+=a[i];

return summation;}

45.00000028.00000018.00000012.00000025.000000

in main(), we have

double v[100]={3.0};

sum(v,100); return v[0]+v[1]+…v[99]sum(v,88); return v[0]+v[1]+…v[87]sum(&v[7], k-7); return v[7]+v[8]+…v[k-1]sum(v+7,2*k); return v[7]+v[8]+…v[2*k+6]

Example: Bubble SortExample: Bubble Sortvoid swap(int *p, int *q){

int tmp;

tmp = *p;*p = *q;*q = tmp;

}

/* n is the size of a[] */void bubble(int a[], int n) {

int i, j;void swap(int *, int *);

for (i = 0; i < n - 1; ++i)for (j = n - 1; j > i; --j)

if (a[j-1] > a[j])swap(&a[j-1], &a[j]);

/* or swap (a+(j-1), a+j) */}

Dynamic Memory Allocation Dynamic Memory Allocation with with calloccalloc() and () and mallocmalloc()()

These functions in standard library can be used to reserve memory allocation dynamically during execution. The function prototypes of these two functions are in stdlib.hcalloc stands for contiguous allocation while malloc stands for memory allocation

Dynamic Memory Allocation Dynamic Memory Allocation with with calloccalloc() and () and mallocmalloc()()

calloc(n, elementSize) return void *

number of elements size of data type

a=(int *) calloc(n, size(int); it allocates contiguous space in memory for an array of n elements, with each element having elementSize bytes; It initializes each elements type casting to int *

Dynamic Memory Allocation Dynamic Memory Allocation with with calloccalloc() and () and mallocmalloc()()

malloc(n*elementSize) return void *

number of elements size of data type

a=(int *) malloc(n*size(int); it allocates contiguous space in memory for an array of n elements, with each element having elementSize bytes; It doesn't initialize each element; efficient.

type casting to int *

Dynamic Memory Allocation Dynamic Memory Allocation with with calloccalloc() and () and mallocmalloc()()

free the reserved space using

free(prt);

#include <stdio.h>#include <stdlib.h>#include <time.h>

void fill_array(int *a, int n);int sum_array(int *a, int n);void wrt_array(int *a, int n);

#include "array.h"

void fill_array(int *a, int n){

int i;

for (i = 0; i < n; ++i)a[i] = rand() % 19 - 9;

}int sum_array(int *a, int n){

int i, sum = 0;

for (i = 0; i < n; ++i)sum += a[i];

return sum;}

void wrt_array(int *a, int n){

int i;

printf("a = [");for (i = 0; i < n; ++i)

printf("%d%s", a[i], ((i < n - 1) ? ", " : "]\n"));}

#include "array.h"

int main(void){

int *a, n;

srand(time(NULL)); /* seed the random number generator */printf("\n%s\n",

"This program does the following repeatedly:\n""\n"" 1 create space for an array of size n\n"" 2 fill the array with randomly distributed digits\n"" 3 print the array and the sum of its element\n"" 4 release the space\n");

for ( ; ; ) {printf("Input n: ");

if (scanf("%d", &n) != 1 || n < 1)break;

putchar('\n');a = calloc(n, sizeof(int)); /* allocate space for a[] */fill_array(a, n);wrt_array(a, n);printf("sum = %d\n\n", sum_array(a, n));free(a);

}printf("\nBye!\n\n");return 0;

}

This program does the following repeatedly:

1 create space for an array of size n2 fill the array with randomly distributed digits3 print the array and the sum of its element4 release the space

Input n: 10

a = [7, -3, -8, 8, -5, -3, -5, 5, 0, -6]sum = -10

Input n: -1

Bye!

Dynamic Memory Allocation Dynamic Memory Allocation with with calloccalloc() and () and mallocmalloc()()

Offsetting the PointerSince array index starts with 0.If we want to shift 1, we can use offsetting the pointer, example

int n;double *a;…a=(double *) calloc(n+1,sizeof(double));

Dynamic Memory Allocation Dynamic Memory Allocation with with calloccalloc() and () and mallocmalloc()()

Alternatively, we can use pointer arithmetic

int n;double *a;…a=(double *) calloc(n,sizeof(double));--a; /* this way we can use a[1]. a[2], …

in order to free it, we need free(a=1);

Example: Merge and Merge Example: Merge and Merge SortSort

Merge arraysSort again

merge.c file

/*// Merge a[] of size m and b[] of size n into c[].*/

#include "mergesort.h"

void merge(int a[], int b[], int c[], int m, int n){

int i = 0, j = 0, k = 0;

while (i < m && j < n)if (a[i] < b[j])

c[k++] = a[i++];

elsec[k++] = b[j++];

while (i < m) /* pick up any remainder */c[k++] = a[i++];

while (j < n)c[k++] = b[j++];

}

mergesort.h file

#include <stdio.h>#include <stdlib.h>

#define KEYSIZE 16

void merge(int a[], int b[], int c[], int m, int n);void mergesort(int key[], int n);

/* mergesort.c// Mergesort: Use merge() to sort an array of size n.*/#include "mergesort.h"

void merge(int *, int *, int *, int, int);

void mergesort(int key[], int n){

int j, k, m, *w;

for (m = 1; m < n; m *= 2);

if (m != n) {printf("ERROR: Size of the array is not a power of 2 - bye!\n");exit(1);

}

w = calloc(n, sizeof(int)); /* allocate workspace */for (k = 1; k < n; k *= 2) {

for (j = 0; j < n - k; j += 2 * k)merge(key + j, key + j + k, w + j, k, k); /* merge into w */

for (j = 0; j < n; ++j)key[j] = w[j]; /* write w back into key */

}free(w); /* free the workspace */

}

#include "mergesort.h"

void wrt(int key[], int sz) {

int i;for (i=0;i<sz;++i)printf("%4d%s", key[i], ((i<sz-1)?"":"\n"));

}

wrt.c

#include "mergesort.h"

int main(void){

int sz, key[] = { 4, 3, 1, 67, 55, 8, 0, 4,-5, 37, 7, 4, 2, 9, 1, -1 };

sz=sizeof(key)/ sizeof(int);printf("Before mergesort:\n");wrt(key,sz);mergesort(key, KEYSIZE);printf("After mergesort:\n");wrt(key,sz);return 0;

}

main.c

Before mergesort:4 3 1 67 55 8 0 4 -5 37 7 4 2 9 1 -1

After mergesort:-5 -1 0 1 1 2 3 4 4 4 7 8 9 37 55 67

StringsStrings

Strings are one-dimensional arrays of type charString is terminated by char '\0' or null char.string constants are written between double quotes, "a" and 'a' is a string and a char. They are differentstring constant like an array and is treated by a pointer

StringsStrings

for example:

a constant string can be treated as a pointer

char *p="abc";printf("%s %s\n", p,p+1);

"abc"[1] *("abc"+2)

StringsStrings

Use pointer to access a string or use a char array to deal with a string

char *p ="abcd", s[]={'a','b','c','d'};

a b c b d \0p

a b c d \0

s

char *s;int nfrogs;..... /* get nfrogs from somewhere */s = (nfrogs == 1) ? "" : "s";printf("We found %d frog%s in the pond.\n", nfrogs, s);

/* Count the number of words in a string. */#include <ctype.h>int word_cnt(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;

}

StringString--Handling Functions in Handling Functions in the Standard Librarythe Standard Library

There are many built-in functions in stand library which can handle string manipulationconcatenates two string

char *strcat (char *s1, const char *s2);

append s2 to s1

StringString--Handling Functions in Handling Functions in the Standard Librarythe Standard Library

compare two string

int strcmp (const char *s1, const char *s2);

compare s1 and S2; If the return result is <, =, >0, indicates s1 is less then, equal, greater thans2 lexicographically.

StringString--Handling Functions in Handling Functions in the Standard Librarythe Standard Library

copy a string to another

account the number of characters before null char

char * strcpy (char *s1, const char *s2);

copy characters of s2 into s1

size_t strlen(const *s);

unsigned strlen(const char *s){

register int n;

for (n = 0; *s != '\0'; ++s)++n;

return n;}

char *strcpy(char *s1, register const char *s2) {register char *p=s1;while(*p++=*s2+=);return s1;}

char *strcat(char *s1, const char *s2){

register char *p = s1;

while (*p)++p;

while (*p++ = *s2++);

return s1;}

Example:

char s1[]="beatiful big sky country", s2="how now brown cow";

strlen(s1) 25strlen(s2+8) 9strcmp(s1,s2) negative number

Multidimensional ArraysMultidimensional Arrays

Array of array

Two-dimensional array

int a[1000];int b[2][7];int c[5][3][2];

int a[2][3];

row1 a[0][0] a[0][1] a[0][2]row2 a[1][0] a[1][1] a[1[][2]

Multidimensional ArraysMultidimensional Arrays

Tow-dimensional arraysa[i][j]

*(a[i]+j)(**a+i))[j]*((*a+i))+j)*(&a[0][0]+3*i+j

int a[2][3];

row1 a[0][0] a[0][1] a[0][2]row2 a[1][0] a[1][1] a[1[][2]

Multidimensional ArraysMultidimensional ArraysThe storage mapping function: mapping between pointer values and array indices is called storage mapping function

int a[3][5];a[i][j] *(&a[0][0]+5*i+j)

Therefore, You can use a one-dimensional array to replace a two-dimensional array. int i, j, b[15], jSize=5, iSize=3; /* iSize*jSize=15)*/for (j=0;j<jSize;j++)

for (i=0;i<iSize;i++)*(b+jSize*i+j)=3;

#include<stdio.h>#define BSIZE 15#define ROWSIZE 3#define COLUMNSIZE 5

void print2Darray(int [], int, int, int);

int main(){/* jSize is the column size, jSize is row size */

int i, j, b[BSIZE]; for (i=0;i<ROWSIZE;i++)for (j=0;j<COLUMNSIZE;j++) *(b+COLUMNSIZE*i+j)=i;

print2Darray(b,BSIZE,ROWSIZE, COLUMNSIZE);return 0;

}

void print2Darray(int x[], int n, int isize, int jsize){

int i,j;for (i=0;i<isize;i++){for (j=0;j<jsize;j++){printf("%d ",*(x+jsize*i+j));

}printf("\n");}

}

Multidimensional ArraysMultidimensional Arrays

Formal Parameter Declarations

int a[][5] int a[3][5] int (*a)[5]

int sum(int a[][5]){

int i, j, sum = 0;for (i = 0; i < 3; ++i)

for (j = 0; j < 5; ++j)sum += a[i][j];

return sum;}

Multidimensional ArraysMultidimensional Arrays

Formal Parameter Declarations

header of the function definition can have the following parameter declarations

int b[] int b[3] int *b

char *argv[] char *argv[3] char **argv

Multidimensional ArraysMultidimensional Arrays

Three-dimensional Arrays

int sum(int a[][9][2]){

int i, j, k, sum = 0;

for (i = 0; i < 7; ++i)for (j = 0; j < 9; ++j)

for (k = 0; k < 2; ++k)sum += a[i][j][k];

return sum;}

int a[7][9][2];

mapping function can be

*(a[0][0][0]+9*2*i+2*j+k)

Multidimensional ArraysMultidimensional ArraysInitialization of multidimensional arrays

int a[2][3]={1,2,3,4,5,6};int a[2][3]={{1,2,3},{4,5,6}};int a[][3]={{1,2,3},{4,5,6}};int a[2][2][3]={{{1,1,0}, {2,0,0}},{{3,0,0}, {4,4,0}}};int a[][2][3]={{{1,1},{2}},{{3},{4,4}}};int a[2][2][3]={0];

Multidimensional ArraysMultidimensional ArraysThe Use of typedef– self-defined equivalent data-type

#define N 3

typerdef double scalar;typedef scalar vector[N];

typedef scalar matrix[N][N];ortypedef vector matrix[N];

void add(vector x, vector y, vector z){int i;for (i=0;i<N;++i)

x[i]=y[i]+z[i];}

scalar dot_product(vector x, vector y){int i;scalar sum=0.0;for (i=0;i<N;++i)sum+=x[i]*y[i];

return sum;}

void multiply(matrix a, matrix b, matrix c);{int i,j,k;for (i=0;i<N;i++){for (j=0;j<N;j++){a[i][j]=0.0;for (k=0;k<N;k++)

a[i][j]+=b[i][k](c[k][j];}

}}

Arrays of PointersArrays of Pointerssort of words in a file sort.h

#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAXWORD 50 /* max word size */#define N 300 /* array size of w[] */

void error_exit_calloc_failed(void);void error_exit_too_many_words(void);void error_exit_word_too_long(void);void sort_words(char *w[], int n);void swap(char **p, char **q);void wrt_words(char *w[], int n);

/* Sort words lexicographically. */

#include "sort.h"

int main(void){

char word[MAXWORD]; /* work space */char *w[N]; /* an array of pointers */int n; /* number of words to be sorted */int i;

main.c

for (i = 0; scanf("%s", word) == 1; ++i) {if (i >= N)

error_exit_too_many_words();if (strlen(word) >= MAXWORD)

error_exit_word_too_long();w[i] = calloc(strlen(word) + 1, sizeof(char));if (w[i] == NULL)

error_exit_calloc_failed();strcpy(w[i], word);

}n = i;sort_words(w, n); /* sort the words */wrt_words(w, n); /* write sorted list of words */return 0;

}

#include "sort.h"

void wrt_words(char *w[], int n){

int i;

for (i = 0; i < n; ++i)printf("%s\n", w[i]);

}

wrt.c

#include "sort.h"

void error_exit_calloc_failed(void){

printf("%s","ERROR: The call to calloc() failed to\n"" allocate the requested memory - bye!\n");

exit(1);}

void error_exit_too_many_words(void){

printf("ERROR: At most %d words can be sorted - bye!\n", N);exit(1);

}

error.c

void error_exit_word_too_long(void){

printf("%s%d%s","ERROR: A word with more than ", MAXWORD, "\n"" characters was found - bye!\n");

exit(1);}

error.c

#include "sort.h"

void sort_words(char *w[], int n) /* n elements are to be sorted */{

int i, j;

for (i = 0; i < n; ++i)for (j = i + 1; j < n; ++j)

if (strcmp(w[i], w[j]) > 0)swap(&w[i], &w[j]);

}

sort_words.c

#include "sort.h"

void swap(char **p, char **q){

char *tmp;

tmp = *p;*p = *q;*q = tmp;

}

swap.c

a.out<input

input file

The College of Dentistry currently enrolls nearly 300 students in its D.D.S. program and is the only provider of pre-doctoral dental education in Iowa.Faculty include generalists and specialists in every discipline of dentistry as well as faculty who hold Ph.D.'s in biological or related fields. Most clinical faculty are private practitioners, who usually practice one day per week. Students at Iowa benefit from a 3-to-1 ratio of dental students to full-time clinical faculty. Teaching is the primary responsibility of 96 full-time faculty.

3-to-130096CollegeD.D.S.DentistryFacultyIowaIowa.MostPh.D.'sStudentsTeachingTheaand

andareasasatbenefitbiologicalclinicalclinicalcurrentlydaydentaldentaldentistrydisciplineeducationenrolls

everyfacultyfacultyfaculty.faculty.fields.fromfull-timefull-timegeneralistsholdininininincludeis

isitsnearlyofofofofofoneonlyorperpracticepractitioners,predoctoralprimaryprivate

programproviderratiorelatedresponsibilityspecialistsstudentsstudentsthethetousuallyweek.wellwhowho

Arguments to main()Arguments to main()Command line execution– passing information about execution condition

or parameters to program– use two arguments, char arrays, argc and argv– argc is used to count total parameters including

command itself– argv is used to store the total parameters

including command itself and save in the first element

/* Echoing the command line arguments. */

#include <stdio.h>

int main(int argc, char *argv[]){

int i;

printf("argc = %d\n", argc);for (i = 0; i < argc; ++i)

printf("argv[%d] = %s\n", i, argv[i]);return 0;

}

a.out a is for apple

argc = 5argv[0] = a.outargv[1] = aargv[2] = isargv[3] = forargv[4] = apple

Ragged ArraysRagged Arrays#include <stdio.h>

int main(void){

char a[2][15] = {"abc:", "a is for apple"};char *p[2] = {"abc:", "a is for apple"};

printf("%c%c%c %s %s\n%c%c%c %s %s\n",a[0][0], a[0][1], a[0][2], a[0], a[1],p[0][0], p[0][1], p[0][2], p[0], p[1]);

return 0;}

abc abc: a is for appleabc abc: a is for apple

Ragged ArraysRagged Arrays

An array of pointers whose elements are used to point arrays of varying size is called a ragged array.

Function as ArgumentsFunction as Arguments

pointers to functions can be passed as arguments, used in arrays, return from functions, and so forth. For example

2 ( )n

kk mf x

=∑

#include <math.h>#include <stdio.h>

double f(double);double sum_square(double (*)(double), int, int);

sum_sqr.h

double sum_square(double f(double), int m, int n){

int k;double sum = 0.0;

for (k = m; k <= n; ++k)sum += f(k) * f(k);

return sum;}

sum_sqr.c

double f(double x){

return 1.0 / x;}

fct.c

#include "sum_sqr.h"

int main(void){

printf("%s%.7f\n%s%.7f\n"," First computation: ", sum_square(f, 1, 10000),"Second computation: ", sum_square(sin, 2, 13));

return 0;}

main.c

First computation: 1.6448341Second computation: 5.7577885

An Example:Using Bisection An Example:Using Bisection to find the root of a functionto find the root of a function

#include <assert.h>#include <stdio.h>

typedef double dbl;

extern int cnt;extern const dbl eps; /* epsilon, a small quantity */

dbl bisection(dbl f(dbl x), dbl a, dbl b);dbl f(dbl x);

#include "find_root.h"

dbl bisection(dbl f(dbl x), dbl a, dbl b){

dbl m = (a + b) / 2.0; /* midpoint */

++cnt; /* # of fct calls */if (f(m) == 0.0 || b - a < eps)

return m;else if (f(a) * f(m) < 0.0)

return bisection(f, a, m);else

return bisection(f, m, b);}

#include "find_root.h"

dbl f(dbl x){

return (x * x * x * x * x - 7.0 * x - 3.0);}

/* Find a root of f() by the bisection method. */#include "find_root.h"int cnt = 0;const dbl eps = 1e-13; /* epsilon, a small quantity */int main(void){

dbl a = -10.0;dbl b = +10.0;dbl root;assert(f(a) * f(b) <= 0.0);root = bisection(f, a, b); /* recursive fct call */printf("%s%d\n%s% .15f\n%s% .15f\n",

"No. of fct calls: ", cnt,"Approximate root: ", root," Function value: ", f(root));

return 0;}

No. of fct calls: 49Approximate root: 1.719628091484431Function value: -0.000000000000977

KeplerKepler FunctionFunction

Example:

#include <assert.h>#include <math.h>#include <stdio.h>

typedef double dbl;

extern int cnt;extern const dbl eps; /* epsilon, a small quantity */extern const dbl e; /* a parameter in the Kepler eqn */extern const dbl m; /* a parameter in the Kepler eqn */

dbl bisection(dbl f(dbl x), dbl a, dbl b);dbl kepler(dbl x);

#include "kepler.h"

dbl bisection(dbl f(dbl x), dbl a, dbl b){

dbl m = (a + b) / 2.0; /* midpoint */

++cnt; /* # of fct calls */if (f(m) == 0.0 || b - a < eps)

return m;else if (f(a) * f(m) < 0.0)

return bisection(f, a, m);else

return bisection(f, m, b);}

#include "kepler.h"

dbl kepler(dbl x){

return (x - e * sin(x) - m);}

/* Use bisection to solve the Kepler equation. */

#include "kepler.h"

int cnt = 0;const dbl eps = 1e-15; /* epsilon, a small quantity */const dbl e = 0.5; /* a parameter in the Kepler eqn */const dbl m = 2.2; /* a parameter in the Kepler eqn */

int main(void){

dbl a = -100.0;dbl b = +100.0;dbl root;

assert(kepler(a) * kepler(b) <= 0.0);root = bisection(kepler, a, b); /* recursive fct call */printf("%s%d\n%s% .15f\n%s% .15f\n",

"No. of fct calls: ", cnt,"Approximate root: ", root," Function value: ", kepler(root));

return 0;}

No. of fct calls: 59Approximate root: 2.499454528163501Function value: 0.000000000000000

Arrays of Pointers to FunctionArrays of Pointers to Function

In C function name is treated by the compiler as a pointer to the function.Example:

fint_roots.h

#include <assert.h>#include <math.h>#include <stdio.h>

#define N 4 /* size of array of ptrs to fcts */

typedef double dbl;

/*// Create the type "ptr to fct taking a dbl and returning a dbl."*/typedef dbl (*pfdd)(dbl);

extern int cnt;extern const dbl eps; /* epsilon, a small quantity */

dbl bisection(pfdd f, dbl a, dbl b);dbl f1(dbl x);dbl f2(dbl x);dbl f3(dbl x);

#include "find_roots.h"

dbl bisection(pfdd f, dbl a, dbl b){

dbl m = (a + b) / 2.0; /* midpoint */

++cnt; /* # of fct calls */if (f(m) == 0.0 || b - a < eps)

return m;else if (f(a) * f(m) < 0.0)

return bisection(f, a, m);else

return bisection(f, m, b);}

bisection.c

#include "find_roots.h"

dbl f1(dbl x){

return (x*x*x - x*x + 2.0*x - 2.0);}

dbl f2(dbl x){

return (sin(x) - 0.7*x*x*x + 3.0);}

dbl f3(dbl x){

return (exp(0.13*x) - x*x*x);}

fct.c

/* Use bisection to find roots. */

#include "find_roots.h"

int cnt = 0;const dbl eps = 1e-13; /* epsilon, a small quantity */

int main(void){

int begin_cnt;int i;int nfct_calls;dbl a = -100.0;dbl b = +100.0;dbl root;dbl val;

main.c

pfdd f[N] = {NULL, f1, f2, f3};

for (i = 1; i < N; ++i) {assert(f[i](a) * f[i](b) <= 0.0);begin_cnt = cnt;root = bisection(f[i], a, b);nfct_calls = cnt - begin_cnt;val = f[i](root);printf("%s%d%s% .15f\n%s%d%s% .15f\n%s%3d\n\n",

"For f[", i, "](x) an approximate root is x0 = ", root," Fct evaluation at the root: f[", i, "](x0) = ", val," Number of fct calls to bisection() =", nfct_calls);

}return 0;

}

Result:

For f[1](x) an approximate root is x0 = 1.000000000000023Fct evaluation at the root: f[1](x0) = 0.000000000000069Number of fct calls to bisection() = 52

For f[2](x) an approximate root is x0 = 1.784414278382185Fct evaluation at the root: f[2](x0) = 0.000000000000169Number of fct calls to bisection() = 52

For f[3](x) an approximate root is x0 = 1.046387173807117Fct evaluation at the root: f[3](x0) = -0.000000000000134Number of fct calls to bisection() = 52

The Type Qualifiers const and The Type Qualifiers const and volatilevolatile

const is used to indicate the variable is a constant

static const int k=3; the value of k can not changed

const int n=3;int v[n]; /* complains*/

const int a=7;int *p&a; /* complains */

const int a=7;const in *p=&a; /* pointer to const variable */

int a;int const p=&a; /* const pointer to a variable */

/* the pointer can not direct othervariable except variable a */

const int a-7;const int const p=&a; /*const pointer points to the const

variable a */

The Type Qualifiers const and The Type Qualifiers const and volatilevolatile

It is seldom used.

A volatile object is one that can be modified in some unspecified way by the hardware.

extern cons volatile int real_time_clock;