C99: Hunt

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

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

Re: C99: Hunt

Δημοσίευσηαπό migf1 » 07 Μάιος 2012, 16:26

Α και για να γράψουμε και κάτι οn-topic, σύμφωνα με τον τίτλο του νήματος. Ένα ενδιαφέρον βήμα θα ήταν η υποστήριξη hi-scores στο Hunt ;) Ακόμα πιο ενδιαφέρον θα ήταν η δυνατότητa save/load game :)
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: C99: Hunt

Δημοσίευσηαπό Ilias95 » 07 Μάιος 2012, 17:08

Λοιπόν ας πω και εγώ την γνώμη μου. :P

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

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

migf1 έγραψε:κάτι σαν...
Μορφοποιημένος Κώδικας: Επιλογή όλων
char *messages[MAX_MESSAGES];
enum LangId lang = LANG_EN;
...
if ( LANG_EL == lang )
load_messages( messages, el_fname ); /* load strings from el_file into messages*/
else if ( LANG_DE == lang)
load_messages( messages, de_fname ); /* load strings from de_file into messages*/
...

for (i=0; i < MAX_MESSAGES; i++)
printf( "%s ", messages[i] );
puts("\b\n");
...


Αν κατάλαβα καλά δηλαδή οι εκτυπώσεις μηνυμάτων θα γίνονται κάπως έτσι;
Μορφοποιημένος Κώδικας: Επιλογή όλων
if (n == 3)
puts(messages[157]);
else if (n == 2)
puts(messages[158]);
else
puts(messages[159]);

Δεν χαλάει πολύ η readability;

migf1 έγραψε:Α και για να γράψουμε και κάτι οn-topic, σύμφωνα με τον τίτλο του νήματος. Ένα ενδιαφέρον βήμα θα ήταν η υποστήριξη hi-scores στο Hunt ;) Ακόμα πιο ενδιαφέρον θα ήταν η δυνατότητa save/load game :)

Ναι, αυτές είναι ωραίες ιδέες. :)
Μια ερώτηση: Γίνεται να κάνεις serializing δομές δεδομένων της C;
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: C99: Hunt

Δημοσίευσηαπό migf1 » 07 Μάιος 2012, 18:50

Ilias95 έγραψε:
...
Το πακετάρισμα / διανομή του προγράμματος είναι κάτι με το οποίο θα βρεθώ αντιμέτωπος πολύ, πολύ αργότερα.
Οπότε ίσως είναι καλύτερα να ασχοληθώ περισσότερο με το ίδιο το πρόγραμμα που νομίζω είναι πιο ουσιαστικό.
Στο κάτω, κάτω δεν είναι και κάποια σοβαρή εφαρμογή που χρησιμοποιείται από πολλούς χρήστες και επιβάλετε να είναι πολύ εύκολη η εγκατάσταση και σε όλα τα λειτουργικά συστήματα.

Όσο πιο αυτόνομο το κάνεις το πρόγραμμά σου, τόσο πιο cross-platform γίνεται (και σαν κώδικας και σαν εγκατάσταση). Δηλαδή, όσο λιγότερο το βασίζεις σε εξωτερικές βιβλιοθήκες, τόσο αυξάνεις τις πιθανότητες να γίνεται παντού compile. Ταυτόχρονα τόση περισσότερη δουειά πρέπει να κάνεις, αφού θα πρέπει να υλοποιήσεις μόνος σου την λειτουργικότητα των εξωτερικών βιβλιοθηκών που ΔΕΝ χρησιμοποιείες ;)

έγραψε:
Αν κατάλαβα καλά δηλαδή οι εκτυπώσεις μηνυμάτων θα γίνονται κάπως έτσι;
Μορφοποιημένος Κώδικας: Επιλογή όλων
if (n == 3)
puts(messages[157]);
else if (n == 2)
puts(messages[158]);
else
puts(messages[159]);

Δεν χαλάει πολύ η readability;

Είναι αρκετά πιο σύνθετο, αλλά το readability χαλάει έτσι κι αλλιώς. Είναι trade-off (όπως τα περισσότερα στον προγραμματισμό).. στην προκειμένη περίπτωση είναι trade-off μεταξύ readability & δουλειάς έναντι ευκολίας τόσο σε επίπεδο μεταγλώττισης από τρίτους όσο και εγκαταστασης/χρήσης απλούς χρήστες. Για παράδειγμα, για έναν χρήστη, όταν θέλει να αλλάξει γλώσσα στο πρόγραμμά σου, αντί να αλλάζει environment variable θα διαλέγει τη γλώσσα μέσα από το ίδιο το πρόγραμμα (ή έστω θα του περνάει ένα command-line argument).

Για τον κώδικα τώρα, ένας (σχετικά) απλός τρόπος είναι ο εξής...

Ας πούμε ότι συνολικά στο πρόγραμμά σου τυπώνεις συνολικά 3 strings:

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

"What is your name?"
"Hello %s, welcome to my little program"
"Your name reversed is: %s"

Φτιάχνεις ένα απλό αρχείο κειμένου με το καθένα από τα παραπάνω strings σε μια γραμμή, χωρίς τα εισαγωγικά και το ονομάζεις ας πούμε: hunt_en.txt ...

Μορφοποιημένος Κώδικας: Επιλογή όλων
What is your name?
Hello %s, welcome to my little program
Your name reversed is: %s

Μέσα στο πρόγραμμά σου έχεις έναν πίνακα από 3 strings, ας τον πούμε: msgout κι έναν enumerator για τα 3 striings, ας τον πούμε MsgId...

Μορφοποιημένος Κώδικας: Επιλογή όλων
enum MsgId {
MSG_WHAT 0,
MSG_HELLO 1,
MSG_REV 2,
/* not an id, just their total count */
MAX_MESSAGES
};

int main( void )
{
char *msgout[ MAX_MESSAGES ] = { NULL };

Το επόμενο βήμα είναι να φτιάξεις μια ρουτίνα η οποία θα παίρνει σαν όρισμα τον πίνακα msgout και ένα filename, η οποία θα διαβάζει το αρχείο γραμμή-γραμμή και θα βάζει το string στην αντίστοιχη θέση του msgout...

Μορφοποιημένος Κώδικας: Επιλογή όλων
Bool load_messages( char *msgout[ MAX_MESSAGES], const char *fname )
{
char fline[ 512+1] = {'\0'};
FILE *fp = NULL;
enum MsgId i = 0, j;

if ( !msgout || NULL == (fp = fopen( fname, "r")) )
return false; /* ενδεχομένως και κάποιο error-message εδώ */

for (i=0; i < MAX_MESSAGES && fgets( fline, 512+1, fp); i++ )
{
msgout[ i ] = malloc( (strlen(fline) + 1) * sizeof(char) );
if ( !msgout[ i ] )
{
for (j=i-1; j > -1; j--) {
free( msgout[ j ] );
msgout[ j ] = NULL;
}
fclose( fp );
return false;
}
strcpy( msgout[ i ], fline );
}

fclose( fp );
return true;
}
έχω παραλείψει κάποιους ελέγχους για να μην περιπλακεί πολύ ο κώδικας (π.χ. αν αποτύχει η fgets() πρέπει και πάλι να απελευθερωθεί όση μνήμη είχε δεσμευτεί στα προηγούμενα msgout[ i ] ... οπότε καλό είναι να υπάρχει μια γενική συνάρτηση που θα παίρνει ως όρισμα τον msgout και θα απελευθερώνει τη μνήμη όλων των msgout[ i ] που ΔΕΝ είναι NULL, και η οποία θα μπορεί να χρησιμοποιηθεί και παραπάνω αντί για το for-loop του j ).

Σε αυτό το σημείο έχεις φορτωμένα όλα τα strings που χρησιμοποιεί το πρόγραμμά σου μέσα στον msgout. Οπότε, όταν θέλεις να τυπώσεις ας πούμε το "What is your name?" γράφεις...

Μορφοποιημένος Κώδικας: Επιλογή όλων
printf( "%s", msgout[ MSG_WHAT ] );

Δεν είναι και τόσο τραγικό πιστεύω το readability (βασικά εξαρτάται κι από σένα, από τι ονόματα θα επιλέξεις να δώσεις στον πίνακα και στους enumerators ).

Τώρα, αν έχεις διαβάσει το όνομά του σε ένα string ας πούμε name, και θέλεις να τυπώσεις το "Hello %s, welcome to my little program" και να αλλάξεις γραμμή, γράφεις...

Μορφοποιημένος Κώδικας: Επιλογή όλων
printf( msgout[ MSG_HELLO ], name );
putchar('\n');

Από εδώ και πέρα είναι πλέον τετριμένο το να αλλάζεις γλώσσα σε πραγματικό χρόνο, μέσα από το πρόγραμμά σου, αφού το μόνο που χρειάζεται είναι να καλέσεις την: load_messages() με 2ο όρισμα το όνομα του αρχείου που περιέχει τα messages της άλλης γλώσσας ;)

Βασικά χρειάζεται πρώτα να απελευθερώσεις τη μνήμη που έχουν δεσμεύσει τα msgout[ i ] στην παλιά γλώσσα πριν φορτώσεις τη νέα. Με εκείνη τη γενική συνάρτηση απελευθέρωσης που είπα παραπάνω.

Π.χ.

Μορφοποιημένος Κώδικας: Επιλογή όλων
Bool unload_messages( char *msgout[ MAX_MESSAGES ] )
{
enum MsgId i;

if ( !msgout )
return false; /* internal error, non-existent msgout */

for (i=0; i < MAX_MESSAGES; i++)
{
if ( msgout[ i ] ) {
free( mesgout[ i ] );
msgout[ i ] = NULL;
}
}

return true;
}

Οπότε, με την προϋπόθεση πως υπάρχουν τα αρχεία των γλωσσών, αλλάζεις γλώσσα on-the-fly στο run-time...

Μορφοποιημένος Κώδικας: Επιλογή όλων
...
/* load greek */
unload_messages( msgout );
load_messages( msgout, "hunt_el.txt");
...
/* load italian */
unload_messages( msgout );
load_messages( msgout, "hunt_it.txt");
...

Αυτό που ΔΕΝ είναι trivial είναι να διαβάζεις/γράφεις σε διαφορετικές κωδικοποιήσεις, αλλά για αρχή η παραπάνω διδικασία είναι παραπάνω από αρκετή για να πάρεις το feeling ;)

έγραψε:
Μια ερώτηση: Γίνεται να κάνεις serializing δομές δεδομένων της C;

Υπάρχουν εξωτερικές βιβλιοθήκες, π.χ. δες εδώ: http://stackoverflow.com/questions/3713 ... tures-in-c (οι tpl και eet είναι από τις πιο γνωστές, με την eet να μπορεί νομίζω να διαχειριστεί και nested-structs).

Αλλά για αρχή κάνε τα με απλά αρχεία κειμένου που θα τα διαχειρίζεσαι μόνος σου. Μπορείς να χρησιμοποιήσεις και τις στάνταρ συναρτήσεις της C fread()/fwrite() αλλά τα αρχεία που δημιουργούνται έτσι είναι platform-specific. Δηλαδή, ένα αρχείο που έχει γραφτεί σε little-endian platform δεν διαβάζεται σωστά σμετά σε big-endian platform.

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

Re: C99: Hunt

Δημοσίευσηαπό simosx » 07 Μάιος 2012, 19:48

simosx έγραψε:
Ilias95 έγραψε:
Δοκίμασα να κάνω ένα Project στο Anjuta όπως είπες, αλλά χάθηκα τελείως. Οκ, δημιουργήθηκαν κάποια αρχεία αυτόματα. Μετά;
Κάποιος οδηγός; (Θυμάμαι ότι ανέφερες πως έχεις γράψει κάποιον οδηγό στο LinuxInside. Υπάρχει διαθέσιμος online;)


Γενικά τον βάζουν στο http://www.linuxinside.gr μετά από κάποιο χρονικό διάστημα. Το κείμενο που έγραψα είναι σε μορφή κατάλληλο για στοιχειοθεσία οπότε μάλλον δε θα βοηθήσει ως έχει.
Θα πρότεινα να ξεκινούσες μια νέα δημοσίευση με τίτλο π.χ. «Υποστήριξη autotools στο πρόγραμμά μου;»
όπου θα βοηθήσουμε όλοι να απαντήσουμε σε ερωτήματα. Και θα μπορούν και άλλα μέλη να μάθουν ταυτόχρονα.

Γενική περιγραφή, http://en.wikipedia.org/wiki/GNU_build_system


Έκανα την ανακοίνωση,
viewtopic.php?f=6&t=23193
όπου έχω και παράδειγμα κώδικα για το hunt. Δεν έχω βάλει μέσα τον κώδικα του hunt, ωστόσο είναι κάτι σχετικά εύκολο που είναι καλό να κάνεις ο ίδιος.
Αυτό που κάνεις είναι μεταφέρεις τα αρχεία από το παραπάνω .zip στο αποθετήριό σου, και δοκιμάζεις ότι όλα πάνε καλά.
Είναι σημαντικό να προσέξεις τι ενδιάμεσα αρχεία παράγονται, διότι για τα αρχεία αυτά θέλεις να τα κάνεις .gitignore, μιας και είναι ενδιάμεσα (δεν πρέπει να εμφανίζονται στο git).
προσωπικό ιστολόγιο ϗ πλανήτης Ubuntu-gr
Συμβάλετε και εσείς στο ελληνικό βιβλίο Ubuntu!
1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 13.10 saucy 3.11.0-031100rc1-generic 64bit (el_GR.UTF-8, Unity ubuntu)
3 AMD E-450 APU with Radeon HD Graphics ‖ RAM 3555 MiB ‖ Sony Corporation VAIO
4 AMD nee ATI Wrestler [Radeon HD 6320] [1002:9806] {fglrx_pci}
5 eth0: Atheros Inc. AR8151 v2.0 Gigabit Ethernet [1969:1083] (rev c0) ⋮ wlan0: Atheros Inc. AR9285 [168c:002b] (rev 01)
Φτιάξτε και εσείς τη δική σας υπογραφή (παραπάνω κείμενο) αυτόματα με κλικ εδώ!
simosx
Επίτιμο μέλος
Επίτιμο μέλος
 
Δημοσιεύσεις: 10334
Εγγραφή: 11 Μάιος 2008, 18:52
Launchpad: simosx
IRC: simosx
Εκτύπωση

Re: C99: Hunt

Δημοσίευσηαπό Ilias95 » 09 Μάιος 2012, 19:47

@simosx
Ευχαριστώ για την βοήθεια.
Δεν το χρειάζομαι άμεσα και δεν θα το πολύ ψάξω τώρα.
Όταν ασχοληθώ κάποια στιγμή θα γράψω τι κατάφερα στο νήμα που άνοιξες.

@migf1
Δεν ξέρω. Ακόμα μου φαίνεται περίεργο να καλώ στην printf() enumerator values.
Δεν μπορείς να δεις με την πρώτη ματιά τι εκτυπώνεται σε κάθε συνάρτηση. Πρέπει συνεχώς να ανατρέχεις στα textfiles.

Και όταν θα έχω 2000 string μέσα στο πρόγραμμα;
Θα πρέπει να γράψω 2000 διαφορετικά ονόματα στον enumerator, ένα για κάθε string; :shock: :shifty:

Σκέψου και το άλλο. Έστω ότι έχω πάλι 2000 strings και έχω μεταφράσει το πρόγραμμα σε 20 γλώσσες.
Κάθε φορά που θα χρειαστεί να σβήσω ένα string μέσα στον enumerator ή να αλλάξω θέση στον ορισμό μερικών, θα πρέπει πειράξω ένα ένα και τα 20 αρχεία κειμένου για κάθε γλώσσα ξεχωριστά!!!

Παρ' αυτά είμαι σίγουρος ότι κάποια στιγμή θα μου φανεί χρήσιμο το post σου γι' αυτό το έκανα bookmark. :)
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: C99: Hunt

Δημοσίευσηαπό migf1 » 09 Μάιος 2012, 22:10

Αυτός είναι όμως ο τρόπος. Π.χ. όλα τα GUI έτσι δουλεύουν (resource/glade files). Το gettext επίσης έτσι δουλεύει (άμα ανοίξεις το .pot αρχείο θα δεις πως δεν είναι τίποτε άλλο από αντιστοιχίσεις μεταξύ ID και κειμένων).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: C99: Hunt

Δημοσίευσηαπό Ilias95 » 09 Μάιος 2012, 22:30

Σωστά.
Η τρόπος όμως για να κάνεις generate, merge κλπ τα αρχεία είναι αυτοματοποιημένος.
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: C99: Hunt

Δημοσίευσηαπό migf1 » 09 Μάιος 2012, 23:04

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

Re: C99: Hunt

Δημοσίευσηαπό Ilias95 » 09 Μάιος 2012, 23:20

migf1 έγραψε:Είχα όμως την εντύπωση πως το συζητούσαμε στα πλαίσια της προγραμματιστικής εξοικείωσης/εκμάθησης.

Αν το δούμε έτσι, ναι σίγουρα κάτι παραπάνω θα κερδίσει όποιος ασχοληθεί. Απλά νομίζω ότι δεν είναι και τόσο ουσιαστικό σε αυτή τη φάση.
Βασικά μου φαίνεται λιγάκι χαμαλοδουλειά και δεν ξέρω αν αξίζει τον κόπο στην προκειμένη περίπτωση (και για την συγκεκριμένη εφαρμογή).
Προτιμώ να υλοποιήσω τα high scores, και save/load. :P
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: C99: Hunt

Δημοσίευσηαπό migf1 » 10 Μάιος 2012, 15:44

Ilias95 έγραψε:
migf1 έγραψε:Είχα όμως την εντύπωση πως το συζητούσαμε στα πλαίσια της προγραμματιστικής εξοικείωσης/εκμάθησης.

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

Έχει και χαμαλοδουλειά (και μπόλικη). Από την άλλη σε εξοικειώνει παράλληλα και με άλλα πέρα των μεταφράσεων (π.χ. file-parsing, pointers, arrays, ακόμα και με τον pre-processor ανάλογα πως θα το υλοποιήσεις).

έγραψε:Προτιμώ να υλοποιήσω τα high scores, και save/load. :P

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

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

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

cron