480 likes | 486 Views
This chapter covers the basics of one-dimensional arrays, pointers, and strings, including array initialization, pointer arithmetic, dynamic memory allocation, and string-handling functions.
E N D
Chapter 6 Arrays, Pointers, and Strings 2008-11-25
6.1 One-dimensional Arrays • 6.2 Pointers • 6.3 Call-by-Reference • 6.4 The Relationship Between Arrays and Pointers • 6.5 Pointer Arithmetic and Element Size • 6.6 Array as Function Arguments • 6.7 An Example: Bubble Sort • 6.8 Dynamic Memory Allocation With calloc() and malloc() • 6.9 An Example: Merge and Merge Sort • 6.10 Strings • 6.11 String-Handling Function in the Standard Library • 6.12 Multidimensional Arrays • 6.13 Arrays of Pointers • 6.14 Arguments to main() • 6.15 Ragged Arrays • 6.16 Functions as Arguments • 6.17 An Example: Using Bisection to Find the Root of a Function • 6.18 Arrays of Pointers to Function • 6.19 The Type Qualifiers const and volatile
6.1 One-dimensional Arrays • int grade0, grade1, grade2; • int grade[3]; Memory OR Memory
Test • #include <stdio.h> • int main(void) • { • int a=10; • int b=20; • int c=30; • int d=40; • printf(“a=%d,b=%d,d=%d,d=%d”, a,b,c,d); • printf("a=%p,b=%p,c=%p,d=%p\n", &a,&b,&c,&d); • return 1; • } Pointer address Output: a=10,b=20,c=30,d=40 a=0023FF74,b=0023FF70,c=0023FF6C,d=0023FF68
One-dimensional Arrays • int a[size]; • /*space for a[0],…, a[size-1] allocated • low bound = 0 • upp bound = size - 1 • size = upper bound + 1; */ int a[8]; //size=8 low bound=0 upper bound=7 a[5] a[3] a[2] a[4] a[7] a[0] a[1] a[6]
#define N 100 • int a[N]; /* space for a[0],…,a[99] is allocated */ General version void main() { for (int a=0;a<100;a++) {……….} for (int a=0;a<100;a++) {……….} for (int a=0;a<100;a++) {……….} } Good version void main() { for (int a=0;a<N;a++) {……….} for (int a=0;a<N;a++) {……….} for (int a=0;a<N;a++) {……….} }
Array Initialization • float f[5] = {0,1,2,3,4}; • int a[100] = {0}; • int a[] = {2,3,5,-7}; • int a[4] = {2,3,5,-7} • char s[]=“abc”; • char s[]={‘a’,’b’,’c’,’\0’};
Exercise 1 • Trace the codes and Find out the problem in the for-loop • int a[10]; • int sum=0; • for (int i=0;i<=10;i++) • { • sum += a[i]; • }
Overrunning the bounds • Overrunning the bounds of an array is a common programming error. • The effect of the error is system-dependent, and can be quite confusing. • One frequent result is that the value of some unrelated variable will be returned or modified. • It is the programmer’s job to ensure that all subscripts to arrays stay within bounds.
Array elements for two-dimensional Arrays int array_name[num_row][num_column];
Two dimensional array initialization • int my_array[2][5]= • { • {1,2,3,4,5}, • {6,7,8,9,10} • }; • printf("%d",my_array[1][3]); • int my_array[2][5]= • { • 1,2,3,4,5, • 6,7,8,9,10 • }; • printf("%d",my_array[1][3]); • int now_value = 0; • for (int y=0;y<2;y++) • { • for (int x=0;x<5;x++ • my_array[y][x] = 1; • now_value += 1; • } • printf(“%d”,now_value);
Exercise 2 • Print out the sum of each row of two dimensional array respectively by using for-loop instruction. • #define num_row 4 • #define num_col 6 • int my_array[num_row][num_col]; • // ………initial the value of my_array • int row_sum=0; • for (int a=0 ; a<num_row ; a++) • { • for (int b=0 ; b<num_col ; b++) • { • row_sum += my_array[a][b]; • } • printf(“The sum of %d row is %d”,row_sum); • row_sum = 0; • }
【實例探討】某學生之功課表如下,(每個課程名稱皆以代碼表示),使用者輸入星期幾及第幾節課,輸出課程名稱。【實例探討】某學生之功課表如下,(每個課程名稱皆以代碼表示),使用者輸入星期幾及第幾節課,輸出課程名稱。
void main() • { • int course[6][5] = { 0, 2, 0, 2, 0, /* 課程定義 */ 1, 4, 1, 4, 1, 5, 0, 5, 0, 5, 0, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 0, 0, 0, 0 }; int week; /* 星期資料變數 */ int class; /* 第幾節課的變數 */ int class_no; /* 課程代碼變數 */ printf("請輸入星期(1 到 5). ==> "); scanf("%d",&week); /* 讀取星期資料 */ printf("請輸入第幾節課(1 到 6). ==> "); scanf("%d",&class); /* 讀取第幾節課 */ class_no = course[class-1][week-1]; /* 課程查詢 */
switch ( class_no ) /* 印出課程名稱 */ { • case 0: • printf("這節沒課\n"); • break; • case 1: • printf("計算機概論\n"); • break; • case 2: • printf("離散數學\n"); • break; • case 3: • printf("資料結構\n"); • break; • case 4: • printf("資料庫概論\n"); • break; • case 5: • printf("上機實習\n"); • break; • } • }
6.2 Pointers • Pointers are used in programs to access memory and manipulate addresses. • If v is a variable, then &v is the location, or address, in memory of its stored value. • Pointer variables can be declared in programs and then used to take addresses as values. • The declaration int *p; declares p to be of type pointer to int. • Its legal range of values always includes the special address 0 and a set of positive integers that are interpreted as machine addresses on the given C system.
Example int a=100; /*在記憶體中,要一塊空間來儲存數值,至於實際的位址, 使用者不知道。*/ int a 100 int *p; /*在記憶體中,要一塊空間來儲存別人的”位址”。*/ int p 位址? p = &a; /*將a的位址儲存在p中*/ int p a的位址
*p = 200; /*將200儲存到p所指的位址裡。*/ int int p a 100->200 a的位址 printf(“%d”,a); 200 printf(“%d”,*p); 200 printf(“%p”,p); 0023FF74 printf(“%p”,&a); 0023FF74 4,294,967,296 = 4G bytes
Pointer Assignment • int a; • int *p; • p = 0; • p = NULL; /*equivalent to p=0 */ • p = &a; • p = (int *) 1776; /*an absolute address in memory */ int *p (p is a pointer to int)
p a b • int a=1,b=2,*p; ? 1 2 • p = &a; p a b 1 2 *p = 1
int i=3,j=5,*p=&i,*q=&j,*r;double x; *q *p j *r i 3 5 x ?
Warning 1 int a=10; int *p = &a; *p = &a; Different printf("%d",*p); Warning 2 illegal: &3, &(k+99), register v; &v;
Exercise 3 • #include <stdio.h> • void main() • { • int a; • int *b; • b = &a; • *b = 100; • printf("\na=%d",a); • } Output: a=100
example: locate.c • /* printing an address, or location. */ • #include <stdio.h> • int main(void) • { • int i=7, *p=&i; • printf(“%s%d\n%s%p”,”Value of i: “,*p,”Location of i: “,p); • return 0; • } • Value of i: 7 • Location of i: effffb24 (!depend on compiler)
6.3 Call-by-Reference • Whenever variables are passed as arguments to a function, their values are copied to the corresponding function parameters, and the variables themselves are not changed in the calling environment. • To change the values of variables in the calling environment, other languages provide the “call-by-reference” mechanism.
Example for call-by-value and call-by-reference int int int int c c a a a的位址 300 100 100 void fun_1(int c) { c = 300; } void main( ) { int a = 100; func_1(a); printf(“a=%d”,a); } void fun_1(int *c) { *c = 300; } void main( ) { int a = 100; func_1(&a); printf(“a=%d”,a); } Output: a=300 Output: a=100
Example • #include <stdio.h> • void swap(int *, int *); • int main (void) • { • int i=4,j=5; • swap(&i,&j); • printf(“i=%d,j=%d”,i,j); • return 0; • } • void swap(int *p, int *q) • { • int tmp; • tmp = *p; • *p = *q; • *q = tmp; • } tmp j i Output: i=5,j=4 5 3 *q *p
The effect of “call-by-reference” is accomplished by • 1. Declaring a function parameter to be a pointer. • 2. Using the dereferenced pointer in the function body. • 3. Passing an address as an argument when the function is called
6.4 The Relationship Between Arrays and Pointers • a[i] is equivalent to *(a+i) • // p=a; is equivalent to p =&a[0]; • // p=a+1; is equivalent to p =&a[1]; a[2] a[0] a[1] a[3] a[4] a[5] &a[0] &a[2] &a[3] &a[4] &a[5] &a[1] int p p=&a[0] a的位址
Different between arrays and pointers • An array name by itself is an address, or pointer value, and pointers, as well as arrays, can be subscripted. Although pointers and arrays are almost synonymous in terms of how they are used to access memory, there are differences. • A pointer variable can take different addresses as values. • In contrast, an array name is an address, or pointer, that is fixed.
Exercise 4 • int main(void) • { • int a[10]; • int *p = a; • int i; • a[0] = 3; • for (i=1;i<10;i++) • a[i] = a[i-1] * 2; • printf("%d\n",*p); //3 • printf(“%d\n”,*p+1); //4 • printf("%p\n",a); //0023FF40 • printf(“%p,%p\n”,a,(a+1)); //0023FF40,0023FF44 • }
Three ways to calculate the sum • #define N 6 • int a[N], i,*p, sum=0; • 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];
6.5 Pointer Arithmetic and Element Size • Pointer arithmetic is one of the powerful 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. 10 20 40 80 *(p+1) *p *(p+2) *(p+3)
Continue • Pointer expressions such as p+i and ++p and p+=1 all make sense. If p and q are both pointering to elements of an array, then p-q yields the int value representing the number of array elements between p and q. • double a[2], *p, *q; • p = a; //points to base of array • q = p + 1; //equivalent to q=&a[1] • printf(“%d\n”,q-p); //1 is printed • printf(“%d\n”,(int)q – (int)p); //8 is printed • On most machines, a double is stored in 8 bytes. Because p points to a double and q points to the next double, the difference in terms of array elements is 1, but the difference is memory location is 8.
6.6 Array as Function Arguments • In a function definition, a formal parameter that is declared as an array is actually a pointer. • Corresponding to this, when an array is passed as an argument to a function, the base address of the array is passed “call-by-value.” • The array elements themselves are not copied.
Concept • void fun_sum ( double b[], int length_b ) • { • …… • } • int main() • { • int array[10]; • …… • fun_sum(array,10) • …… • …… • }
Example • double fun_sum(double a[], int n) • { • int i; • double sum=0; • for (i = 0; i < n ;i++) • sum += a[i]; • return sum; • } • int main(void) • { • double my_array[10]; • double s; • int a; • for(a=0;a<10;a++) • my_array[a] = a; • s = fun_sum(my_array,10); • printf("\nsum=%.0f",s); • }
s = fun_sum(v,100); • v[0]+v[1]+…+v[99] • s = fun_sum(v,88); • v[0]+v[1]+…+v[87] • s = fun_sum(&v[7],k-7); • v[7]+v[8]+…+v[k-1] • s = fun_sum(v+7,2*k); • v[7]+v[8]+…+v[2*k+6]
n = 7 20 90 40 30 80 70 0 1 2 3 4 5 6 50 6.7 An Example: Bubble Sort 由第零個元素開始, 與下一個元素比較, 如果比下一個元素大, 二者對調, 直到最後一個. 對於 n 個元素, 此步驟需要進行 n-1 次, 第一次 pass 完成後, 最大的元素會落於第 n-1 個位置, 即最大的元素已經排序好了, 接下來, 第 2 個 pass 完成後, 次大的元素會排在第 n-2 個位置. 依此方式即可將該陣列排序好.
n = 7 n = 7 n = 7 20 20 20 90 40 90 90 40 40 30 30 30 80 80 80 70 70 70 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 50 50 50 k = n-1 = 6 j = 0, a[0] = 20 < 90 = a[1] j = 1, a[1] = 90 > 40 = a[2]
n = 7 n = 7 n = 7 20 20 20 40 40 40 90 30 30 30 80 90 90 80 80 70 70 70 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 50 50 50 j = 2, a[2] = 90 > 30 = a[3] j = 3, a[3] = 90 > 80 = a[4]
n = 7 n = 7 n = 7 20 20 20 40 40 40 30 30 30 80 80 80 70 70 90 50 70 90 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 50 90 50 j = 4, a[4] = 90 > 70 = a[5] j = 5, a[5] = 90 > 50 = a[6]
pass 4: pass 3: pass 2: pass 1: n = 7 n = 7 n = 7 n = 7 n = 7 20 20 20 20 20 40 30 90 30 30 40 40 40 30 40 50 30 70 80 50 70 50 80 70 70 70 80 80 80 50 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5 6 6 6 6 6 90 50 90 90 90
Bubble Sort • void swap(int *, int *); • void bubble(int a[], int n) • { • int i,j; • 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]); • } • } • …….. • int a[] = {7, 3, 66, 3, -5, 22, -77, 2}; • bubble(a,8); • ……
n=8 7 3 66 3 -5 22 -77 2 i=0 j=n-1 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]); } Page:258
Time complexity of bubble sort • A bubble sort is very inefficient. If the size of the array is n, then the number of comparisons performed is proportional to n2.