Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Γενική Δομή Προγράμματος Λίστα από συναρτήσεις - main() Τύπος-επιστρεφόμενης-τιμής όνομα(λίστα-παραμέτρων) { δηλώσεις μεταβλητών λίστα εντολών } /*Επιστρέφει.

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "Γενική Δομή Προγράμματος Λίστα από συναρτήσεις - main() Τύπος-επιστρεφόμενης-τιμής όνομα(λίστα-παραμέτρων) { δηλώσεις μεταβλητών λίστα εντολών } /*Επιστρέφει."— Μεταγράφημα παρουσίασης:

1 Γενική Δομή Προγράμματος Λίστα από συναρτήσεις - main() Τύπος-επιστρεφόμενης-τιμής όνομα(λίστα-παραμέτρων) { δηλώσεις μεταβλητών λίστα εντολών } /*Επιστρέφει το μέγιστο μεταξύ των x, y*/ int max(int x,int y) { int z = x; /*δηλώσεις μεταβλητών - αρχικοποίηση*/ if (y > x) /*λίστα εντολών*/ { z = y; } return z; }

2 Παραστάσεις υπό Συνθήκη if ( x > y) { x = a; } else { x = b; }

3 Τυπικά Λάθη if(x=5) αντί για if(x==5) Ξεχάσατε το break σε εντολή switch Ξεχάσατε {, } Λάθος στις προτεραιότητες: ( ) Λύση: Μορφοποίηση και χρήση σχολίων

4 Μορφοποίηση Σχόλια πριν από συναρτήσεις και τους ορισμούς μεταβλητών Κατάλληλη χρήση tabs, παρενθέσεων και αγκυλών Κατάλληλη ονοματολογία συναρτήσεων - μεταβλητών /*Epistrefei ton endiameso ari8mo twn a,b,c*/ int getMedian(int a,int b, int c) { int median; /*Endiamesos*/ if ((a = c)) || ((a >= b) && (a <= c)) { median = a; } else if ((b = c)) || ((b >= a) && (b <= c)) { median = b; } else { median = c; } return median; }

5 Define – Const – Include #define #define FALSE 0 #define TRUE !FALSE #define N 1000 /*ΠΡΟΣΟΧΗ!! – ΔΕΝ ΜΠΟΡΩ ΝΑ ΧΡΗΣΙΜΟΠΟΙΗΣΩ ΤΟ Ν ΩΣ ΜΕΤΑΒΛΗΤΗ*/ #define Pi 3.14159 –Ορίζεται στην αρχή κάθε προγράμματος και μπορεί να χρησιμοποιηθεί σε όλο το πρόγραμμα. –To Pi θα αντικατασταθεί από τον 3.14159 στο πρώτο βήμα του compilation (preprocessing) int const a = 1; –ορίζει μια σταθερά – δεν μπορεί να αλλάξει τιμή #include #include “file”

6 Παράδειγμα /* Author: C. Panagiotakis Function: Solves a second order polynomial equation. */ #include /*function prototypes*/ float diakrinousa(float,float, float ); int printSolution2ba8mou(float a, float b, float c); int main() { float a,b,c; printf(“Dwste 3 pragmatikous ari8mous \n”); scanf(“%f %f %f”,&a,&b,&c); printf("Dw8hke to poluwnumo: %f x^2 + (%f) x + (%f) \n",a,b,c); if (a == 0) { printf(“H e3iswsh einai prwtou ba8mou\n”); } else { printSolution2ba8mou(a, b, c); } /*Υπολογίζει τη διακρίνουσα */ float diakrinousa(float a,float b, float c) { float D = b*b – 4*a*c; return D; } /*Εκτυπώνει τις λύσεις */ int printSolution2ba8mou(float a, float b, float c) { float D = diakrinousa( a, b, c); float x1,x2; if (D < 0) { printf(“Den uparxoun pragmatikes luseis.\n”); return 0; } else if (D == 0) { x1 = -b/(2*a); printf(“Yparxei monadikh lush %f\n”,x1); return 1; } else { x1 = (-b+sqrt(D))/(2*a); x2 = (-b-sqrt(D))/(2*a); printf(“Yparxoun 2 luseis :%f, %f\n”,x1,x2); return 2; }

7 Επαναληπτικές Εντολές – while – for Συντακτικό: while (έκφραση) { εντολή } for ( έκφραση1 ; έκφραση2; έκφραση3) { εντολή }

8 Έξοδος από βρόγχο Εντολή break –Τερματισμός μόνο του πιο «μέσα» βρόγχου ή switch –Ειδικές περιπτώσεις –Π.χ., βγες από το μενού Εντολή continue –Η ροή πηγαίνει απευθείας στην έκφραση3 παράσταση της for (αν πρόκειται για for) –Κατόπιν η ροή πηγαίνει στην συνθήκη ελέγχου της ανακύκλωσης (για for, while, do) –Π.χ., αγνόησε κάποιο στοιχείο του βρόχου

9 Παραδείγματα Bρόχων // Υπολογισμός Δύναμης int power(int base, int n) { int i, p; p =1; for (i = 1; i <= n; i++) p = p*base; return p; } /* Υπολογισμός παραγοντικού n! = n*(n-1)! */ int parag(int n) { int i, p; p =1; for (i = 2; i <= n; i++) p = p*i; return p; }

10 Παραδείγματα Bρόχων /* Υπολογισμός της μικρότερης δύναμης του 2 που είναι μεγαλύτερη από τον αριθμό n*/ int powerOfTwo(int n) { int p; p = 1; while (1) { p = p*2; if (p > n) break; } return p; }

11 /* Εκτυπώνει του s 10 πρώτους αριθμούς που το άθροισμα των ψηφίων τους είναι 7 και την μέση τους τιμή */ int x = 1; //metablhth gia enan tyxaio ari8mo int sum = 0; //metablhth gia to # tvn ari8mwn float mean = 0; //metablhth gia th mesh timh while (sum < 10) { if (sumOfDigits(x) == 7) { mean += x; sum++; printf( “ O %d ari8mos einai o %d\n ”,sum,x); } ++x; } mean = mean/10; printf( “ H mesh tous timh einai %.2f\n ”,mean);

12 for (i=1; i<=8; i++) { for (j = 1; j <= i; ++j) { printf( “ * ” ); } printf( “ \n ” ); } * ** *** **** ***** ****** ******* ********

13 Πίνακες Δήλωση πολλών πινάκων ίδιου τύπου –Όπως και μεταβλητές –int b[ 100 ], x[ 27 ]; Τα στοιχεία του πίνακα χρησιμοποιούνται σαν συνηθισμένες μεταβλητές c[ 0 ] = 3; printf( "%d", c[ 0 ] ); Μπορούμε να κάνουμε πράξεις μέσα στο δείκτη. If ( x[0] == 3) c[ 5 - 2 ] == c[ 3 ] == c[ i ] Εμφωλιασμένοι δείκτες: c[c[c[1]]] ΠΡΟΣΟΧΗ: –δείκτης πίνακα (index) c[i], index is i (int i;)

14 Στοιχεία του Πίνακα σε Εκφράσεις έκφραση1  όνομα_πίνακα[έκφραση2] –πρώτα υπολογίζεται η τιμή της έκφρασης2 –η τιμή της έκφρασης2 πρέπει να είναι ακέραια (int) –η τιμή της έκφρασης1 είναι το στοιχείο του πίνακα που αντιστοιχεί στην συγκεκριμένη θέση που δίνεται από την έκφραση2 –ο τύπος της έκφρασης1 είναι ο τύπος των στοιχείων του πίνακα double array[100]; int i, x=5; for (i = 0; i < 100; ++i) scanf( “ %lf ”,&(array[i])); i = (int)(array[10*x]);

15 Παραδείγματα χρήσης Αρχικοποίηση int n[ 5 ] = { 1, 2, 3, 4, 5 }; –Αν δεν υπάρχουν αρκετά στοιχεία για αρχικοποίηση, τότε τα υπολοιπόμενα γίνονται 0 int n[ 5 ] = { 0 }; /* All elements 0 */ for (i = 0; i < 5; ++i) n[i] = 0; –Αν βάλουμε πιο πολλά στοιχεία από όσα έχει ο πίνακας τότε θα πάρουμε λάθος Αν αρχικοποιούμε τον πίνακα μπορούμε να μη δώσουμε μέγεθος και ο πίνακας θα είναι όσος και τα στοιχεία που δίνουμε int n[ ] = { 1, 2, 3, 4, 5 }; –5 στοιχεία, οπότε πίνακας 5 στοιχείων

16 Πρόγραμμα : histogram.c #include // The size of the array storing the grades #define HIST_SIZE 11 #define STUDENTS 30 // The size of the array storing the histogram //Computes the histogram n of array a. //Array a has sizeA elements void computeHist(int n[],int a[],int sizeA) { int i; for (i = 0; i < sizeA; ++i) n[a[i]]++; } int main() { int hist[HIST_SIZE] = {0}; int ba8moi[STUDENTS],i,j; for (i = 0; i < STUDENTS; ++i) scanf("%d",&(ba8moi[i])); computeHist(hist,ba8moi,STUDENTS) ; for (i=0; i < HIST_SIZE; i++) { printf("%7d%13d%8c", i, hist[i], ' '); for (j = 0; j < hist[i]; j++) putchar('*'); printf("\n"); } return 0; }

17 Όρια C arrays have no bounds checking Στη C δεν υπάρχει έλεγχος ορίων! Τι γίνεται αν βγούμε έξω από τον πίνακα;

18 Size-of sizeof μπορεί να χρησιμοποιηθεί με –Ονόματα μεταβλητών –Ονόματα τύπων –Σταθερές sizeof –Επιστρέφει το μέγεθος σε bytes –Για πίνακες: μέγεθος του 1 στοιχείου * πλήθος –Αν sizeof( int ) είναι 4 bytes, τότε int myArray[ 10 ]; printf( "%d", sizeof( myArray ) ); Θα τυπώσει 40

19 Πρόγραμμα - armemory.c #include #define SIZE 10 int main() { int array[SIZE] = {5, 3,9, 123,0, 293, 2394, 2,-1, -232}; int n; for (n=0; n < SIZE ; n++) { printf("Element array[%2d] = %5d, memory address %d\n", n, array[n], &array[n]); } return 0; }

20 Πίνακες ως ορίσματα συναρτήσεων Ορίσματα: Δίνουμε το όνομα του πίνακα μόνο: int myArray[ 24 ]; float getMean(int myArray[],int length) { int i; float sum = 0; for (i = 0; i < length; i++) sum += myArray[i]; return sum/length; } getMean( myArray, 24 ); Συνήθως περνάμε μαζί και το μέγεθος του πίνακα –Οι πίνακες πέρνιουνται call-by-reference –Το όνομα του πίνακα είναι και δείκτης στο 1 ο στοιχείο –Η συνάρτηση έχει πρόσβαση στο σημείο αποθήκευσης του πίνακα Περνάμε στοιχεία του πίνακα –call-by-value –Περνάμε όνομα[θέση]: myArray[ 3 ]

21 #include void f(int a[], int size, int b); int main() { int c[10] = {0}; int n; int q = 30; // Print the values of the array before // the function call for (n=0; n < 10; n++) printf("%2d, %3d\n", n, c[n]); printf("\nq = %d\n\n", q); f(c, 10, q); /* Print the values of the array AFTER the function call Notice: the values of the array elements have changed. The value of q has not changed.*/ for (n=0; n < 10; n++) printf("%2d, %3d\n", n, c[n]); printf("\nq = %d\n", q); return 0; } void f(int a[], int size, int b) { for (; size; ) a[size-1] = size--; b = 100; }

22 #include int main() { int magic[3][3] = { {8, 1, 6}, {3, 5, 7}, {4, 9, 2} }; int i, j, sum; int sumrows[3]; int sumcolumns[3]; int sumdiagonal1; int sumdiagonal2; // Print the magic square for (i=0; i < 3; i++) { for (j = 0; j < 3; j++) { printf("%3d", magic[i][j]); } printf("\n"); } // Now check that it is a magic square: // all rows and columns need to add to 15 sumdiagonal1 = 0; sumdiagonal2 = 0; for (i = 0 ; i < 3; i++) { sumrows[i] = 0; sumcolumns[i] = 0; for (j = 0 ; j < 3; j++) { sumrows[i] += magic[i][j]; sumcolumns[i]+= magic[j][i]; } sumdiagonal1 += magic[i][i]; sumdiagonal2 += magic[i][2-i]; } for (i=0; i < 3 ; i++) { printf("Sum Row %d = %d\n", i, sumrows[i]); printf("Sum Column %d = %d\n", i, sumcolumns[i]); } printf("Sum diagonal 1 is %d\n", sumdiagonal1); printf("Sum diagonal 2 is %d\n", sumdiagonal2); return 0; }

23 void displayValues(int[][MAX_COLS]) { int i,j; for(i=0;i<MAX_ROWS;i++) { for(j=0;j<MAX_COLS;j++) printf("%4d ", t[i][j]); printf("\n"); }

24 Add matrices int i,j; for (i=0;i<MAX_ROWS;i++) { for(j=0;j<MAX_COLS;j++) result[i][j]=a[i][j]+b[i][j]; } displayValues(result);

25 Subtract matrices int i,j; for(i=0;i<MAX_ROWS;i++) { for(j=0;j<MAX_COLS;j++) result[i][j]=a[i][j]-b[i][j]; } displayValues(result);

26 Συχνότερη εμφάνιση στοιχείου int commonGrade(int *flow, int nrGrades) { int grade[5] = {0}, commonGrade = 0, i; for(i = 0; i < nrGrades; i++) grade[flow[i] -1]++; for(i = 1; i < 5; i++) { if(grade[i] > grade[commonGrade]) commonGrade = i; } return grade[commonGrade]; }

27 33 34/* Find the minimum grade */ 35int minimum( const int grades[][ EXAMS ], 36 int pupils, int tests ) 37{ 38 int i, j, lowGrade = 100; 39 40 for ( i = 0; i <= pupils - 1; i++ ) 41 for ( j = 0; j <= tests - 1; j++ ) 42 if ( grades[ i ][ j ] < lowGrade ) 43 lowGrade = grades[ i ][ j ]; 44 45 return lowGrade; 46} 47

28 48/* Find the maximum grade */ 49int maximum( const int grades[][ EXAMS ], 50 int pupils, int tests ) 51{ 52 int i, j, highGrade = 0; 53 54 for ( i = 0; i <= pupils - 1; i++ ) 55 for ( j = 0; j <= tests - 1; j++ ) 56 if ( grades[ i ][ j ] > highGrade ) 57 highGrade = grades[ i ][ j ]; 58 59 return highGrade; 60}

29 for (i = 0 ; i < 3; i++) { sumrows[i] = 0; sumcolumns[i] = 0; for (j = 0 ; j < 3; j++) { sumrows[i] += magic[i][j]; sumcolumns[i]+= magic[j][i]; } sumdiagonal1 += magic[i][i]; sumdiagonal2 += magic[i][2-i]; }

30 Straight Selection SORT for (i = 0; i < array_size-1; i++) { min = i; for (j = i+1; j < array_size; j++) if (numbers[j] < numbers[min]) min = j; temp = numbers[i]; numbers[i] = numbers[min]; numbers[min] = temp; }

31 void shiftArray(int *p, int N, int shift) { int i; /* if shifting right */ if (shift > 0 && shift < N) { for (i = N - 1 - shift; i >= 0; i --) p[i + shift] = p[i]; for (i = shift - 1; i >= 0; i --) p[i] = 0; } /* if shifting left */ else if (shift < 0 && -shift < N) { shift = -shift; for (i = 0; i <= N - 1 - shift; i++) p[i] = p[i + shift]; for (i = N - shift; i < N; i++) p[i] = 0; }

32 Binary Search –με επανάληψη int binaryLoopSearch(int p[], int searchkey, int low, int high) { int middle; while ( low <= high ) { middle = (low + high ) / 2; if (searchkey == p[middle]) return middle; else if (searchkey < p[middle] ) high = middle – 1; else low = middle + 1; } return -1; }

33 Binary Search –με αναδρομή int binarySearch(int p[], int searchkey, int low, int high) { int middle; middle = (low + high ) / 2; if (high < low) return -1; if (searchkey == p[middle]) return middle; else if (searchkey < p[middle]) return binarySearch(p, searchkey, low, middle- 1); else return binarySearch(p, searchkey, middle+1,high); return -1; }

34 Δείκτες int Counter = 7; int *PointerToCounter; PointerToCounter = &Counter; ΌνομαΘέση Μνήμης Τιμή …… Counter2310007 …… PointerToCounter234000231000 count 7 7 countPtr

35 Τελεστές Δεικτών * (indirection/dereferencing operator) int y = 5; int *yPtr; yPtr = &y; *yPtr = *yPtr * 2; –Μπορώ να αλλάζω την τιμή των μεταβλητών με τη βοήθεια δεικτών –Η τιμή του y γίνεται ίση με 10 –Η μεταβλητή y αλλάζει τιμή, χωρίς στον κώδικα να φαίνεται αυτό άμεσα σε μια εντολή που εμφανίζει την y! –H y δηλαδή, αποκτά ένα «ψευδώνυμο»: το *yPtr * και & είναι ανάποδα και αλληλοακυρώνονται

36 1/* 2 Using the & and * operators */ 3#include 4 5int main() 6{6{ 7 int a; /* a is an integer */ 8 int *aPtr; /* aPtr is a pointer to an integer */ 9 10 a = 7; 11 aPtr = &a; /* aPtr set to address of a */ 12 13 printf( "The address of a is %p" 14 "\nThe value of aPtr is %p", &a, aPtr ); 15 16 printf( "\n\nThe value of a is %d" 17 "\nThe value of *aPtr is %d", a, *aPtr ); 18 19 printf( "\n\nShowing that * and & are inverses of " 20 "each other.\n&*aPtr = %p" 21 "\n*&aPtr = %p\n", &*aPtr, *&aPtr ); 22 23 return 0; 24} The address of a is 0012FF88 The value of aPtr is 0012FF88 The value of a is 7 The value of *aPtr is 7 Proving that * and & are complements of each other. &*aPtr = 0012FF88 *&aPtr = 0012FF88 The address of a is the value of aPtr. The * operator returns an alias to what its operand points to. aPtr points to a, so *aPtr returns a. Notice how * and & are inverses

37 1/* 2 Cube a variable using call-by-reference 3 with a pointer argument */ 4 5#include 6 7void cubeByReference( int * ); /* prototype */ 8 9int main() 10{ 11 int number = 5; 12 13 printf( "The original value of number is %d", number ); 14 cubeByReference( &number ); 15 printf( "\nThe new value of number is %d\n", number ); 16 17 return 0; 18} 19 20void cubeByReference( int *nPtr ) 21{ 22 *nPtr = *nPtr * *nPtr * *nPtr; /* cube number in main */ 23} The original value of number is 5 The new value of number is 125 Notice how the address of number is given - cubeByReference expects a pointer (an address of a variable). Inside cubeByReference, *nPtr is used ( *nPtr is number ). Notice that the function prototype takes a pointer to an integer ( int * ).

38 1/* Fig. 7.15: fig07_15.c 2 This program puts values into an array, sorts the values into 3 ascending order, and prints the resulting array. */ 4#include 5#define SIZE 10 6void bubbleSort( int *, const int ); 7 8int main() 9{9{ 10 11 int a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 12 int i; 13 14 printf( "Data items in original order\n" ); 15 16 for ( i = 0; i < SIZE; i++ ) 17 printf( "%4d", a[ i ] ); 18 19 bubbleSort( a, SIZE ); /* sort the array */ 20 printf( "\nData items in ascending order\n" ); 21 22 for ( i = 0; i < SIZE; i++ ) 23 printf( "%4d", a[ i ] ); 24 25 printf( "\n" ); 26 27 return 0; 28} 29 30void bubbleSort( int *array, const int size ) 31{ 32 sort gets passed the address of array elements (pointers). The name of an array is a pointer. void swap( int *, int * );

39 33 int pass, j; 34 for ( pass = 0; pass < size - 1; pass++ ) 35 36 for ( j = 0; j < size - 1; j++ ) 37 38 if ( array[ j ] > array[ j + 1 ] ) 39 swap( &array[ j ], &array[ j + 1 ] ); 40} 41 42void swap( int *element1Ptr, int *element2Ptr ) 43{ 44 int hold = *element1Ptr; 45 *element1Ptr = *element2Ptr; 46 *element2Ptr = hold; 47} Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45

40 Αριθμητική Δεικτών Στους δείκτες μπορούμε να πραγματοποιούμε αριθμητικές πράξεις: –++ ή – - Ο δείκτης δείχνει στο επόμενο ή προηγούμενο αντικείμενο, δηλ. αν είναι δείκτης σε ακέραιο στον επόμενο ή προηγούμενο ακέραιο –Αντίστοιχα για + ή +=, - ή -= –Οι δείκτες μπορούν να αφαιρούνται ο ένας από τον άλλο –Όλες αυτές οι πράξεις δεν έχουν νόημα εκτός αν πραγματοποιούνται πάνω δείκτη που δείχνει στα στοιχεία ενός πίνακα

41 Πίνακας 5 στοιχείων τύπου int σε μηχανή με 4 byte int s –int v[5]; –int *vPtr; vPtr = &v[0] ή vPtr = v; //δείχνει στο πρώτο στοιχείο v[0] // vPtr στο 3000 –vPtr += 2; // vPtr στο 3008 vPtr δείχνει στο v[ 2 ] (αύξηση κατά 2), μια και η μηχανή έχει 4 byte int s, οπότε δείχνει 3008 pointer variable vPtr v[0]v[1]v[2]v[4]v[3] 30003004300830123016 location

42 Πίνακες από δείκτες Ένας πίνακας μπορεί να περιέχει και δείκτες Παράδειγμα: ένας πίνακας από strings char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" }; –Περιέχει δείκτες στον 1 ο κάθε φορά χαρακτήρα –char * – κάθε στοιχείο του suit είναι δείκτης σε char –Τα strings στην πραγματικότητα δεν αποθηκεύονται στον πίνακα suit, μόνο δείκτες αποθηκεύονται στον πίνακα –Το suit έχει σταθερό μέγεθος (ως πίνακας άλλωστε), αλλά τα αλφαριθμητικά μπορούν να έχουν όποιο μέγεθος επιθυμούμε suit[3] suit[2] suit[1] suit[0]’H’’e’’a’’r’’t’’s’ ’\0’ ’D’’i’’a’’m’’o’’n’’d’’s’ ’\0’ ’C’’l’’u’’b’’s’ ’\0’ ’S’’p’’a’’d’’e’’s’ ’\0’

43 Δυναμική Διαχείριση Μνήμης Μέχρι τώρα στατική ανάθεση και δέσμευση μνήμης –Ζητούσαμε στο πρόγραμμά μας τη μέγιστη μνήμη που μπορεί να χρειαζόμασταν –#define MAX_SIZE10000 –int array[MAX_SIZE]; –Μειονέκτημα : Υπάρχουν εφαρμογές που το MAX_SIZE είναι άγνωστο οπότε αναγκαζόμαστε να δηλώνουμε μεγάλες τιμές και να χάνουμε και σε μνήμη και σε ταχύτητα Δυναμική κατανομή μνήμης (dynamic memory allocation) –Αίτηση από το λειτουργικό να μας παραχωρήσει μνήμη –Ειδοποίηση στο λειτουργικό ότι δεν χρειαζόμαστε πια ένα μέρος μνήμης –Ό,τι δεσμεύετε πρέπει να αποδεσμεύετε

44 Συναρτήσεις Δυναμικής Διαχείρισης Μνήμης Βρίσκονται στην stdlib.h void *malloc( size_t numBytes); – Δεσμεύει numBytes αριθμό από διαδοχικά Bytes και επιστρέφει ένα δείκτη στην αρχή της δεσμευμένης θέση μνήμης – Επιστρέφει NULL αν δεν μπορεί να δεσμεύσει άλλη μνήμη int *ptr = (int *) malloc (100*sizeof(int));

45 Συναρτήσεις Δυναμικής Διαχείρισης Μνήμης void free(void *pointer); –Αποδεσμεύει τη μνήμη που έχει δεσμευτεί με μία από τις προηγούμενες κλήσεις στην malloc, calloc ή realloc –Δεν πρέπει να αποδεσμεύουμε πάνω από μια φορά την ίδια μνήμη ptr = (int *)malloc (100*sizeof(int)); free(ptr); // Αυτό είναι οκ μέχρι εδώ free(ptr); // Αποδεσμεύουμε την ίδια μνήμη // δυο φορές ! ΛΑΘΟΣ

46 Δυναμικοί Πίνακες Πίνακες που το μέγεθος τους καθορίζεται κατά την εκτέλεση του προγράμματος ( σε run-time). Δυνατότητα προσαρμογής στις εκάστοτε απαιτήσεις χωρίς ανάγκη περιορισμού. int *x = (int *)malloc( 10 * sizeof(int)); x

47 Πρόβλημα 1: Αποτυγχάνει η Δέσμευση Πρέπει να γίνεται πάντα έλεγχος επιστροφής της απαραίτητης μνήμης !! Είναι ευθύνη του προγραμματιστή και στοιχείο σωστού προγραμματισμού! Οι συναρτήσεις δυναμικής δέσμευσης επιστρέφουν NULL όταν αποτυγχάνουν, το οποίο μπορούμε να εξετάσουμε και να διακόψουμε την εκτέλεση του προγράμματος αν χρειάζεται int *p = (int *)malloc(10000*sizeof(int)); if (p == NULL) { printf( “ No Memory Available\n ” ); exit(0); }

48 Πρόβλημα 2: Διαρροή Μνήμης Απελευθέρωση –Πρέπει να ελευθερώνουμε την μνήμη όταν δεν την χρειαζόμαστε (με την free) Δεν ελευθερώνουμε ποτέ μνήμη που δεν έχει αποκτηθεί δυναμικά (λ.χ. με malloc) Αν δεν ελευθερώσουμε όλη τη μνήμη που δεσμεύουμε αυτό ονομάζεται διαρροή μνήμης (memory leak)

49 Πρόβλημα 3: Χρήση Μετά την Αποδέσμευση –Κάνουμε free και μετά ξαναχρησιμοποιούμε την ίδια μνήμη –Παρόμοια αποτελέσματα όταν χρησιμοποιούμε μη δεσμευμένη μνήμη Αλλάζουμε μεταβλητές που χρησιμοποιούμε χωρίς να το ξέρουμε – δύσκολα ανιχνεύεται Πάμε να γράψουμε σε μνήμη που δεν μας ανήκει (segmentation fault) και το πρόγραμμα διακόπτεται αυτόματα

50 Πρόβλημα 4: Αποδέσμευση μνήμης που δεν έχουμε δεσμεύσει –Μπορεί να μπερδέψει το λειτουργικό στην διαχείριση ελεύθερης μνήμης

51 Δείκτες σε δείκτες char ch; char *pch; char **ppch; char ***ppch; Δείκτης σε πίνακα από δείκτες (άγνωστο στην αρχή και το μέγεθος του πίνακα και το μέγεθος των περιοχών που δείχνουν οι δείκτες)

52 #include int main(void) { int lines = 5; /* Both lines and cols could be evaluated */ int cols = 10; /* or read in at run time */ int i, **Α; A = (int **)malloc(lines * sizeof(int *)); if (A == NULL) { puts("\nFailure to allocate room for row pointers.\n"); exit(0); } for (i = 0; i < lines; i++) { Α[i] = (int *) malloc(cols * sizeof(int)); if (Α[i] == NULL) { printf("\nFailure to allocate for row[%d]\n",i); exit(0); } printf("\n%d %p %d", i, Α[i], Α[i]); if (i > 0) printf(" %d",(int)(Α[i] - Α[i-1])); } //free the memory for (i = 0; i < lines; i++) free (Α[i]); free(A); return 0; } A A[0] A[1] A[2] A[3] A[4] A[0][0] A[0][1] A[0][2] … A[1][0]... A[2][0]... A[i][j] A[3][0]... A[4][0]... A[4][9]

53 A = (int **)malloc(lines * sizeof(int *)); if (A == NULL) { puts("\nFailure to allocate room for row pointers.\n"); exit(0); } for (i = 0; i < lines; i++) { Α [i] = (int *) malloc(cols * sizeof(int)); if ( Α [i] == NULL) { printf("\nFailure to allocate for row[%d]\n",i); exit(0); } printf("\n%d %p %d", i, Α [i], Α [i]); if (i > 0) printf(" %d",(int)( Α [i] - Α [i-1])); }

54 //free the memory for (i = 0; i < lines; i++) free ( Α [i]); free(A);

55 Πρόβλημα : Εκτυπώστε ανάστροφα το κείμενο που θα διαβαστεί από την οθόνη. #include #define N 100 void inversion(char *s) { int i; for (i = strlen(s)-1; i >= 0; --i) printf("%c",s[i]); printf(“\n”); } int main() { char s[N]; printf("Dwste mia le3h mexri %d xarakthres\n",N); scanf("%s",s); inversion(s); return 0; }

56 Διαχείριση Αλφαριθμητικών Βρίσκονται στο Μετατρέπουν αλφαριθμητικά (αν είναι κατάλληλα) σε αριθμητικές τιμές

57 Συναρτήσεις Ανάγνωσης και Εκτύπωσης int sprintf(char *s, const char *format, …) Ισοδύναμη με την printf μόνο που η έξοδος είναι στο string s και όχι στην οθόνη int sscanf(char *s, const char *format, …) Ισοδύναμη με την scanf μόνο που η είσοδος είναι από το string s και όχι από το πληκτρολόγιο char s[100]; char f[] = "1.45 2.2 0.12"; float t1,t2,t3; sprintf(s,"%s",f); sscanf(s,"%f %f %f",&t1,&t2,&t3); printf("s = %s\nt1 = %f t2 = %f t3 = %f\n",s,t1,t2,t3);

58 Χρήσιμες Συναρτήσεις (string.h) size_t strlen( const char *s ); –Επιστρέφει τον αριθμό των χαρακτήρων πριν το ‘ \0 ’ που βρίσκονται στο s ( το μήκος string) char *strdup(const char *s1); –Δεσμεύει όση μνήμη χρειάζεται και αντιγράφει σε αυτήν το αλφαριθμητικό στο s1. Επιστρέφει την καινούργια μνήμη με το καινούργιο αντίγραφο του s1. Η δεσμευμένη μνήμη χρειάζεται να αποδεσμευτεί στο τέλος με την free.

59 Συναρτήσεις σύγκρισης (string.h) Σύγκριση αλφαριθμητικών –Συγκρίνονται οι ASCII κώδικες των χαρακτήρων int strcmp( const char *s1, const char *s2 ); –Συγκρίνει το s1 με το s2 –Επιστρέφει αρνητικό αριθμό αν s1 s2

60 Φανταστείτε : Έχουμε ονόματα όπως: –Smith, David –Leahy, Bill –Dagon, David –Humperdinck, Englebert Υποθέστε πως θέλουμε να τα ταξινομήσουμε αλφαβητικά αλλά παρατηρούμε πως είναι διαφορετικού μεγέθους. Αντί να χρησιμοποιήσουμε έναν αλγόριθμο ταξινόμησης που αλλάζει character strings around γιατί να μην χρησιμοποιήσουμε έναν πίνακα από δείκτες και να αλλάζουμε δείκτες; – πολύ πιο γρήγορο

61 Έχουμε έναν πίνακα από pointers Leahy, Bill Smith, David Dagon, David Humperdinck, Englebert name[0] name[1] name[3] name[2]

62 Ταξινόμηση με μετακίνηση δεικτών Leahy, Bill Smith, David Dagon, David Humperdinck, Englebert name[0] name[1] name[3] name[2]

63 Η Βιβλιοθήκη Εισόδου/Εξόδου Στο stdio.h –Δηλώνεται ο τύπος δεδομένων FILE (με typedef) με όλες τις πληροφορίες που χρειάζονται για προσπέλαση του αρχείου από τις αντίστοιχες συναρτήσεις –Ορίζονται 3 αρχεία stdin, stdout, stderr (θα δούμε ποια είναι αυτά σε λίγο) –Ορίζονται οι τιμές των σταθερών NULL EOF (End Of File) –Δηλώνονται συναρτήσεις προσπέλασης αρχείων

64 Άνοιγμα Αρχείων FILE *fp; –Δημιουργεί έναν FILE pointer με όνομα fp FILE *fopen(const char *filename, const char *mode); –Δύο ορίσματα: filename: το όνομα του αρχείου που θα ανοίξει mode: Καθορίζει αν το αρχείο ανοιχτεί για διάβασμα ή γράψιμο –Η fopen επιστρέφει έναν FILE pointer στο αρχείο Σε περίπτωση αποτυχίας επιστρέφει NULL

65 Table of file open modes Mo de Περιγραφή r(read) Άνοιγμα μόνο για διάβασμα w(write) Άνοιγμα για γράψιμο. Αν δεν υπάρχει το αρχείο το δημιουργεί, αν υπάρχει καθαρίζει τα περιεχόμενά του a(append) Άνοιγμα του αρχείου για προσάρτηση δεδομένων. Οι επόμενες εγγραφές προσαρτώνται στο τέλος του αρχείου.

66 main( ) { FILE *fp; char stuff[25]; int index; fp = fopen("TENLINES.TXT","w"); /* open for writing */ strcpy(stuff,"This is an example line."); for (index = 1;index <= 10;index++) fprintf(fp,"%s Line number %d\n",stuff,index); fclose(fp); /* close the file before ending program */ }

67 int main( ) { FILE *funny; int c; funny = fopen("TENLINES.TXT","r"); if (funny == NULL) { printf("File doesn’t exist\n"); return 1; } do { c = getc (funny); /* get one character from the file */ putchar (c); /* display it on the monitor */ } while (c != EOF); /* repeat until EOF (end of file) */ fclose(funny); }

68 void filecopy(FILE *ifp, FILE *ofp) { int c; while ((c = getc(ifp)) != EOF) putc(c, ofp); }

69 Παράδειγμα #include... void somefunction(char *file) { FILE *fp; char s[1000]; if ((fp = fopen(file, "r")) == NULL) { printf( “ Can not open the file %s\n ”,file); return; } while (fscanf(fp, ” %s ”,s) != EOF) { printf( “ %s ”,s); } fclose(fp); }

70 Κλείσιμο Αρχείων Ότι ανοίγει, πρέπει να κλείνει –Ειδάλλως ενδέχεται να μην έχετε πρόσβαση σε κάποιο αρχείο για κάποιο διάστημα fclose( FILE pointer ) –«κλείνει» το συγκεκριμένο αρχείο –Επιστρέφει 0 αν είναι επιτυχής και EOF διαφορετικά –Γίνεται αυτόματα με το τέλος του προγράμματος –Είναι καλή πρακτική να γίνεται από τον προγραμματιστή

71 Συναρτήσεις για Ανάγνωση και Εγγραφή Κειμένου fgetc –Διαβάζει έναν χαρακτήρα από αρχείο –Όρισμα: FILE pointer –fgetc( stdin ) ισοδύναμο με getchar() fputc –Γράφει έναν χαρακτήρα σε αρχείο –Όρισμα: FILE pointer και ένας χαρακτήρας για να γραφεί –fputc( 'a', stdout ) ισοδύναμο με putchar( 'a' ) fgets –Διαβάζει μια γραμμή από ένα αρχείο – char *fgets(char *line, int maxline, FILE *fp) fputs –Γράφει μια γραμμή σε ένα αρχείο – int fputs(char *line, FILE *fp) fscanf / fprintf –Ισοδύναμες των scanf και printf για αρχεία

72 Τρία Ειδικής Χρήσης Αρχεία Το λειτουργικό σύστημα, με το που αρχίζει να τρέχει το πρόγραμμά, ανοίγει τρία αρχεία και ορίζει τους δείκτες stdin, stdout, stderr να δείχνουν στις αντίστοιχες δομές FILE. Κανονικά : –stdin: αντιστοιχεί στο πληκτρολόγιο! Ότι κουμπί πατιέται θεωρείται ότι διαβάζεται από ένα αρχείο –stdout: αντιστοιχεί στην οθόνη μας. Ότι εγγράφετε σε αυτό το αρχείο εκτυπώνεται στην οθόνη –stderr: αντιστοιχεί επίσης στην οθόνη μας. Χρησιμοποιείτε για μηνύματα λάθους. Αναδιεύθυνση του Unix –Μπορούμε να δηλώσουμε στο λειτουργικό να συνδέσει τα παραπάνω «αρχεία» με πραγματικά (αντί για το πληκτρολόγιο και την οθόνη) –myprogram < someinputfile Το stdin δεν είναι πλέον το πληκτρολόγιο, αλλά το αρχείο somefile –myprogram > someoutputfile Το stdout δεν είναι πλέον η οθόνη αλλά το someoutputfile

73 #include int main() { int i; FILE *fp; if ((fp = fopen("myfirstfile.txt", "w")) == NULL) { printf("Could not open file.\n"); return 0; } fprintf(fp, "Lets write something here.\n"); for (i = 0; i < 10; ++i) fprintf(fp, “%5d, %5d, %5d\n“,i,i*i,i*i*i); fclose(fp); // Check out the contents of the file myfirstfile.txt } Lets write something here. 0, 0, 0 1, 1, 1 2, 4, 8 3, 9, 27 4, 16, 64 5, 25, 125 6, 36, 216 7, 49, 343 8, 64, 512 9, 81, 729

74 1 2 3#include 4 5int main() 6{6{ 7 int account = 1; 8 char name[ 30 ]; 9 double balance; 10 FILE *cfPtr; /* cfPtr = clients.dat file pointer */ 11 12 if ( ( cfPtr = fopen( "clients.dat", "w" ) ) == NULL ) 13 printf( "File could not be opened\n" ); 14 else { 15 printf( "Enter the account, name, and balance.\n" ); 16 printf( "Enter EOF to end input.\n" ); 17 printf( "? " ); 18 scanf( "%d%s%lf", &account, name, &balance ); 19 20 while (account > 0) { 21 fprintf( cfPtr, "%d %s %.2f\n", 22 account, name, balance ); 23 printf( "? " ); 24 scanf( "%d%s%lf", &account, name, &balance ); 25 } 26 27 fclose( cfPtr ); 28 } 29 30 return 0; 31} Enter the account, name, and balance. Enter EOF to end input. ? 100 Jones 24.98 ? 200 Doe 345.67 ? 300 White 0.00 ? 400 Stone -42.16 ? 500 Rich 224.62 ?


Κατέβασμα ppt "Γενική Δομή Προγράμματος Λίστα από συναρτήσεις - main() Τύπος-επιστρεφόμενης-τιμής όνομα(λίστα-παραμέτρων) { δηλώσεις μεταβλητών λίστα εντολών } /*Επιστρέφει."

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google