Δημοσιεύτηκε: 12 Σεπ 2011, 09:47
από 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