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

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

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

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

Δημοσίευσηαπό stamatiou » 07 Σεπ 2011, 00:48

migf1 έγραψε:Για να ολοκληρώσουμε λοιπόν και το θέμα των ελέγχων που έχουμε αφήσει ανοιχτό στη συνάρτηση s_compare που έχουμε φτιάξει, παραθέτω τον ολοκληρωμένο της κώδικα, κι εξηγώ από κάτω...

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

// ------------------------------------------------------------------------------------
int s_compare( const char *s1, const char *s2 )
{
if ( !s1 && !s2 )
return 0;
if ( !s1 && s2 )
return -1;
if (s1 && !s2 )
return 1;

while ( *s1 == *s2++ )
if ( *s1++ == '\0' )
return 0;

return (int) ( *s1 - *--s2 );
}

Οι έλεγχοι αυτοί είναι όλοι early-exit conditions και αποτελούνται από τα 3 if που έχω προσθέσει στην αρχή της συνάρτησης.

Στο πρώτο ελέγχω αν και ο δείκτης s1 και ο δείκτης s2 είναι NULL (που ουσιαστικά είναι τα 2 strings που μας έχουν περαστεί στη συνάρτηση και καλούμαστε να τα συγκρίνουμε). Όταν λοιπόν είναι και τα 2 NULL, δηλαδή ανύπαρκτα επί της ουσίας, τότε επιστρέφω την τιμή 0... σαν να υπήρχαν δηλαδή και να ήταν ίδια.

Στο 2ο if ελέγχω την περίπτωση όπου το s1 είναι NULL αλλά το s2 υπάρχει (και προφανώς περιέχει κάτι). Σε αυτή την περίπτωση θεωρώ πως το s1 είναι μικρότερο του s2 (με τη λογική πως το ανύπαρκτο είναι πάντα μικρότερο του υπαρκτού) οπότε επιστρέφω την τιμή -1.

Και στο 3ο if εξετάζω την περίπtωση όπου το s1 είναι υπαρκτό και το s2 ανύπαρκτο, οπότε θεωρώ το s1 μεγαλύτερο του s2 κι επιστρέφω την τιμή 1.

Αν η ροή καταφέρει και περάσει από αυτούς τους ελέγχους, τότε έχουμε εγγυημένα 2 υπαρκτά stings (μη NULL) και άρα μπορούμε να γράψουμε τον βασικό αλγόριθμο της συνάρτησής μας, χωρίς να μας απασχολεί πλέον αν κάποιο ή και τα 2 strings που μας περάστηκαν σαν ορίσματα είναι NULL.

Έχουμε καταφέρει επίσης να αποφύγουμε τυχόν παραγωγή segmentation-faults, διότι δεν υπάρχει καμία πιθανότητα ο κώδικάς μας να επιχειρήσει να χρησιμοποιήσει κάποιο από τα s1 και s2 όταν οποιοδήποτε από αυτά είναι NULL.

Άρα έχουμε φτιάξει μια λειτουργική και ΑΣΦΑΛΗ συνάρτηση! :)

Υπάρχει κάποια πιθανότητα να παραχθεί seg-fault, αν για παράδειγμα κάποιο ή και τα δυο από τα s1 και s2 ναι μεν δεν είναι NULL, αλλά δεν δείχνει σε έγκυρη μνήμη. Π.χ. να έχει οριστεί στη main() χωρίς να έχει αρχικοποιηθεί ούτε σε NULL αλλά ούτε με calloc() / malloc()... και να έχει περαστεί έτσι στη συνάρτησή μας.

Αυτό όμως δεν μπορεί να το γνωρίζει η συνάρτηση, ούτε μπορεί να το ελέγξει. Οπότε ότι είχαμε να κάνουμε σε επίπεδο συνάρτησης το έχουμε κάνε!, Μένει να εξασφαλίσουμε πως τα s1 και s2 θα είναι είτε NULL είτε θα δείχνουν σε έγκυρη μνήμη όταν καλούμε τη συνάρτηση και της τα περνάμε σαν ορίσματα!

Θέλω να πιστεύω πως είναι κατανοητό πλέον. Αν όχι πείτε το, για να προχωρήσουμε.

Μετά το βρόχο του while δεν πάει το s1 1 θέση μετά το '\0';
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 07 Σεπ 2011, 00:58

Μετά τον βρόγχο όχι! Τον πάει στο if μέσα στον βρόγχο, όταν το *s1 φτάσει στο '\0' (λόγω του ++) αλλά αφενός δεν επιχειρεί να χρησιμοποιήσει ότι βρίσκεται εκεί πέρα κι αφετέρου τερματίζει απευθείας τη συνάρτηση μέσα στο (με τιμή επιστροφής 0) όταν το *s1 φτάσει στο '\0' ... άρα η ροή δεν φτάνει έξω από τον βρόγχο σε αυτή την περίπτωση.

Η ροή θα βγει έξω από τον βρόγχο μόνο αν τα *s1 και *s2 είναι ίδια, πριν φτάσει στο '\0' το *s1.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό stamatiou » 07 Σεπ 2011, 01:07

migf1 έγραψε:Μετά τον βρόγχο όχι! Τον πάει στο if μέσα στον βρόγχο, όταν το *s1 φτάσει στο '\0' (λόγω του ++) αλλά αφενός δεν επιχειρεί να χρησιμοποιήσει ότι βρίσκεται εκεί πέρα κι αφετέρου τερματίζει απευθείας τη συνάρτηση μέσα στο (με τιμή επιστροφής 0) όταν το *s1 φτάσει στο '\0' ... άρα η ροή δεν φτάνει έξω από τον βρόγχο σε αυτή την περίπτωση.

Η ροή θα βγει έξω από τον βρόγχο μόνο αν τα *s1 και *s2 είναι ίδια, πριν φτάσει στο '\0' το *s1.

Ωχ ναι! Πάλι Κοτσάνα πέταξα.... :D
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

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

Back!!!!!!! Ασχετο αλλα ειναι ο καλυτερος μηνας για να βγαινει καποιος για καφεδακι ουτε πολυ ζεστη ουτε κρυο... ειδικα τα απογευματα που ο ηλιος δεν βαραει οπως ο ηλιος του Ιουλιου ειναι τρομερα ;)

ΣΤαματιου καταλαβες την ανω υπερχειλιση? Γιατι μ αρεσει σαν εννοια και εχω και κωδικα απο παλαιοτερα αυτο που ειχαμε φτιαξει με τον migf1 που εκοβε στο string τον '\0' και τον '\n' . Αν θες την παραθετω μην μεινεις με καποιο κενο πχ.
Γνώσεις ⇛ 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 » 07 Σεπ 2011, 04:13

Να ρωτησω κατι τελευταιο με τους ελεγχους και τα if , γιατι θες να ελεγχεις να μην ειναι NULL Ο δεικτης πριν τον ελευθερωσεις ?
Και αμεσως μετα (αν ειναι) να τον κανεις NULL πχ.

ΕΠισης εκει που λες οτι το ανύπαρκτο ειναι παντα μικρότερο του υπαρκτού εκει κάνεις έλεγχο αν το s1 (ανύπαρκτο) ειναι η εισοδος s1[]="";
δηλαδη ενα string που έχει μονο τον κενο χαρακτηρα.... που ειναι το 0 και επομένως

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

αν το s2 ειναι πχ μήκους 2 s2[]="ab"

s1<s2 => s1-s2<0
=>
τοτε '\0' - 2 = 0 - 2 = -2 ΑΡΑ θα επιστρέψει - 1 η συνάρτηση (η κωδικοποιηση του -2 και γενικοτερα ολων των - n αριθμων που θα προκυψουν


αυτη ειναι η λογικη ????
Γνώσεις ⇛ 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 » 07 Σεπ 2011, 04:53

Κώδικας: Επιλογή όλων
#include<stdio.h>

int main()

{
int x,y;
x=1 , y =2;

int *p1 , *p2 , *p3;

p1=&x , p2=&y , p3=NULL;

if(p1)
{
printf("\n The pointer 1 exists");
printf("\nAnd his value is: %d",*p1);
}
else
printf("The pointer 2 does not exist");


if(p2)
{
printf("\n The pointer 2 exists");
printf("\nAnd his value is: %d",*p2);
}
else

printf("The pointer 2 does not exist");


if(p3)
{
printf("\nThe pointer 3 exists");
printf("\nAnd his value is: %d",*p3);
}
else
printf("\nThe pointer 3 does not exist");


return 0;
}



Στο μεταξυ εδω δεν θα μπορουσε να φαει segm fault??? λεω στο 3ο if γιατι ουσιαστικα ενω τον εχω σαν NULL παω να τον προσπελασω κατα τα αλλα μου εμφανιζει κανονικα πως ο δεικτης δεν υπάρχει :D

εΠΙΣΗς αν βαλω

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

if(*pn) // οπου n ειναι ο αριθμος σε ολους τους δεικτες για n=1,2,3 δηλαδη


τοτε τρωω ακριβως ενα seg fault στο σημειο 3 αλλα φυσικα δεν μου εμφανιζει και το σημειο 2 παρα μονο το σημειο 1 μου εμφανιζει μαζι με την τιμη του 1 και απλα μου λεει οτι το 2 υπάρχει κουλο ε??? τελοςπαντων παω να την πεσω καληνυχτα!!!!
Γνώσεις ⇛ 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 » 07 Σεπ 2011, 11:36

Star_Light έγραψε:Να ρωτησω κατι τελευταιο με τους ελεγχους και τα if , γιατι θες να ελεγχεις να μην ειναι NULL Ο δεικτης πριν τον ελευθερωσεις ?

Γιατί σε παλαιότερες αναθεωρήσεις της γλώσσας η συνάρτηση free( p ) επιχειρούσε να πειράξει τα περιεχόμενά του p χωρίς να ελέγχει πρώτα αν o p είναι NULL, οπότε αν ήταν NULL (δεν είχε δλδ περιεχόμενα) παρήγαγε seg-fault. Σε νεότερες αναθεωρήσεις έχει μπει στα στάνταρ να κάνει τον έλεγχο αυτόν η free() αλλά όπως έχουμε πει δεν ακολουθούν όλοι οι compilers όλα τα νέα στάνταρ.

έγραψε:Και αμεσως μετα (αν ειναι) να τον κανεις NULL πχ.

Αμέσως μετά την απελευθέρωσή του εννοούμε. Τον κάνεις NULL για να μη ρισκάρεις να χρησιμοποιηθεί αργότερα με undefined περιεχόμενα, σε μεταγενέστερα σημεία του κώδικα ( free() δεν κάνουμε μόνο πριν τερματίσουμε, πολύ συχνά κάνουμε και σε άλλα σημεία του προγράμματός μας).

έγραψε:ΕΠισης εκει που λες οτι το ανύπαρκτο ειναι παντα μικρότερο του υπαρκτού εκει κάνεις έλεγχο αν το s1 (ανύπαρκτο) ειναι η εισοδος s1[]="";
δηλαδη ενα string που έχει μονο τον κενο χαρακτηρα.... που ειναι το 0 και επομένως

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

αν το s2 ειναι πχ μήκους 2 s2[]="ab"

s1<s2 => s1-s2<0
=>
τοτε '\0' - 2 = 0 - 2 = -2 ΑΡΑ θα επιστρέψει - 1 η συνάρτηση (η κωδικοποιηση του -2 και γενικοτερα ολων των - n αριθμων που θα προκυψουν

αυτη ειναι η λογικη ????

Κοίτα, με αυτή την ερώτηση καταλαβαίνω πως ακόμα δεν τα έχεις ξεκαθαρίσει. Καταρχήν ο δείκτης s1 στο s1[]="" είναι υπαρκτός δείκτης (δηλαδή δεν είναι NULL) και έπειτα το μήκος του s2[]="ab" δεν είναι 2... 2 είναι το μήκος των ωφέλιμων χαρακτήρων του, αλλά το συνολικό του μήκος είναι 3, αφού υπάρχει και ο μηδενικός χαρακτήρας στο τέλος.

Λοιπόν, ας το πούμε αλλιώς, ένας δείκτης που έχει οριστεί μπορεί γενικώς να βρίσκεται σε 2 καταστάσεις:

  • έγκυρος: όταν δείχνει είτε σε NULL ( p = NULL ), είτε σε μνήμη που έχει δημιουργηθεί ειδικά για τον δείκτη ( p = calloc(...) ), είτε σε μνήμη μιας άλλης έγκυρης μεταβλητής ( p = &var ή p = array )
  • άκυρος: όταν δείχνει σε μη-έγκυρη μνήμη... δείχνει δηλαδή σε undefined περιοχή μνήμης, ή αν το προτιμάς σαν ορολογία έχει undefined περιεχόμενο (π.χ. int *p; ή free(p) )
Οπότε, ας υιοθετήσουμε στο εξής και τους όρους: "έγκυρος" και "άκυρος" !

Σε αυτό το σημείο είναι πολύ σημαντικό να ξεκαθαρίσετε πως το NULL είναι ΕΓΚΥΡΟΣ δείκτης, αλλά ΔΕΝ ΕΧΕΙ ΠΕΡΙΕΧΟΜΕΝΑ! Οπότε οποιαδήποτε απόπειρα να χρησιμοποιήσετε τα περιεχόμενα ( *p ) ενός δείκτη p που είναι NULL παράγει seg-fault ! Οπότε μπορούμε να χαρακτηρίσουμε έναν έγκυρο δείκτη NULL ως ανύπαρκτο, υπό την έννοια πως δεν έχει υπαρκτά περιεχόμενα! Από την άλλη μεριά, ένας δείκτης με υπαρκτά περιεχόμενα δεν είναι κατά ανάγκην και έγκυρος! Αν τα περιεχόμενά του είναι undefined τότε o δείκτης είναι άκυρος (undefined περιεχόμενα παίρνει ένας δείκτης όταν τον κάνουμε free() ή όταν τον ορίζουμε αλλά χωρίς να τον βάλουμε μετά να δείχνει κάπου).

Άρα λοιπόν στην s_compare() με τα early-exit conditions που προσέθεσα εξασφαλίζω αφενός πως η συνάρτησή μας δεν θα παράξει seg-fault αν της περαστεί έστω κι ένα από τα ορίσματά της ως NULL, κι αφετέρου πως όταν η ροή φτάσει στον βασικό αλγόριθμο της συνάρτησης και οι δυο δείκτες θα δείχνουν σε υπαρκτά περιεχόμενα. Το αν αυτά τα περιεχόμενα είναι έγκυρα ή άκυρα η συνάρτηση δεν μπορεί να το ελέγξει, αυτή η εξασφάλιση είναι ευθύνη της ρουτίνας που καλεί τη συνάρτηση.

Οπότε για να απαντήσω και στην ερώτησή σου σχετικά με τη σύγκριση NULL και μη NULL δεικτών στην s_compare(), θεωρώ αυθαίρετα (αλλά σύμφωνα με τη γενικότερη λογική της συνάρτησης) πως ένας δείκτης με ανύπαρκτα περιεχόμενα είναι μικρότερος από έναν άλλον που έχει υπαρκτά περιεχόμενα (δηλαδή πως το NULL είναι μικρότερο του !NULL ... που btw συνήθως ισχύει κιόλας :lol: ... 0 < !0), καθώς επίσης πως 2 δείκτες με ανύπαρκτα περιεχόμενα είναι ίσοι (NULL == NULL) και πάντα σύμφωνα με την γενικότερη λογική της συγκεκριμένης συνάρτησης).

Η παραπάνω λογική εφαρμόζεται άμεσα και τερματίζει την συνάρτηση με τα 3 if που πρόσθεσα στην αρχή της. Η όλη ιστορία γίνεται ακριβώς για να μην επιχειρήσει ο βασικός μας αλγόριθμος να χρησιμοποιήσει ανύπαρκτα περιεχόμενα δεικτών ( *s1 ή *s2) ... να μην μπει καν δηλαδή στη διαδικασία ελέγχου μεμονωμένων χαρακτήρων στα strings ... άρα το παράδειγμα που έγραψες παραπάνω για την απορία σου είναι τελείως εκτός συγκριτικά με τα όσα είπαμε στα 2-3 προηγούμενα posts ( δεν το εννοώ υποτιμητικά, αυτό έλειπε... το λέω ως συνέχεια αυτού που έγραψα στην αρχή πως με αυτή την ερώτηση κατάλαβα πως δεν τα έχεις ακόμα ξεκαθαρισμένα ).

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

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

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

Star_Light έγραψε:
Spoiler: show
Κώδικας: Επιλογή όλων
#include<stdio.h>

int main()

{
int x,y;
x=1 , y =2;

int *p1 , *p2 , *p3;

p1=&x , p2=&y , p3=NULL;

if(p1)
{
printf("\n The pointer 1 exists");
printf("\nAnd his value is: %d",*p1);
}
else
printf("The pointer 2 does not exist");


if(p2)
{
printf("\n The pointer 2 exists");
printf("\nAnd his value is: %d",*p2);
}
else

printf("The pointer 2 does not exist");


if (p3)
{
printf("\nThe pointer 3 exists");
printf("\nAnd his value is: %d",*p3);
}
else
printf("\nThe pointer 3 does not exist");

return 0;
}


Στο μεταξυ εδω δεν θα μπορουσε να φαει segm fault??? λεω στο 3ο if γιατι ουσιαστικα ενω τον εχω σαν NULL παω να τον προσπελασω κατα τα αλλα μου εμφανιζει κανονικα πως ο δεικτης δεν υπάρχει :D

Όχι δεν θα μπορούσε να φάει seg-fault, για αυτό δεν τρώει κιόλας :)

Το if ( p3 ) που ισοδυναμεί με if ( p3 != NULL ) εξασφαλίζει πως όταν ο p3 είναι NULL η ροή ΔΕΝ μπαίνει στο σώμα του if, στο οποίο σώμα χρησιμοποιείς τα περιεχόμενα του p3 στο 2ο printf... εκείνο το *p3 δηλαδή.

έγραψε:
εΠΙΣΗς αν βαλω

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

if(*pn) // οπου n ειναι ο αριθμος σε ολους τους δεικτες για n=1,2,3 δηλαδη


τοτε τρωω ακριβως ενα seg fault στο σημειο 3 αλλα φυσικα δεν μου εμφανιζει και το σημειο 2 παρα μονο το σημειο 1 μου εμφανιζει μαζι με την τιμη του 1 και απλα μου λεει οτι το 2 υπάρχει κουλο ε??? τελοςπαντων παω να την πεσω καληνυχτα!!!!

Και πολύ σωστά τρως seg-fault αφού στο if χρησιμοποιείς τα περιεχόμενα του p3 ( *p3 σημαίνει τα περιεχόμενα του p3) χωρίς να έχεις εξασφαλίσει πρώτα πως ο p3 έχει όντως περιεχόμενα. Οπότε όταν ο p3 είναι NULL (δλδ δεν έχει περιεχόμενα) το if ( *p3 ) προκαλεί seg-fault.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

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

οΚ θα κατσω να διαβασω προσεκτικα αυτα που μου εδωσες και θα ξανα επανελθω :D
Γνώσεις ⇛ 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++

Δημοσίευσηαπό stamatiou » 07 Σεπ 2011, 14:24

Εγώ τα κατάλαβα, Star_Light με την ησυχία σου :D
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

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

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