ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

...ασύγχρονα μαθήματα γλώσσας C

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό Star_Light » 26 Ιουν 2011, 23:30

Eυχαριστω migf1 σαν να εχω αρχισει να τα ξεδιαλυνω!

επομενως αλλο βιβλιοθηκες αλλο header files. OK απλα αυτο που νομιζα εγω σαν βιβλιοθηκες ειναι τελικα τα header files.

Γιατι με μπερδεψε η εξηγηση του συναδελφου sv1jsb ρε παιδι μου....

viewtopic.php?f=61&t=18772

αθελα του βεβαια θα με μπερδεψε αλλα τσεκαρε λιγο...

και για να σε διευκολυνω κιολας αστο και θα στο παραθεσω ως ειχε

"Θα ήθελα να προσθέσω ότι ο χωρισμός ενός προγράμματος σε επιμέρους αρχεία γίνεται και για δύο ακόμα λόγους.
Ο πρώτος και κυριότερος είναι η επαναχρησιμοποίηση, ή αλλιώς δημιουργία βιβλιοθηκών. Στο παραπάνω παράδειγμα το αρχείο module.c μπορεί να χρησιμοποιηθεί και σε άλλο πρόγραμμα που ίσως να χρειάζεται πχ το παραγοντικό. (Με αυτό το σκεπτικό η συνάρτηση main_interface δεν "κολλάει" στο module.c αν θέλουμε να το έχουμε σαν βιβλιοθήκη μας. Μπορεί σε άλλο πρόγραμμα που θα φτιάξουμε να μην έχουμε επαφή με τον χρήστη αλλά να θέλουμε τον παραγοντικό υπολογισμό.). Φανταστείτε τι θα μπορούσες να κάνεις σε C αν δεν υπήρχαν οι βιβλιοθήκες. Τίποτα. Η γλώσσα αυτή καθ' αυτή είναι πολύ λιτή. Όλες οι δυνατότητες της έρχονται από τις βιβλιοθήκες της."

ΣΤην αρχη οκ λεει οτι μπορει να χρησιμοποιηθει στην δημιουργια βιβλιοθηκων.... ως εδω ειμαστε οκ.

ΑΛλα πιο κατω.... μπερδευομαι... φυσικα δεν λογοκρινω τον συναδελφο απλα θελω να το καταλαβω τελειως.
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό migf1 » 27 Ιουν 2011, 01:29

Ο πιο απλός τρόπος να το εξηγήσω με ζωντανό & λειτουργικό παράδειγμα, είναι το πρόγραμμα της Ξερής που έχω ανεβάσει στο σχετικό νήμα: viewtopic.php?f=6&t=19080

Αποτελείται από 3 .c και 2 .h αρχεία:
Κώδικας: Επιλογή όλων
main.c
stack.c
s.c
stack.h
s.h

Ας ξεχάσουμε για λίγο τελείως τις βιβλιοθήκες. Αν ανοίξεις και δεις το αρχείο stack.h θα διαπιστώσεις πως αποτελείται από 3 λογικές ενότητες:
  1. macros (#define)
  2. ορισμό της δομής Cardstack (και μάλιστα προβιβασμό της σε πρόσθετο τύπο δεδομένων, μέσω της εντολής typedef)
  3. τα πρότυπα όσων συναρτήσεων ορίζονται μέσα στο αρχείο: stack.c
Το αρχείο stack.c είναι ουσιαστικά το "module" του προγράμματος που ασχολείται αποκλειστικά και μόνο με τη διαχείριση στοιβών. Περιέχει δηλαδή μόνο συναρτήσεις που ασχολούνται με τη διαχείριση των στοιβών και τίποτε άλλο.

Επειδή όμως αυτές οι συναρτήσεις όπως θα δεις χρησιμοποιούν τόσο τον πρόσθετο τύπο δεδομένων Cardstack (που τον έχω ορίσει στο αρχείο: stack.h) όσο και τα macros (που επίσης έχω ορίσει στο αρχείο: stack.h) έχω συμπεριλάβει στην αρχή τη γραμμή:
Κώδικας: Επιλογή όλων
#include "stack.h"
(μη σε απασχολούν οι γραμμές: #ifndef STACK_H και #endif για τώρα). Χωρίς αυτό το include το compilation του stack.c θα χτύπαγε!

Όταν κάνεις include ένα αρχείο μέσα σε ένα άλλο, τότε αυτό που συμβαίνει είναι πως τα περιεχόμενα του included αρχείου αντιγράφονται στο σημείο που υπάρχει η γραμμή #include. Η απόφαση να μπουν σε ξεχωριστό .h αρχείο τα macros, τα πρότυπα και οι πρόσθετοι τύπο δεδομένων των στοιβών πάρθηκε διότι αυτά θέλω να τα χρησιμοποιήσω ΚΑΙ στο αρχείο: main.c

Αντί λοιπόν να τα ξαναγράφω και στο main.c απλά κάνω πάλι ένα: #include "stack.h" και στην αρχή του main.c.

Oι γραμμές: #ifndef STACK_H και #endif που περικλείουν τη γραμμή του #include (και σου είπα παραπάνω να τις αγνοήσεις) είναι για να σιγουρέψουν πως τα περιεχόμενα του αρχείου: stack.h θα γίνουν compiled μια μόνο φορά για όλο το πρόγραμμα και όχι πολλές φορές (μια για κάθε .c αρχείο που κάνει include αυτό το header file). Και να μην τις βάλεις, δεν υπάρχει πρόβλημα, απλά θα καθυστερήσει λιγάκι ο χρόνος του compilation. Ονομάζεται "Include Guard", αλλά για να μην πλατιάσουμε πολύ, διάβασε λεπτομέρειες εδώ: http://en.wikipedia.org/wiki/Include_guard

Το ίδιο ακριβώς πράγμα κάνω και με το αρχείο: s.h που το κάνω κι αυτό include στο αρχείο: main.c προκειμένου να μπορώ να χρησιμοποιήσω μέσα στο main.c τις συναρτήσεις διαχείρισης strings, που έχω ορίσει στο αρχείο: s.c. Σε αντίθεση με το stack.h, το s.h περιέχει μονάχα τα πρότυπα των συναρτήσεων του αρχείου: s.c (αν οι συναρτήσεις χρειάζονταν εξειδικευμένα macros, πρόσθετους τύπους, κλπ θα τα είχα γράψει κι αυτά μέσα στο s.h, αλλά οι συγκεκριμένες δεν χρειάζονται).

Οπότε πιστεύω πλέον να είναι ξεκάθαρος ο ρόλος των header file (αν όχι, εδώ είμαστε :) )

Πες τώρα πως το αρχείο s.c θέλεις να το κάνεις βιβλιοθήκη, μιας και οι συναρτήσεις που περιέχει είναι τελείως γενικής φύσεως και μπορούν να χρησιμοποιηθούν ατόφιες όπως είναι όχι μόνο στο πρόγραμμα της ξερής, αλλά και σε οποιοδήποτε άλλο πρόγραμμα (το ίδιο πράγμα δεν ισχύει για τις συναρτήσεις των στοιβών στο stack.c, γιατί εκείνες είναι εξαρτημένες από τον τύπο int στο πεδίο data, ενώ σε άλλα προγράμματα μπορεί οι στοίβες να μην δέχονται int αλλά άλλον τύπο δεδομένων).

Θα χρησιμοποιήσεις λοιπόν την διαδικασία που σου περιέγραψα στο προηγούμενο post για να κάνεις compile μονάχα το αρχείο: s.c και κατόπιν με το εργαλείο ar θα μετατρέψεις το object file: s.o σε βιβλιοθήκη, με όνομα π.χ.: libs.a

Αντιγράφοντας τώρα το αρχείο: libs.a στον στάνταρ φάκελο /lib του gcc, και το αρχείο: s.h στον στάνταρ φάκελο /include του gcc, μπορείς πια σε ΟΠΟΙΟΔΗΠΟΤΕ πρόγραμμα φτιάχνεις να γράφεις στην αρχή του .c αρχείου του: "include <s.h> ώστε να χρησιμοποιήσεις οποιαδήποτε από τις συναρτήσεις στη βιβλιοθήκη: libs.a (που είναι δηλαδή οι συναρτήσεις του s.c). Εννοείται πως το αρχείο: s.c δεν χρειάζεται πια να το συμπεριλαμβάνεις στο compilation των προγραμμάτων, αφού το έχεις κάνεις βιβλιοθληκη (libs.a).

Θα πρέπει όμως στη γραμμή εντολών του gcc να του πεις να συμπεριλαμβάνει την βιβλιοθήκη στο compilation:
Κώδικας: Επιλογή όλων

gcc blablabla -ls

Οπότε όπως καταλαβαίνεις, με αυτό τον τρόπο όσο περνάει ο καιρός θα έχεις φτιάξει δικές σου βιβλιοθήκες που θα τις χρησιμοποιείς κατά βούληση σε όποιο νέο πρόγραμμα φτιάχνεις, χωρίς να ξαναγράφεις κώδικα για τις συναρτήσεις αυτών των βιβλιοθηκών ;)

ΥΓ. Ας κάνει ένας moderator τον κόπο να μεταφέρει όλα τα posts που εξηγούν τα περί header files και libraries είτε σε ξεχωριστό νήμα, είτε σε πιο κατάλληλο. Είναι λίγο κρίμα να μείνουν "θαμμένα" σε άσχετο με το αντικείμενό τους νήμα.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό Star_Light » 27 Ιουν 2011, 02:10

migf1 και ευχαριστω να πω θα ειναι λιγο!

Θα τα διαβασω και αυριο αυτα.

Προς το παρον ομως... τι λαθος κανω (λογικο) εδω

Κώδικας: Επιλογή όλων

#include<stdio.h>

typedef struct
{
int id;
char name[6];

} customer;

int main ()
{
customer array[2]={ 1 , "Kwstas" };
customer *p;


for(p=array; p<&array[3]; p++)

printf("%d %s \t", p->id , p->name);

return 0;
}


το προγραμμα τρέχει κανονικα και μου εμφανιζει αυτα που θελω.... αλλα μου πεταει και κατι περιεργα... μετα το 1 και το Κωστας πχ 0 και -1589696969 ?
κατι τετοιο :/ αρχικοποιησα την δομη με εναν πινακα απο δομες... και με δεικτες παω να κανω προσπελαση !
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό migf1 » 27 Ιουν 2011, 02:31

1. το name[6] θέλει name[7] για να έχει στο τέλος χώρο και για τον μηδενικό χαρακτήρα (το "Kwstas" έχει ήδη 6 χαρακτήρες)
2. η αρχικοποίηση του: customer array[2] καλό είναι να θέτει τιμές και για όλους τους customers (δίνεις μόνο για τον 1ο)
3. η συνθήκη του loop πρέπει να είναι: p < &array[2]; (το έχεις: p < &array[3];)

Κώδικας: Επιλογή όλων

#include<stdio.h>

typedef struct {
int id;
char name[7];
} customer;

int main ( void )
{
customer array[2] = {
{.id=1, .name="Kwstas"},
{.id=2, .name="Panos"}
};
customer *p;

for (p=array; p < &array[2]; p++)
printf("%d %s \t", p->id , p->name);

return 0;
}

Τελευταία επεξεργασία από migf1 και 27 Ιουν 2011, 02:46, έχει επεξεργασθεί 1 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό migf1 » 27 Ιουν 2011, 02:35

Btw, είναι χρήσιμο τους πρόσθετους τύπους δεδομένων να τους βάζεις με κεφαλαίο το 1ο γράμμα, για να τους ξεχωρίζεις με την μια από τους στάνταρ τύπους της γλώσσας (π.χ. Customer αντί για customer)

Για τον ίδιο λόγο, είναι χρήσιμο να έχεις με όλα πεζά γράμματα τα ονόματα των μεταβλητών, όπως τα έχεις ήδη ;)
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό Star_Light » 27 Ιουν 2011, 02:46

migf1 έγραψε:1. το name[6] θέλει name[7] για να έχει στο τέλος χώρα και για τον μηδενικό χαρακτήρα (το "Kwstas" έχει ήδη 6 χαρακτήρες)
2. η αρχικοποίηση του: customer array[2] καλό είναι να θέτει τιμές και για όλους τους customers (δίνεις μόνο για τον 1ο)
3. η συνθήκη του loop πρέπει να είναι: p < &array[2]; (το έχεις: p < &array[3];)

Κώδικας: Επιλογή όλων

#include<stdio.h>

typedef struct {
int id;
char name[7];
} customer;

int main ( void )
{
customer array[2] = {
{.id=1, .name="Kwstas"},
{.id=2, .name="Panos"}
};
customer *p;

for (p=array; p < &array[2]; p++)
printf("%d %s \t", p->id , p->name);

return 0;
}




ααααα τωρα καταλαβα!!! Καλα τι διαολο ρε παιδι μου με το συμπαθειο κιολας
ολοκληρο βιβλιο Γκιουρδα εχω βγαλει πριν μιλησουμε εδω ... τιποτα δεν εμαθα?!
ΜΗπως φταιει που ειχα να την πιασω την C καιρο ??? κανα 2μηνο... πριν 15 μερες αρχισα παλι να ασχολουμαι ενεργα.

Εσυ τι πιστευεις? Μιας και εισαι Δασκαλος.
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό migf1 » 27 Ιουν 2011, 02:55

Star_Light έγραψε:
[snip]
Εσυ τι πιστευεις?
[snip]

Πιστεύω πως είναι απλά θέμα χρόνου να σου ξανα έρθουν. Όταν τα αφήνεις, δυστυχώς σε αφήνουν κι εκείνα, και χρειάζεται λίγος χρόνος για να επανέλθεις :)

Προσπάθησε μέχρι να ξαναβρεις την αυτοπεποίθησή σου να θυσιάζεις όπου μπορείς βελτιστοποίηση εις όφελος του ευανάγνωστου κώδικα.

Π.χ. αν σου έρχεται πιο φυσικό στο μάτι (και στο μυαλό) αντί να διατρέχεις τα arrays με pointer, διέτρεχέ τα με register int

π.χ.
Κώδικας: Επιλογή όλων

register int i;
for (i=0; i < 2; i++)
printf("%d %s \t", array[i].id ,array[i].name);


Έτσι κι αλλιώς, αν τον παραπάνω κώδικα τον κάνεις compile με το -Ο3 optimization flag του gcc (ενδεχομένως και με το -Ο2) πριν παράξει το εκτελέσιμο αρχείο θα τον μετατρέψει αυτόματα σε μορφή ίδια ή πολύ παραπλήσια με την εκδοχή του pointer ;)
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό Star_Light » 27 Ιουν 2011, 03:07

Παντως για να επανελθω και σε αυτα που λεγαμε για τις βιβλιοθηκες.... Θυμαμαι ειχα διαβασει πως ενα απο τα αρχεια DLL παρέχει την συνάρτηση CreateWindow η οποια χρησιμοποιείται απο προγράμματα οταν δημιουργείται ενα νεο παράθυρο στην οθόνη.
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό migf1 » 27 Ιουν 2011, 03:12

Μιλάς για Windows programming?

Αν ναι, υπάρχει φοβερό tutorial για beginners, το theForger's Win32 API Programming Tutorial. Αλλά θα πρότεινα πριν το αρχίσεις, να ξεκαθαρίσεις πρώτα με απλά παραδείγματα σε κονσόλα τη χρήση των structs, pointers και strings, σε Standard C.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: ΚΕΦΑΛΑΙΟ 6 - ΔΕΙΚΤΕΣ

Δημοσίευσηαπό Star_Light » 27 Ιουν 2011, 21:03

migf1 έγραψε:Μιλάς για Windows programming?

Αν ναι, υπάρχει φοβερό tutorial για beginners, το theForger's Win32 API Programming Tutorial. Αλλά θα πρότεινα πριν το αρχίσεις, να ξεκαθαρίσεις πρώτα με απλά παραδείγματα σε κονσόλα τη χρήση των structs, pointers και strings, σε Standard C.


BΑΣΙΚΑ ηθελα να πεταξω ενα ψεγμα ξερεις.... για να τα συνδυασουμε ολα μαζι.
Κοιτα το WIndows programming δεν θα μου αρεσε λογω νοοτροπιας κλειστου κωδικα.

Π.Σ Ενα προγραμμα αν τρεχει σε ενα συστημα Linux και οχι σε ενα συστημα Windows θα ειναι λογω ελλειψης βιβλιοθηκων ????
Γνώσεις ⇛ Linux: Βασικές ┃ Προγραμματισμός: Δέν θέλω μεροκάματο , θέλω C και κακο θάνατο! ┃ Αγγλικά: Lower
Λειτουργικό ⇛ Ubuntu 10.10 σε Dual Boot με Windows 7
Προδιαγραφές ⇛ Επεξεργαστής : Intel(R) Core(TM) i3 CPU 540 @3.07Ghz (64bit)
RAM : Kingston 2GB
HDD : Coreshare 500GB
Κάρτα Γραφικών : Intel Corporation Core Processor Integrated Graphics Controller(rev 18) (prog-if 00 [VGA controller]) [8086:0042]
Star_Light
superbTUX
superbTUX
 
Δημοσιεύσεις: 2787
Εγγραφή: 01 Μάιος 2010, 21:07
Τοποθεσία: Αθήνα
IRC: Star_Light
Εκτύπωση

ΠροηγούμενηΕπόμενο

Επιστροφή στο Μαθήματα C

cron