arrays, pointers, and stringdsiva.weebly.com/uploads/5/2/7/8/5278587/chap07.pdf · pointer...
TRANSCRIPT
Arrays, Pointers, and Arrays, Pointers, and StringStringJun Ni, Ph.D.M.E.
Department of Computer ScienceThe University of Iowa
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;