Τα πάντα για την C

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

Συντονιστής: konnn

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 11 Σεπ 2011, 21:28

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

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 11 Σεπ 2011, 21:31

migf1 έγραψε:Το ότι θες μεταβλητή για να χρησιμοποιήσεις μια δομή είναι θέμα γλώσσας. Το να μπορείς να αρχικοποιείς μεταβλητές τύπου struct μπήκε στη γλώσσα με την αναθεώρηση του 1999.


ΕΠειδη υπαρχει διαφορα αναμεσα στην αρχικοποιηση και την προσπελαση - χρησιμοποιηση ?
Γνώσεις ⇛ 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: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 11 Σεπ 2011, 21:55

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

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 12 Σεπ 2011, 00:40

δηλαδη οποτε θελω να περασω μια συναρτηση μεσα σε μια δομη θα γινεται ολο αυτο το πανηγυρι που γινεται πιο κατω? :lol: :lol:

500 κωστηδες σε ολο το προγραμμα.... μεχρι να το καταφερω να το δεχθει ο μεταγλωττιστης!!! απηυδησα... παω να ξαναβαπτιστω.

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

#include <stdio.h>
#define N 254 + 1
typedef struct person
{
int age;
char name[N];
char surname[N];
} kostas ;

kostas struct_function(kostas someone);


int main(void)
{

kostas someone;

struct_function(someone);

return 0;
}

kostas struct_function(kostas someone)
{


printf("Dwse to onoma sou: ");
fgets(someone.name,254,stdin);

printf("Dwse to epwnumo sou: ");
fgets(someone.surname,254,stdin);

printf("Dwse tin ilikia sou: ");
scanf("%d",&someone.age);


printf("========================================");

printf("\nTo onoma pou edwses einai: %s",someone.name);
printf("H ilikia pou edwses einai: %d",someone.age);
printf("\nTo epwnimo pou edwses einai: %s",someone.surname);

return someone;
}

Τελευταία επεξεργασία από Star_Light και 12 Σεπ 2011, 01:18, έχει επεξεργασθεί 1 φορά/ες συνολικά
Γνώσεις ⇛ 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: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 12 Σεπ 2011, 01:17

εφτασα και στο τελευταιο step πλεον πριν αρχισω να κοιταω τον κωδικα σου....

Δομες και δείκτες (μεσα σε συναρτηση)

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

#include <stdio.h>
#define N 254 + 1
typedef struct person
{
int age;
char name[N];
char surname[N];
} kostas ;

void struct_function(kostas *p);


int main(void)
{

kostas someone , *p;

p=&someone;

struct_function(p) ;

return 0;
}

void struct_function(kostas *p)
{


printf("Dwse to onoma sou: ");
fgets(p->name,254,stdin);

printf("Dwse to epwnumo sou: ");
fgets(p->surname,254,stdin);

printf("Dwse tin ilikia sou: ");
scanf("%d",&(*p).age);


printf("========================================");

printf("\nTo onoma pou edwses einai: %s",p->name);
printf("H ilikia pou edwses einai: %d",p->age);
printf("\nTo epwnimo pou edwses einai: %s",p->surname);

}


Λοιπον εχω καποιες βασικες αποριες ομως... ωρες ωρες οι δεικτες με βασανιζουν και δεν ξερω το γιατι....

1.
Κώδικας: Επιλογή όλων
struct_function(p)


Ουσιαστικα εδω ειναι κληση με τιμη , και η ιδια αυτη η τιμη ειναι η διευθυνση που δειχνει ο δεικτης p
αρα η διευθυνση της someone γιατι σε αυτην ειναι αρχικοποιημένος ε? Eιναι δηλαδη διευθυνση στην οποια ο δεικτης δειχνει
και οχι διευθυνση στην οποια θα "δουλευε" πχ αλλαζοντας τα περιεχομενα της και αρα επρεπε να βαλουμε και τον τελεστη & ας πουμε .. ε?

2.
Κώδικας: Επιλογή όλων
&(*p).age


αυτο ειναι η διευθυνση του στοιχειου age?
To (*p).age ειναι απο μονο του στοιχειο γιατι? Γιατι αμα το δωσεις μεσα σε μια printf αυτο θα σου δωσει ενα στοιχειο - εναν ακεραιο- ... αρα μαζι με το & δεν ειναι τιποτε αλλο απο διευθυνση σαν να λεγαμε οκ?

Κώδικας: Επιλογή όλων
int x;
&x => (& = ΔΙΕΥΘΥΝΣΗ) + x = στοιχειο) οποτε ολο μαζι διευθυνση στοιχειου


καταλαβαινεις πως το ρωταω...

3.
Ενα ονομα δομής θα μπορούσε να αποτελεί δείκτης προς την ιδια την δομη οπως και στους πινακες?

4. Λενε επισης πως για λογους προτεραιοτητας μπαινουν οι παρενθεσεις στο
Κώδικας: Επιλογή όλων
(*p).age


και πως αν δεν γινοταν αυτο... ο τελεστης (.) εχει μεγαλυτερη προτεραιοτητα αρα θα λαμβανε αυτον υποψη το συστημα και οχι τον (*)
που δεν ειναι λεει αυτο που θελουμε... και τι δηλαδη σημαινει αυτο???? Υπαρχει καμια εξηγηση ή να μην το σκαλισω γιατι θα μπλεξω?

ειναι καίριες ερωτήσεις!! ΕΥχαριστω εκ των προτερων.
Γνώσεις ⇛ 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: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 12 Σεπ 2011, 09:47

Καλημέρα,

Star_Light έγραψε:εφτασα και στο τελευταιο step πλεον πριν αρχισω να κοιταω τον κωδικα σου....

Δομες και δείκτες (μεσα σε συναρτηση)

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

#include <stdio.h>
#define N 254 + 1
typedef struct person
{
int age;
char name[N];
char surname[N];
} kostas ;

void struct_function(kostas *p);


int main(void)
{

kostas someone , *p;

p=&someone;

struct_function(p) ;

return 0;
}

void struct_function(kostas *p)
{


printf("Dwse to onoma sou: ");
fgets(p->name,254,stdin);

printf("Dwse to epwnumo sou: ");
fgets(p->surname,254,stdin);

printf("Dwse tin ilikia sou: ");
scanf("%d",&(*p).age);


printf("========================================");

printf("\nTo onoma pou edwses einai: %s",p->name);
printf("H ilikia pou edwses einai: %d",p->age);
printf("\nTo epwnimo pou edwses einai: %s",p->surname);

}

Έτσι όπως έχεις γράψει τον κώδικα μπερδεύονται τα πράγματα, ενώ είναι πολύ πιο απλά! Ο κώδικάς σου για να αντιστοιχεί και στην ανθρώπινη σκέψη και άρα να είναι μακράν πιο κατανοητός πρέπει να γραφτεί κάπως έτσι...

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

#include <stdio.h>
#include <stdlib.h> // για atoi()

// Macros

#define MAXSLEN (254 + 1) // MAXimum String LENgth

// Πρόσθετοι Τύποι Δεδομένων

typedef struct person // ορισμός δομής person ως πρόσθετο τύπο
{ // με το όνομα Person (λόγω του typedef)
char name[ MAXSLEN ]; // ... 1ο πεδίο της δομής
char surname[ MAXSLEN ]; // ... 2ο πεδίο της δομής
int age; // ... 3ο πεδίο της δομής
} Person; // το όνομα του πρόσθετου τύπου

// Πρότυπα Συναρτήσεων

char *s_getflushed(char *s, size_t len); // αντί fgets, για να μην κρατάει το '\n'
void read_person( Person *someone ); // για διάβασμα των πεδίων της someone
void print_person( Person someone ); // για τύπωμα των πεδίων της someone

// -------------------------------------------------------------------------------
int main( void )
{
Person someone; // η someone είναι μεταβλητή τύπου Person

read_person( &someone ); // πέρασμα της someone by reference
print_person( someone ); // πέρασμα της someone by value

return 0;
}
// -------------------------------------------------------------------------------
char *s_getflushed(char *s, size_t len)
{
char *cp;
for (cp=s; (*cp=getc(stdin)) != '\n' && (cp-s) < len-1; cp++ )
;

if ( *cp != '\n') { // len reached withoutn '\n'
*cp = '\0'; // null terminate s and
while (getchar() != '\n') // flush remaining chars
;
}
else // '\n' found
*cp = '\0'; // null-terminate

return s;
}
// -------------------------------------------------------------------------------
void read_person( Person *someone ) // by reference πέρασμα της someone
{ // άρα χρήση του -> για τα πεδία της
char inbuf[ 254+1 ] = {'\0'};

printf("Dwse to onoma sou: ");
s_getflushed( someone->name, MAXSLEN );

printf("Dwse to epwnumo sou: ");
s_getflushed( someone->surname, MAXSLEN );

printf("Dwse tin ilikia sou: ");
s_getflushed( inbuf, MAXSLEN );
someone->age = atoi( inbuf );

return;
}
// -------------------------------------------------------------------------------
void print_person( Person someone ) // by value πέρασμα της someone
{ // άρα χρήση τελείας για τα πεδία της
puts("========================================");

printf("To onoma pou edwses einai: %s\n", someone.name);
printf("To epwnimo pou edwses einai: %s\n", someone.surname);
printf("H ilikia pou edwses einai: %d\n", someone.age);

putchar('\n');

return;
}

Τον γέμισα με Ελληνικά σχόλια ελπίζοντας πως ξεκαθαρίζει τα πράγματα και μπορεί να χρησιμοποιηθεί και ως γρήγορος οδηγός για φρεσκάρισμα μνήμης. Εδώ και με syntax-highlighting: http://ideone.com/tw7BS

Ορίζουμε μια δομή struct person, την μετατρέπουμε σε πρόσθετο τύπο Person με το typedef και ορίζουμε μια μεταβλητή someone να είναι τύπου Person. Κατόπιν περνάμε την someone by reference στη συνάρτηση read_person() επειδή θέλουμε να διατηρηθούν οι αλλαγές που θα γίνουν στα πεδία της (διαβάζουμε νέες τιμές για τα πεδία). By reference σημαίνει πως μέσα στη συνάρτηση έχει οριστεί ως δείκτης, άρα εκεί μέσα όταν θέλουμε να αναφερθούμε σε κάποιο πεδίο της το κάνουμε με το σύμβολο ->
Τέλος περνάμε την someone by value στη συνάρτηση print_person() επειδή δεν θα αλλάξουμε τιμές στα πεδία της μέσα στη συνάρτηση. By value σημαίνει πως μέσα στη συνάρτηση ΔΕΝ έχει οριστεί ως δείκτης, άρα εκεί μέσα όταν θέλουμε να αναφερθούμε σε κάποιο πεδίο της το κάνουμε με το σύμβολο της τελείας .

Με άλλα λόγια, σε επίπεδο main() η someone συμπεριφέρεται όπως οποιαδήποτε άλλη μεταβλητή και η μόνη διαφορά με τις κανονικές μεταβλητές είναι πως δεν έχει μια ενιαία τιμή, έχει επιμέρους τιμές στο καθένα από τα πεδία της.

Και μερικές συμβουλές για ευανάγνωστο κώδικα:

α) τους πρόσθετους τύπους που ορίζουμε με typedef τους γράφουμε με κεφαλαίο το πρώτο τους γράμμα.
β) αν ο πρόσθετος τύπος είναι δομή, τότε στον ορισμό της δομής, δίπλα στο struct γράφουμε το ίδιο όνομα αλλά με πεζά γράμματα.

Π.χ...

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

struct person {
char name[ MAXSLEN ];
char surname[ MAXSLEN ];
int age;
};
typedef struct person Person;

ή σε ένα μόνο βήμα...

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

typedef struct person {
char name[ MAXSLEN ];
char surname[ MAXSLEN ];
int age;
} Person;


ΥΓ. Το (*p).age το γράφουμε: p->age και η διεύθυνσή του είναι: &p->age
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 12 Σεπ 2011, 12:26

Kαλημερα! Οκ τον καταλαβαινω τον κωδικα που δινεις (αυτον που μου εφτιαξες δηλαδη) αλλα δεν εχω διαβασει ακομη την εξηγηση σου... θα την διαβασω και θα τα συζητησουμε... παντως και ετσι οπως το εκανα δεν μπερδευτηκα αν και καταλαβαινω πως το εννοεις το μπερδεμενο... και πως σχετιζεται αμεσα με την κληση της συναρτησης και τους δεικτες.

εκεινο που δεν με μπερδεψε παντως ηταν η σκεψη πως εφοσον θελω εκτυπωση δεν πειραζω την μνημη. (Μεσα στην συναρτηση)

το μονο που ηταν λιγο αμφιλεγομενο ηταν το

struct_function(p) αλλα και παλι δεν δεχεται καποια τροποποιηση. Απλα ουσιαστικα λες στην συναρτηση να κληθει με βαση αυτη την διευθυνση που ειναι η διευθυνση της δομης απο την οποια θα εκτυπωσει στοιχεια...

ειμαι καπου λαθος?

Το
Κώδικας: Επιλογή όλων
(*p).age


ΟΚ το γραφουμε οπως το λες... αλλα το ιδιο πραγμα λεμε... :D
Eχεις καποιο λογο που προτιμας πιο πολυ αυτη τη γραφη???? (με τον τελεστη εμμεσης σχεσης)
Γνώσεις ⇛ 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: Τα πάντα για την C/C++

Δημοσίευσηαπό migf1 » 12 Σεπ 2011, 13:01

Star_Light έγραψε:
...
το μονο που ηταν λιγο αμφιλεγομενο ηταν το

struct_function(p) αλλα και παλι δεν δεχεται καποια τροποποιηση. Απλα ουσιαστικα λες στην συναρτηση να κληθει με βαση αυτη την διευθυνση που ειναι η διευθυνση της δομης απο την οποια θα εκτυπωσει στοιχεια...
ειμαι καπου λαθος?

Σε χάνω εδώ, δεν καταλαβαίνω τι εννοείς. Ο απλούστερος και συνιστώμενος τρόπος σκέψης είναι να σκέφτεσαι μεταβλητές και τύπους. Τυπικά η someone είναι μεταβλητή που έχει ως τύπο μια δομή, άσχετα αν συχνά για συντομία λέμε πως η someone είναι δομή... η someone είναι μεταβλητή που ο τύπος της είναι δομή struct person (ή Person αν το struct person το έχουμε κάνει typedef σε Person). Όπως λέμε π.χ όταν έχουμε: int n; ότι το n είναι ακέραιος, αλλά τυπικά το n είναι μεταβλητή που ο τύπος της είναι ακέραιος αριθμός.

Οπότε τη someone τη χρησιμοποιείς όπως όλες τις μεταβλητές, με μόνη διαφορά πως δεν έχει μια ενιαία τιμή, αλλά επιμέρους τιμές στα πεδία της. Όταν χρειάζεσαι να αναφερθείς σε κάποια επιμέρους τιμή της someone, τότε αν η someone είναι απλή μεταβλητή βάζεις .όνομα_πεδίου κολλητά στο όνομα της μεταβλητής σου, αλλιώς αν είναι δείκτης βάζεις ->όνομα_πεδίου κολλητά στο όνομα της μεταβλητής σου.

έγραψε:
Το
Κώδικας: Επιλογή όλων
(*p).age


ΟΚ το γραφουμε οπως το λες... αλλα το ιδιο πραγμα λεμε... :D
Eχεις καποιο λογο που προτιμας πιο πολυ αυτη τη γραφη???? (με τον τελεστη εμμεσης σχεσης)

Ένας λόγος είναι πως το παραπάνω χαρακτηρίζει προγραμματιστές που δεν τα έχουν αυτοματοποιήσει στο μυαλό τους. Άλλος λόγος είναι πως το p->age είναι πολύ πιο λιτό κι ευανάγνωστο, κάτι που ισχύει μεγενθυμένο στο: &p->age έναντι του: &( (*p).age )... και ισχύει ακόμα πιο μεγενθυμένο στο: p->q->age έναντι του: (*p).(*q).age ή ακόμα και του: p->buffer[i] έναντι του: (*p).buffer[i] και του: &p->buffer[i] έναντι του &( (*p).buffer[i] ).

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

Re: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 12 Σεπ 2011, 15:49

migf1 έγραψε:Καλημέρα,

Star_Light έγραψε:εφτασα και στο τελευταιο step πλεον πριν αρχισω να κοιταω τον κωδικα σου....

Δομες και δείκτες (μεσα σε συναρτηση)

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

#include <stdio.h>
#define N 254 + 1
typedef struct person
{
int age;
char name[N];
char surname[N];
} kostas ;

void struct_function(kostas *p);


int main(void)
{

kostas someone , *p;

p=&someone;

struct_function(p) ;

return 0;
}

void struct_function(kostas *p)
{


printf("Dwse to onoma sou: ");
fgets(p->name,254,stdin);

printf("Dwse to epwnumo sou: ");
fgets(p->surname,254,stdin);

printf("Dwse tin ilikia sou: ");
scanf("%d",&(*p).age);


printf("========================================");

printf("\nTo onoma pou edwses einai: %s",p->name);
printf("H ilikia pou edwses einai: %d",p->age);
printf("\nTo epwnimo pou edwses einai: %s",p->surname);

}

Έτσι όπως έχεις γράψει τον κώδικα μπερδεύονται τα πράγματα, ενώ είναι πολύ πιο απλά! Ο κώδικάς σου για να αντιστοιχεί και στην ανθρώπινη σκέψη και άρα να είναι μακράν πιο κατανοητός πρέπει να γραφτεί κάπως έτσι...

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

#include <stdio.h>
#include <stdlib.h> // για atoi()

// Macros

#define MAXSLEN (254 + 1) // MAXimum String LENgth

// Πρόσθετοι Τύποι Δεδομένων

typedef struct person // ορισμός δομής person ως πρόσθετο τύπο
{ // με το όνομα Person (λόγω του typedef)
char name[ MAXSLEN ]; // ... 1ο πεδίο της δομής
char surname[ MAXSLEN ]; // ... 2ο πεδίο της δομής
int age; // ... 3ο πεδίο της δομής
} Person; // το όνομα του πρόσθετου τύπου

// Πρότυπα Συναρτήσεων

char *s_getflushed(char *s, size_t len); // αντί fgets, για να μην κρατάει το '\n'
void read_person( Person *someone ); // για διάβασμα των πεδίων της someone
void print_person( Person someone ); // για τύπωμα των πεδίων της someone

// -------------------------------------------------------------------------------
int main( void )
{
Person someone; // η someone είναι μεταβλητή τύπου Person

read_person( &someone ); // πέρασμα της someone by reference
print_person( someone ); // πέρασμα της someone by value

return 0;
}
// -------------------------------------------------------------------------------
char *s_getflushed(char *s, size_t len)
{
char *cp;
for (cp=s; (*cp=getc(stdin)) != '\n' && (cp-s) < len-1; cp++ )
;

if ( *cp != '\n') { // len reached withoutn '\n'
*cp = '\0'; // null terminate s and
while (getchar() != '\n') // flush remaining chars
;
}
else // '\n' found
*cp = '\0'; // null-terminate

return s;
}
// -------------------------------------------------------------------------------
void read_person( Person *someone ) // by reference πέρασμα της someone
{ // άρα χρήση του -> για τα πεδία της
char inbuf[ 254+1 ] = {'\0'};

printf("Dwse to onoma sou: ");
s_getflushed( someone->name, MAXSLEN );

printf("Dwse to epwnumo sou: ");
s_getflushed( someone->surname, MAXSLEN );

printf("Dwse tin ilikia sou: ");
s_getflushed( inbuf, MAXSLEN );
someone->age = atoi( inbuf );

return;
}
// -------------------------------------------------------------------------------
void print_person( Person someone ) // by value πέρασμα της someone
{ // άρα χρήση τελείας για τα πεδία της
puts("========================================");

printf("To onoma pou edwses einai: %s\n", someone.name);
printf("To epwnimo pou edwses einai: %s\n", someone.surname);
printf("H ilikia pou edwses einai: %d\n", someone.age);

putchar('\n');

return;
}

Τον γέμισα με Ελληνικά σχόλια ελπίζοντας πως ξεκαθαρίζει τα πράγματα και μπορεί να χρησιμοποιηθεί και ως γρήγορος οδηγός για φρεσκάρισμα μνήμης. Εδώ και με syntax-highlighting: http://ideone.com/tw7BS

Ορίζουμε μια δομή struct person, την μετατρέπουμε σε πρόσθετο τύπο Person με το typedef και ορίζουμε μια μεταβλητή someone να είναι τύπου Person. Κατόπιν περνάμε την someone by reference στη συνάρτηση read_person() επειδή θέλουμε να διατηρηθούν οι αλλαγές που θα γίνουν στα πεδία της (διαβάζουμε νέες τιμές για τα πεδία). By reference σημαίνει πως μέσα στη συνάρτηση έχει οριστεί ως δείκτης, άρα εκεί μέσα όταν θέλουμε να αναφερθούμε σε κάποιο πεδίο της το κάνουμε με το σύμβολο ->
Τέλος περνάμε την someone by value στη συνάρτηση print_person() επειδή δεν θα αλλάξουμε τιμές στα πεδία της μέσα στη συνάρτηση. By value σημαίνει πως μέσα στη συνάρτηση ΔΕΝ έχει οριστεί ως δείκτης, άρα εκεί μέσα όταν θέλουμε να αναφερθούμε σε κάποιο πεδίο της το κάνουμε με το σύμβολο της τελείας .

Με άλλα λόγια, σε επίπεδο main() η someone συμπεριφέρεται όπως οποιαδήποτε άλλη μεταβλητή και η μόνη διαφορά με τις κανονικές μεταβλητές είναι πως δεν έχει μια ενιαία τιμή, έχει επιμέρους τιμές στο καθένα από τα πεδία της.

Και μερικές συμβουλές για ευανάγνωστο κώδικα:

α) τους πρόσθετους τύπους που ορίζουμε με typedef τους γράφουμε με κεφαλαίο το πρώτο τους γράμμα.
β) αν ο πρόσθετος τύπος είναι δομή, τότε στον ορισμό της δομής, δίπλα στο struct γράφουμε το ίδιο όνομα αλλά με πεζά γράμματα.

Π.χ...

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

struct person {
char name[ MAXSLEN ];
char surname[ MAXSLEN ];
int age;
};
typedef struct person Person;

ή σε ένα μόνο βήμα...

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

typedef struct person {
char name[ MAXSLEN ];
char surname[ MAXSLEN ];
int age;
} Person;


ΥΓ. Το (*p).age το γράφουμε: p->age και η διεύθυνσή του είναι: &p->age


ΚΑΤΑΛΑβα δηλαδη ετσι μπερδευεται καποιος που διαβαζει τον κωδικα μου επειδη ενω δεν κανω call by reference μεσα στην συναρτηση με τον τελεστη (->) ειναι σαν να δειχνω οτι κανω....

Οσο για το
migf1 έγραψε: Είναι δηλαδή σαν να με ρωτάς για ποιο λόγο προτιμάς γενικώς στους δείκτες τη γραφή: p αντί της: &(*p)


Και ομως το πιστευεις οτι εγω συμφωνω πιο πολυ με το &(*p) παρα με το p? Το p γιατι να το δεχθω σαν διευθυνση? Επειδη ετσι μου το οριζουν ή μου το λενε? Δεν εχω καποια αλλη ενδειξη... οταν παλιοτερα καποιος πηγε να μου εξηγησει τους δεικτες (πολυ παλιοτερα) μου ειχε πει οκ
οριζουμε int *p το p πλεον ειναι μεταβλητη δεικτη που φερει την διευθυνση ενω το * ειναι περιεχομενα....

ενω αντιθετως... στο
Κώδικας: Επιλογή όλων
&(*p)


το & ειναι τελεστης διευθυνσης και δινει την διευθυνση... ειναι αξιωμα. Δεν σου λεει ο αλλος ειναι δικο μου αξιωμα οποτε δεξου το και εσυ... καταλαβαινεις γενικα πως ειναι αξιωμα. Οκ? Απο την αλλη και το (*p) ειναι και αυτο γενικο αξιωμα οτι δινει το περιεχομενο αρα ολο μαζι
δηλαδη το &(*p) δινει την διευθυνση του περιεχομενου στο οποιο δειχνει ο δεικτης... ακριβως με αυτη τη διευθυνση που έχεις αρχικοποιησει και τον δεικτη στο να δειχνει... καταλαβαινεις τι λεω ή ειμαι για δεσιμο? :lol:

Και σχετικα με την ερωτηση

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


Θα γινω πιο συγκεκριμενος... γιατι το καλεις ετσι??? Επειδη μεσα εχει την διευθυνση της δομης (στην οποια εχουμε βαλει να δειχνει ο δεικτης) αυτο ηθελα να ξεκαθαρισω.
Γνώσεις ⇛ 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: Τα πάντα για την C/C++

Δημοσίευσηαπό Star_Light » 12 Σεπ 2011, 16:07

ετσι οπως το λες ειναι σαν να το εχω κανει λαθος.... οτι δηλαδη μεσα στην συναρτηση ΔΕΝ οριζουμε ως δεικτη... εγω το εχω ορισει μεν ως δεικτη αλλα οχι για να δουλεψει πανω στην μνημη (κατι που θα γινοταν με call by reference) εγω το δηλωνω ως δεικτη για να κανω μεσω αυτου προσπελαση στα στοιχεια της δομης για αναγνωση....οπα κατσε γιατι μπερδευτηκα τωρα...

ΛΟΛ αφου ο χρηστης τα δινει αρα ο δεικτης τα αποθηκευει στα στοιχεια της δομης (ή καλυτερα της μεταβλητης της δομης) αρα δουλευει στην μνημη μιας και εχει την δυνατοτητα να την τροποποιει ??? Eκτος αυτου προσθεσα μια printf αμεσως μετα την κληση και το τελος της συναρτησης στην main και ειδα πως ακομη και με call by value διατηρει τις τιμες της.... στα πεδια της (οταν τις εδινα σαν εισοδο στην συναρτηση) πως γινεται αυτο εφοσον ειναι by value? :/

Κώδικας: Επιλογή όλων
int main(void)
{

kostas someone , *p;

p=&someone;

struct_function(p) ;

===> printf("%s",p->surname); <==========

return 0;
}
Γνώσεις ⇛ 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
Εκτύπωση

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

Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι