arrays, pointers and strings
DESCRIPTION
Arrays, Pointers and Strings. Chapter 6 in ABC. One Dimensional Arrays. # defineN100 int a[N]; for ( i = 0; i< N; ++i ) sum += a[i];. space for a[0], ..., a[99] is allocated. process element a[ i ]. One Dimensional Arrays. float f[5] = { 0.0, 1.0, 2.0, 3.0, 4.0 }; - PowerPoint PPT PresentationTRANSCRIPT
Arrays, Pointersand Strings
Chapter 6 in ABC
One Dimensional Arrays
#define N 100
int a[N];
for ( i = 0; i< N; ++i )
sum += a[i];
space for a[0], ..., a[99] is allocatedspace for a[0], ..., a[99] is allocated
process element a[ i ]process element a[ i ]
One Dimensional Arrays
float f[5] = { 0.0, 1.0, 2.0, 3.0, 4.0 };
int a[100] = { 0 };
int a[] = { 2, 3, 5, -7 };
char s[] = “abc”;
char s[] = { ‘a’, ‘b’, ‘c’, ‘\0’ };
Pointers
p = 0;
p = NULL;
p = &i;
p = (int *) 1776;
equivalent to p = 0equivalent to p = 0
an absolute address in memoryan absolute address in memory
a b p
1 2
int a = 1, b = 2, *p;
p = &a;
b = *p; is equivalent to b = a;
a b p
1 2
Pointers
Pointers
int a = 1, b = 2, *p;
p = &a;
b = *p; is equivalent to b = a;
This is also correct:
int a = 1, b = 2, *p = &a;
Pointers
#include <stdio.h>
int main(void)
{
int i = 7, *p;
p = &i;
printf( “%s%d\n%s%u\n”, “ Value of i: ”, *p, “Location of i: ”, p );
return 0;
}
Value of i: 7
Location of i: 251657504
The result of the printingThe result of the printing
Declarations and Initializations
int i = 3, j = 5, *p = &i, *q = &j, *r;
double x;
Expression Equivalent Expression Value
p == &i p == ( &i ) 1
**&p * ( * ( &p ) ) 3
r = &x r = ( & x ) illegal
7 * *p / *q + 7 ( ( ( 7 * ( *p ) ) ) / ( *q ) ) + 7 11
*( r = &j ) *= *p ( *( r = ( &j ) ) ) *= ( *p ) 15
Declarations and Initializations
DeclarationDeclaration
int *p;
float *q;
void *v;
More illegalMore illegal::
&3,
&(k + 99),
register v;
&v
Legal Assignment Illegal Assignment
p = 0; p = 1;
p = ( int* ) 1; v = 1;
p = v = q; p = q;
p = ( int* ) q;
Call by Refernce#include <stdio.h>
void swap(int *p, int *q)
{
int tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void)
{
int i = 3, j = 5;
swap(&i, &j);
printf( “%d %d\n”, i, j );
return 0;
} 5 3 is printed5 3 is printed
Arrays and Pointers
a[i] is equivalent to *(a + i)
p[i] is equivalent to *(p + i)
p = a is equivalent to p = &a[0]
p = a + 1is equivalent to p = &a[1]
An array name is an address!
Pointer arithmetic ~ array indexing
Arrays and Pointers
for ( p = a; p < &a[ N ]; ++p )
sum += *p;
is equivalent to:
for ( i = 0; i < N; ++i )
sum += *( a + i );
is equivalent to:
p = a;
for ( i = 0; i< N; ++i )
sum += p[ i ];
Arrays and Pointers
Illegal expressions
a = p
++a
a += 2
&a
a = p
++a
a += 2
&a
Pointer Arithmetic and Element Size
double a[2], *p = NULL, *q = NULL;
p = a;
q = p +1;
printf(“%d\n”, q - p);
printf(“%d\n”, (int)q - (int)p);
points to the base the arraypoints to the base the array
equivalent to q = &a[ 1 ]equivalent to q = &a[ 1 ]
1 is printed1 is printed
8 is printed8 is printed
Arrays as Function Arguments
double sum(double a[], int n)
{
int i = 0;
double sum = 0.0;
for ( i = 0; i < n; ++i )
sum += a[i];
return sum;
}
n is the size of a[]n is the size of a[]
An Example: Bubble Sort
void bubble( int a[], int n )
{
int i = 0, j = 0;
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 ] );
}
n is the size of a[]n is the size of a[]
Another Examplevoid 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 )
c[k++] = a[i++];while (j < n) c[k++] = b[j++];
}
Merge a[] of size m and b[] of size n into
c[].
Merge a[] of size m and b[] of size n into
c[].
pickup any remainderpickup any remainder
Mergesort#include <stdio.h>
#include <stdlib.h>
void merge(int *, int *, int *, int, int);
void mergesort(int key[], int n)
{
int j = 0, k = 0, m = 0, *w = NULL;
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 );
}
Use merge() to sort an array of size nUse merge() to sort an array of size n
no additional statements for this loop
no additional statements for this loop
Mergesort
w = calloc( n, sizeof( int ) );
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 );
for (j = 0; j < n; ++j)
key[j] = w[j];
}
free(w);
w = NULL;
}
allocate workspaceallocate workspace
merge into wmerge into w
write w back into keywrite w back into key
free the workspacefree the workspace
Mergesort#include <stdio.h>
#define KEYSIZE 16
void mergesort(int *, int);
int main(void)
{
int i, key[] = { 4, 3, 1, 67, 55, 8, 0, 4, -5, 37, 7, 4, 2, 9, 1, -1 };
mergesort(key, KEYSIZE);
printf( “After mergesort:\n” );
for ( i = 0; i < KEYSIZE; ++i )
printf( “%4d”, key[i] );
putchar( ‘\n’ );
return 0;
}
Strings
char *p = “abcde”
printf( “%s %s\n”, p, p +1 );
char s[] = “abcde”
is equivalent to:
char s[] = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘\0’};
abcde bcde is printedabcde bcde is printed
Strings
char *p = “abcde” vs. char s[] = “abcde”
sp
a b c d e \0
a b c d e \0
Strings
“abc”[1] and *(“abc” + 2) make sense
char *s = NULL;
int nfrogs = 0;
. . . .
s = (nfrogs == 1)? “” : “s”;
printf( “we found %d frog%s in the pond!\n”, nfrogs, s );
NULL StringsNULL Strings
Count the number ofwords in a string
#include <ctype.h>
int word_cnt(char *s)
{
int cnt = 0;
while (*s != '\0')
{
while (isspace(*s))
++s;
if (*s != '\0')
{
++cnt;
while (!isspace(*s) && *s != '\0')
++s;
}
}
return cnt;
}
skip white spacesskip white spaces
found a wordfound a word
skip the wordskip the word
char *strcat(char *s1, const char *s2);
int strcmp(const char *s1, const char *s2);
char *strcpy(char *s1, const char *s2);
unsigned strlen(const char *s);
String Handling Functions in the Standard Library
String Handling Functions in the Standard Library
unsigned strlen( const char *s )
{
register int n = 0;
for ( n = 0; *s != '\0'; ++s )
++n;
return n;
}
String Handling Functions in the Standard Library
char *strcat( char *s1, const char *s2 )
{
register char *p = s1;
while ( *p )
++p;
while ( *p++ = *s2++ ) ;
return s1;
}
no more statements in this loopno more statements in this loop
Multidimensional Arrays
int sum( int a[][5] )
{
int i = 0, j = 0, sum = 0;
for ( i = 0; i < 3; ++i )
for ( j = 0; j < 5; ++j )
sum += a[i][j];
return sum;
}
Multidimensional Arrays
int sum( int a[][9][2] )
{
int i = 0, j = 0, k = 0, 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;
}
Sort Words Lexicographically
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXWORD 50 /* max word size */
#define N 1000 /* array size */
void sort_words(char *[], int);
void swap(char **, char **);
Sort Words Lexicographicallyint main(void)
{
char *w[N];
char word[MAXWORD];
int n = 0, i = 0;
for ( i = 0; scanf("%s", word) == 1; ++i )
{
if ( i >= N )
{
printf( “Sorry, at most %d words can be sorted.”, N );
exit(1);
}
w[i] = calloc(strlen(word) + 1, sizeof(char));
strcpy(w[i], word);
}
an array of pointersan array of pointers
work spacework space
number of wrods to be storednumber of wrods to be stored
Sort Words Lexicographically
n = i;
sort_words( w, n );
for ( i = 0; i < n; ++i )
printf( “%s\n”, w[i] );
return 0;
}
print the sorted wordsprint the sorted words
void sort_words( char *w[], int n )
{
int i = 0, j = 0;
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] );
}
void swap( char **p, char **q )
{
char *temp = NULL;
temp = *p;
*p = *q;
*q = temp;
}
Sort Words Lexicographically
n elements to be sortedn elements to be sorted
Arguments to main()
#include <stdio.h>
void main(int argc, char *argv[])
{
int i = 0;
printf( “argc = %d\n”, argc );
for ( i = 0; i < argc; ++i )
printf( “argv[%d] = %s\n”, i, argv[i] );
}
Ragged 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 apple
abc abc: a is for apple
Functions as Argumentsdouble sum_square( double f(double), int m, int n )
{
int k = 0;
double sum = 0.0;
for ( k = m; k <= n; ++k )
sum += f(k) * f(k);
return sum;
}
double sum_square( double (*f)(double), int m, int n )
{
.....
Functions as Arguments#include <stdio.h>
double f(double), sin(double), sum_square(double (*)(double), int, int);
int main(void)
{
printf( “%s%.7f\n%s%.7f\n”,
“ First computation: ”, sum_square(sin, 2, 13),
“Second computation: ”, sum_square(f, 1, 10000));
return 0;
}
double f(double x)
{
return 1.0 / x; First computation: 5.7577885
} Second computation: 1.6448341
Find a root of f() by the bisection method
#define EPS 1e-12
double root(double f(double), double a, double b)
{
double m = (a + b) / 2.0;
if (f(m) == 0.0 || b - a < EPS)
return m;
else if (f(a) * f(m) < 0.0)
return root(f, a, m);
else return root(f, m, b);
}
epsilonepsilon
midpointmidpoint
Find a root of f() by the bisection method
#include <stdio.h>
double p(double);
double root(double (*)(double), double, double);
int main(void)
{
double x = root( p, 0.0, 3.0 );
printf( “%s%.16f\n%s%.16f\n”, “Approximate root: ”, x,
“ Function value: ”, p( x ) );
return 0;
}
Find a root of f() by the bisection method
double p(double x)
{
return (x * x * x * x * x - 7.0 * x - 3.0);
}
Approximate root: 1.7196280914844584
Function value: 0.0000000000000317
Constconst ----- - type qualifier; comes after storage class
static const int k=3;
const int a = 7; int *p = &a; /* compiler warning */
const int a = 7; const int *p = &a; /* ok */
int a=7; int * const p = &a; /* the pointer is a constant */
int a=7; const int * const p = &a; /* both pointer and pointed int are constants. */
qsort: a generic sorting procedure
qsort's prototype in stdlib.h (using size_t from stddef.h):
void qsort(void *array,
size_t n_elem,
size_t elem_size,
int compare(const void *, const void *));
compare(a,b) returns negative int if a<b
returns 0 if a=b
returns positive int if a>b
// qsort an array of ints
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define KEYSIZE 16
int compare_int(const void *p1, const void *p2);
void print_array(char *title, int *key, int n_elem);
int main(void)
{
int key[] = { 4, 3, 1, 67, 55, 8, 0, 4, -5, 37, 7, 4, 2, 9, 1, -1 };
print_array("before ", key, KEYSIZE);
qsort(key, KEYSIZE, sizeof(int), compare_int);
print_array("after ", key, KEYSIZE); return 0;
}
void print_array(char *title, int *key, int n_elem) { int i;
printf("\n %s:\n",title); for (i = 0; i < n_elem; ++i)
printf("%4d", key[i]); putchar('\n'); }
// the compare function to be passed as a parameter to qosrt
int compare_int(const void *p1, const void *p2) { const int *q1 = p1, *q2 = p2; return ((*q1) - (*q2)); }
Handling nXn matrices
---------------------
// allocating the matrix
int i,j,n;
double **a;
a = calloc(n,sizeof(double *));
for (i=0; i<n; ++i)
a[i] = calloc(n,sizeof(double));
...
// filling in the matrix with numbers in the range [-N,N]:
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
a[i][j] = rand() % (2 * N + 1) - N;
…
...
// computing the trace
double trace(double **a, int n)
{
int i;
double sum = 0.0;
for (i=0; i<n; ++i)
sum += a[i][i]; /* sum the elements on the main diagonal */
return sum;
}
The trace program (Chapter 12.6)
--------------------------------
•The space for the elements of the matrix is allocated all at once.
•* Pointers are offset so that the indexing starts at 1, not 0.
-------------------------------------------------
// trace.h #include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef double dbl; // could be substituted with other types
The trace program (Chapter 12.6)
--------------------------------
•The space for the elements of the matrix is allocated all at once.
•Pointers are offset so that the indexing starts at 1, not 0.
---------------------פרוטוטייפס--------------------
void check_cmd_line(int argc, char **argv);
void fill_matrix(dbl **a, int m, int n);
dbl ** get_matrix_space(int m, int n);
void release_matrix_space(dbl **a);
dbl trace(dbl **a, int m, int n);
void wrt_info(const char *pgm_name);
void wrt_matrix(const char *s, dbl **a, int m, int n);
// main.c #include "trace.h" int main(int argc, char **argv) {
int m; /* number of rows */ int n; /* number of columns */ int val; dbl **a; /* matrix */
srand(time(NULL)); /* seed the random number generator */
check_cmd_line(argc, argv); printf("%s\n", "---\n" "This program creates space for an mxn
matrix A, fills it with\n" "randomly distributed digits from -9 to +9, and then prints\n" "the matrix A and its trace.\n");
for ( ; ; ) { printf("Input m and n: "); val = scanf("%d%d", &m, &n); if (val != 2 || m < 1 || n < 1) break; putchar('\n'); a = get_matrix_space(m, n); fill_matrix(a, m, n); …
}
// main.c …
srand(time(NULL)); /* seed the random number generator */ check_cmd_line(argc, argv);
printf("%s\n", "---\n" "This program creates space for an mxn matrix A, fills it with\n" "randomly distributed digits from -9 to +9, and then prints\n" "the matrix A and its trace.\n");
for ( ; ; ) { printf("Input m and n: "); val = scanf("%d%d", &m, &n); if (val != 2 || m < 1 || n < 1) break; putchar('\n'); a = get_matrix_space(m, n); fill_matrix(a, m, n); wrt_matrix("A", a, m, n); printf("trace(A) = %.1f\n\n", trace(a, m, n));
release_matrix_space(a); }
printf("\nBye!\n\n"); return 0;
}
// check-cmd-line.c
#include "trace.h"
void check_cmd_line(int argc, char **argv) {
if (argc > 1 && strcmp(argv[1], "-h") == 0) { wrt_info(argv[0]); exit(1);
} if (argc > 1) {
printf("\nERROR: No command line arguments needed.\n\n"); wrt_info(argv[0]); exit(1); }
}
// allocate-free.c #include "trace.h"
dbl **get_matrix_space(int m, int n) { int i; dbl *p; dbl **a; p = malloc(m * n * sizeof(dbl)); /* get the space all at once */ a = malloc(m * sizeof(dbl *)); assert(p != NULL); assert(a != NULL); /* // Offset pointers to change the indexing.*/ --a; /* index from 1, not 0 */
for (i = 1; i <= m; ++i) a[i] = p + ((i - 1) * n) - 1; /* index from 1, not 0 */ return a;}
// allocate-free.c #include "trace.h"
void release_matrix_space(dbl **a) { dbl *p;
/* // The effects of offsetting the pointers // must be undone before releasing space. */
p = a[1] + 1; /* base address in memory */ free(p); free(a + 1); }
// write.c #include "trace.h"
void wrt_matrix(const char *s, dbl **a, int m, int n) { int i, j; printf("%s =\n", s); for (i = 1; i <= m; ++i) {
for (j = 1; j <= n; ++j) printf("%6.1f", a[i][j]);
putchar('\n'); }
putchar('\n'); }
// fill-matrix.c #include "trace.h"
void fill_matrix(dbl **a, int m, int n) { int i, j; for (i = 1; i <= m; ++i)
for (j = 1; j <= n; ++j) a[i][j] = rand() % 19 - 9; /* from -9 to +9 */
}
// compute-trace .c #include "trace.h"
dbl trace(dbl **a, int m, int n) { int i; int k; dbl sum = 0.0;
k = (m < n) ? m : n; for (i = 1; i <= k; ++i)
sum += a[i][i]; return sum; }