migf1 Δημοσ. 6 Αυγούστου 2012 Δημοσ. 6 Αυγούστου 2012 Διαβάζω αυτή τη περίοδο για εισαγωγή ορισμάτων στη main και λέει το βιβλίο ότι τα ορίσματα γραμμής εντολής,μπλα μπλα μπλα...Γραμμή εντολής εννοεί το command prompt,σωστά:Γιατί εμένα δεν μπορεί να τρέξει τίποτα(το σφάλμα-'όνομα προγράμματος'δεν αναγνωρίζεται ως εσωτερική ή εξωτερική εντολή,εκτελέσιμο πρόγραμμα ή αρχείο δέσμης ενεργειών). Υ.Γ.'όνομα προγράμματος' είναι ένα οποιοδήποτε όνομα,δεν είναι το όνομα που έχω δώσει εγώ στο πρόγραμμα. Δεν είμαι σίγουρος πως έχω καταλάβει τι ρωτάς, αλλά ανεξαρτήτως compiler, όταν δημιουργήσεις ένα myprog.exe τότε αν μπεις στο φάκελο που το περιέχει με cd από την γραμμή εντολών και γράψεις: myprog (ή myprog.exe) τότε θα στο τρεξει. Command-line arguments είναι οτιδήποτε άλλο προσθέσεις μετά το όνομα του προγράμματος στην γραμμή εντολών πριν πατήσεις το ENTER. Χρειαζεται να περνάς το μήκος του πινακα ως ορισμα γιατι το χρησιμοποιεις και στις 2 συναρτησεις..... εκτος και αν εννοεις αλλο πραγμα... συμφωνα με την συγκεκριμενη παντα υλοποιηση. Δεικτες δεν εχω κοιταξει ακομη Προφανώς και χρειάζεται να ξέρουν και οι 2 συναρτήσεις το μέγεθος της στοίβας. Αντί ομως να το περνάς σαν όρισμα, μπορείς να το ενσωματώσεις ως πεδίο μέσα στο struct της στοιβας και να περνάς μόνο αυτό το struct στις συναρτήσεις, by refrence. Το by-reference πέρασμα δεν λογίζεται ως υλοποίηση της στοίβας με δείκτες. Χωρίς struct είναι αχρείαστη περιπλοκή του κώδικα, όπως φαίνεται και στον κώδικα που ποστάρισε ο timon, όπου "αναγκάζεται" να καταφύγει σε τρικ όπως π.χ. το να κρατάει το μέγεθος της στοίβας στο 1ο στοιχείο του πίνακα. Btw, η σελίδα της Wikipedia για τις στοίβες είναι άκρως κατατοπιστική, και μεταξύ πολλών άλλων δίνει και κώδικα για διαφορετικές υλοποιήσεις.
capoelo Δημοσ. 6 Αυγούστου 2012 Μέλος Δημοσ. 6 Αυγούστου 2012 > #include<stdio.h> #include<stdlib.h> int main(int argc,char *argv[]) { int i=0; char f[][3][80]={"add","substract",""}; int k=atoi(argv[2]); int j=atoi(argv[3]); if(f[i][0])printf("The sum is:%d\n",k+j); else if(f[i][1])printf("The result is:%d\n",j-k); system("Pause"); return 0; } Ποιο το λάθος μου εδώ;Μου βγάζει κανονικότατα το άθροισμα(ότι αριθμούς κι αν χρησιμοποιήσω)και εμφανίζει πρόβλημα στην αφαίρεση. Υ.Γ.Για να σας προλάβω,το πρόγραμμα δεν εκτελεί κανέναν απολύτως έλεγχο για το πιο είναι μεγαλύτερο και πιο μικρότερο επειδή απλά βαριόμουν να το γράψω,όχι επειδή δεν ξέρω ότι πρέπει να γίνει αυτός ο έλεγχος στη δεύτερη περίπτωση.
migf1 Δημοσ. 6 Αυγούστου 2012 Δημοσ. 6 Αυγούστου 2012 > #include<stdio.h> #include<stdlib.h> int main(int argc,char *argv[]) { int i=0; char f[][3][80]={"add","substract",""}; int k=atoi(argv[2]); int j=atoi(argv[3]); if(f[i][0])printf("The sum is:%d\n",k+j); else if(f[i][1])printf("The result is:%d\n",j-k); system("Pause"); return 0; } Ποιο το λάθος μου εδώ;Μου βγάζει κανονικότατα το άθροισμα(ότι αριθμούς κι αν χρησιμοποιήσω)και εμφανίζει πρόβλημα στην αφαίρεση. Υ.Γ.Για να σας προλάβω,το πρόγραμμα δεν εκτελεί κανέναν απολύτως έλεγχο για το πιο είναι μεγαλύτερο και πιο μικρότερο επειδή απλά βαριόμουν να το γράψω,όχι επειδή δεν ξέρω ότι πρέπει να γίνει αυτός ο έλεγχος στη δεύτερη περίπτωση. Δώσε μας μερικά πλήρη παραδείγματα των command lines που γράφεις και τα αποτελέσματα που σου βγάζουν. Επίσης δεν καταλαβαίνω τι προσπαθείς να κάνεις με τον f[][][] ... ή μάλλον καταλαβαίνω πως θες να δεις αν σου γράφει μια από αυτές τις λέξεις στην command line, αλλά δεν καταλαβαίνω γιατί είναι 3Δ o πίνακας και τι προσπαθείς να ελέγξεις με τo if-else.
migf1 Δημοσ. 6 Αυγούστου 2012 Δημοσ. 6 Αυγούστου 2012 Αν έχω καταλάβει σωστά τι θες να κάνει ο κώδικας που παρέθεσες, είναι κάτι σαν το παρακάτω... > #include <stdio.h> #include <stdlib.h> #include <string.h> /**********************************************/ int usage( char *argv[], char f[][80] ) { printf( "usage: %s %s|%s n1 n2\n", argv[0], f[0], f[1] ); system( "pause" ); return 1; } /**********************************************/ int main( int argc, char *argv[] ) { char f[][80] = { "add", "subtract" }; if ( argc < 4 ) return usage( argv, f ); if ( 0 == strcmp( argv[1], f[0] ) ) printf( "The sum is: %d\n", atoi(argv[2]) + atoi(argv[3]) ); else if ( 0 == strcmp( argv[1], f[1] ) ) printf( "The difference is: %d\n", atoi(argv[2]) - atoi(argv[3]) ); else return usage( argv, f ); system( "pause" ); exit(0); } Έξοδος... > > gcc a5.c -o a5.exe > a5 usage: a5 add|subtract n1 n2 Press any key to continue . . . > a5 add usage: a5 add|subtract n1 n2 Press any key to continue . . . > a5 add 3 usage: a5 add|subtract n1 n2 Press any key to continue . . . > a5 3 add 2 usage: a5 add|subtract n1 n2 Press any key to continue . . . > a5 add 2 3 The sum is: 5 Press any key to continue . . . > a5 subtract 2 3 The difference is: -1 Press any key to continue . . . >
imitheos Δημοσ. 9 Αυγούστου 2012 Δημοσ. 9 Αυγούστου 2012 Το μεσημέρι κάνοντας sign-in είδα ότι πριν λίγες μέρες μου ήρθε ένα pm (σόρυ για την αργοπορία) από ένα φίλο εδώ που έλεγε ότι διάβασε ότι τα Hash Tables χρησιμοποιούνται για γρήγορο search και ήθελε πληροφορίες για αυτά για να ασχοληθεί. Γενικά δεν θεωρώ σωστό να "βγάζω" pm στο φόρουμ αλλά το συγκεκριμένο δεν έχει εμπιστευτικό περιεχόμενο οπότε παίρνω το θάρρος να το αναφέρω και ελπίζω να μην θυμώσει ο OP. Εδώ θα μπορούν να συνεισφέρουν και άλλα άτομα τις γνώσεις τους εξηγώντας κάποια έννοια με πιο εύκολα λόγια ή διορθώνοντας με αν πω κάποια ανακρίβεια (χάριν ευκολίας και σύμπτυξης ενός μεγάλου κεφαλαίου σε ένα post θεωρώ ότι κάμποσα από αυτά που θα πω δεν θα είναι τελείως ακριβή). Το αντίστοιχο άρθρο της Wikipedia εξηγεί εκτενώς τι είναι τα HT. Πολλές φορές θέλουμε να αντιστοιχίσουμε ένα "κλειδί" με μια "τιμή". Ακόμη και το array indexing που χρησιμοποιούμε τόσο συχνά μπορεί να θεωρηθεί τέτοια αντιστοίχιση όπου το κλειδί είναι ο αριθμός του στοιχείο του πίνακα και η τιμή είναι αυτή που θέτουμε. Εκτός από αριθμητικό κλειδί όπως σε array, μπορούμε να έχουμε πχ αλφαριθμητικό κλειδί όπως στο κλασικό παράδειγμα του τηλεφωνικού καταλόγου όπου αντιστοιχούμε ένα όνομα με ένα τηλέφωνο. Στο παραπάνω παράδειγμα με τον τηλεφωνικό κατάλογο, ας υποθέσουμε ότι έχουμε μια πόλη με 50000 οικογένειες οπότε έχουμε ένα πίνακα 50000 στοιχείων όπου κάθε στοιχείο είναι μια δομή (πχ όνομα, διεύθυνση, επάγγελμα, τηλέφωνο). Για να βρούμε το δικό μου τηλέφωνο πρέπει να πάρουμε σβάρνα ένα-ένα όλα τα στοιχεία του πίνακα και να ελέγχουμε αν το στοιχείο.name είναι ίδιο με το δικό μου. Ανάλογα με την αλφαβητική σειρά των ονομάτων των κατοίκων μπορεί να είμαστε τυχεροί και το τηλέφωνο μου να είναι η 5η καταχώρηση αλλά μπορεί κάλλιστα να είναι και στην 5000η. Μία από τις πολλές χρήσεις των Hash Tables είναι σε αυτή την περίπτωση. Πριν μιλήσουμε για τα ίδια τα HT, ας αναφέρουμε τις hash functions. Όταν κατεβάζουμε αρχεία στο διαδίκτυο συχνά βλέπουμε να αναφέρεται "MD5 Hash", "SHA256 Hash", κτλ δίπλα στο όνομα του αρχείου. Αυτό είναι ένα αναγνωριστικό ώστε να διαπιστώσουμε αν το αρχείο που έχουμε κατεβάσει είναι σωστό και δεν έχει κοπεί στη μέση το κατέβασμα ή να έχουν κατεβεί σκουπίδια. Αυτά τα αναγνωριστικά παράγονται από μια συνάρτηση κερματισμού όπως η SHA256. Οι συναρτήσεις κερματισμού έχουν ως σκοπό να μετασχηματίζουν ένα σετ δεδομένων μεταβλητού μεγέθους σε δεδομένα σταθερού μεγέθους. Έτσι ένα hash που παράγεται από τον παραπάνω SHA256 αλγόριθμο θα είναι πάντα 256bit άσχετα αν η είσοδος ήταν 1 Byte ή 1Terabyte. Για να γίνουν πιο κατανοητά αυτά που είπα ας δούμε κάποιες πολύ απλές hash functions: > unsigned int hash1(char *s) { unsigned int hash = 0; int c; while (c = *s++) hash += c; return hash; } unsigned int hash2(char *s) { unsigned int hash = 7; int c; while (c = *s++) hash = hash * 3 + c; return hash; } Όπως βλέπουμε, οι παραπάνω συναρτήσεις παίρνουν είσοδο μεταβλητού μεγέθους (null-terminated "string") και με βάση αυτή την είσοδο μας επιστρέφουν δεδομένα σταθερού μεγέθους (unsigned int). Η συνάρτηση hash1 είναι από τις πιο απλές hash functions που μπορούμε να έχουμε. Αυτό που κάνει είναι να προσθέτει τον κάθε χαρακτήρα και να μας επιστρέφει το σύνολο. Λόγω αυτής της λειτουργίας της θα μας δώσει ίδιο hash για τα strings "abc" και "acb". Η συνάρτηση hash2 διορθώνει αυτό το θέμα με το να πολλαπλασιάζει το μέχρι τώρα hash επί τρία πριν προσθέσει τον εκάστοτε χαρακτήρα οπότε η σειρά των χαρακτήρων είναι σημαντική. Όταν δεν προκύπτουν συγκρούσεις τότε η συνάρτηση ονομάζεται τέλεια (προφανώς οι δύο παραπάνω δεν είναι τέλειες). Οι συναρτήσεις που βλέπουμε στην πιστοποίηση δεδομένων όπως η SHA256 που αναφέραμε πριν ανήκουν όπως καταλαβαίνουμε σε μια ειδική κατηγορία που παρέχει διάφορες εγγυήσεις όπως ότι δεν μπορείς να αλλάξεις την είσοδο χωρίς να αλλάξει το hash και πολλά άλλα που φυσικά δεν προσφέρουν οι παραπάνω συναρτήσεις που έγγραψα. Υπάρχουν όμως περιπτώσεις που ακόμη και αυτές οι "χαζές" συναρτήσεις αρκούν (για παράδειγμα αν δούμε στη σελίδα 95 του πρωτοκόλλου ELF που ακολουθούν τα εκτελέσιμα αρχεία σε πολλά UNIXοειδή θα δούμε ότι χρησιμοποιεί μια τέτοια χαζή συνάρτηση). Γιατί τα έγραψα όμως όλα αυτά και τι μας νοιάζουν οι hash functions ? Γιατί μπορούν να μας βοηθήσουν στην παραπάνω περίπτωση του τηλεφωνικού καταλόγου. > |--|----------------| |0 |Alexandros | |--|----------------| |1 |Baggelis | |--|----------------| |2 |Despoina | |--|----------------| |3 |Fanis | |--|----------------| |4 |Imitheos | |--|----------------| |5 |Kotsos | |--|----------------| |6 |Mitsos | |--|----------------| |7 | | |--|----------------| Στον παραπάνω πίνακα έχουμε εισάγει αλφαβητικά τα ονόματα. Έτσι για να βρούμε εμένα πρέπει, όπως είπαμε, να ψάξουμε μία-μία εγγραφή. Γιατί όμως να τα εισάγουμε αλφαβητικά ? Edit: code tag γ..σαι ρε. Μη σε πετύχω έξω μόνο. Θα χρησιμοποιήσουμε την Χ συνάρτηση κερματισμού. Κατά την εισαγωγή του εκάστοτε στοιχείου, πετάμε το string μας στην συνάρτηση και μας παράγει ένα αριθμό. Έστω ότι για το string "Imitheos" μας δίνει τον αριθμό 3. Έτσι θα βάλουμε την καταχώρηση στην θέση 3. Για το "Alexandros" μας δίνει 1 οπότε θα μπει στην θέση 1. Συνεχίζουμε για κάθε στοιχείο και το βάζουμε στην αντίστοιχη θέση του και προκύπτει ο παρακάτω πίνακας. > |--|----------------| |0 |Fanis | |--|----------------| |1 |Alexandros | |--|----------------| |2 |Mitsos | |--|----------------| |3 |Imitheos | |--|----------------| |4 |Despoina | |--|----------------| |5 |Baggelis | |--|----------------| |6 |Kotsos | |--|----------------| |7 | | |--|----------------| Θα μου πεις τί κερδίσαμε τώρα με αυτό ? Αντί να ψάχνουμε μία-μία τις καταχωρήσεις για να βρούμε αυτήν που θέλουμε, απλά τρέχουμε την hash function πάνω στο όνομα που ζητάμε και ο αριθμός που μας δίνει η συνάρτηση είναι κατευθείαν η θέση που ζητάμε στον πίνακα. Έτσι εξαλείφουμε τον χρόνο αναζήτησης που είχαμε πριν. Ανάλογα με την συνάρτηση κερματισμού που θα επιλέξουμε, έχουμε ένα μικρό ή μεγάλο κόστος στον χρόνο εκτέλεσης λόγω του υπολογισμού αυτού του παραγόμενου αριθμού αλλά αυτός ο υπολογισμός γίνεται μια φορά οπότε όσο περισσότερες καταχωρήσεις έχουμε να ψάξουμε, τόσο πιο αμελητέο γίνεται το overhead της hash function. Μπακάλικα δηλαδή το Hash Table είναι ένας κανονικός πίνακας (ή linked list ή οτιδήποτε) και μια συνάρτηση κερματισμού για το indexing. Παρακάτω θα αναφέρω ένα πολύ απλό παράδειγμα HT. Μην περιμένετε τπτ τρομερό κώδικα . Χάριν ευκολίας θα παραλείψω headers, prototypes καθώς και ελέγχους όπως malloc και τέτοια. > struct lentry { char name[50]; char tel[15]; }; struct hashtable { int size; struct lentry *table; }; Το HT μας είναι μια απλή δομή που ορίζει μόνο το μέγεθός του και ένα πίνακα από καταχωρήσεις ο οποίος θα εκχωρηθεί δυναμικά. Η κάθε καταχώρηση αποτελείται από όνομα και τηλέφωνο. > struct hashtable *hcreate(int size) { struct hashtable *newtable; newtable = malloc(sizeof(struct hashtable)); newtable->table = malloc(sizeof(struct lentry) * size); newtable->size = size; return newtable; } Η συνάρτηση hcreate αρχικοποιεί (δημιουργεί) το hash table μας. Πρώτα εκχωρεί μνήμη για την δομή του ίδιου του hashtable και μετά για size καταχωρήσεις lentry. Θεωρητικά θα έπρεπε να ελέγχω αν το size είναι θετικό και αν η malloc κατάφερε να εκχωρήσει μνήμη. > unsigned int hashfunc(struct hashtable *hashtable, char *name) { unsigned int hash = 7; int c; while (c = *name++) hash = hash * 3 + c - 'A'; return hash % hashtable->size; } Εδώ έχουμε την συνάρτηση κερματισμού που θα χρησιμοποιήσουμε για τo indexing του πίνακα μας. Είναι ίδια με την χαζή hash2 που έγραψα πριν με 2 διαφορές. Αφενώς παράγει μικρότερο αριθμό hash επειδή αφαιρώ το 'A' από κάθε γράμμα και αφετέρου ανάγει αυτό τον αριθμό στο μέγεθος του hash table που έχουμε δημιουργήσει. Εννοείται πως συγκρούσεις υπήρχαν και στην αρχική hash2 αλλά τώρα λόγω της αναγωγής του αριθμού στο πολύ-μικρότερο-από-το-εύρος-του-int size θα έχουμε περισσότερες συγκρούσεις. Εκτός από αυτό ούτε ελέγχω τα hashtable και name. > struct lentry *hlookup(struct hashtable *hashtable, char *name) { unsigned int hash = hashfunc(hashtable, name); int found; found = strcmp(hashtable->table[hash].name, name); if (found == 0) return &hashtable->table[hash]; else return NULL; } Η συνάρτηση αναζήτησής μας. Όπως βλέπουμε υπολογίζει το hash του ονόματος που ζητάμε και μετά δουλεύει κατευθείαν με την θέση που λέει το hash αντί να ψάχνει μία-μία καταχώρηση. > int hinsert(struct hashtable *hashtable, char *name, char *tel) { unsigned int hash = hashfunc(hashtable, name); memcpy(hashtable->table[hash].name, name, 50); memcpy(hashtable->table[hash].tel, tel, 15); return 0; } Ο τρόπος εισαγωγής που εξήγησα πριν. Βρίσκουμε το hash του ονόματος και το χρησιμοποιούμε ως θέση στον πίνακα οπότε μπορούμε να έχουμε γρήγορη αναζήτηση. > void hdestroy(struct hashtable *hashtable) { free(hashtable->table); free(hashtable); } Απλό free της μνήμης. > int main(void) { struct hashtable *htable; struct lentry *hentry; htable = hcreate(10); hinsert(htable, "Mitsos", "12345"); hinsert(htable, "Kotsos", "54321"); printf("Searching for Imitheos\n"); hentry = hlookup(htable, "Imitheos"); if (hentry == NULL) printf("Not Found\n"); else printf("Tel = %s\n", hentry->tel); hinsert(htable, "Imitheos", "22331"); printf("Searching again for Imitheos\n"); hentry = hlookup(htable, "Imitheos"); if (hentry == NULL) printf("Not Found\n"); else printf("Tel = %s\n", hentry->tel); return 0; } Έξοδος: Searching for Imitheos Not Found Searching again for Imitheos Tel = 22331 Η main για να δούμε τι κάναμε πριν με τις συναρτήσεις. Δημιουργούμε ένα HT με μέγεθος 10 στοιχεία. Έπειτα εισάγουμε 2 στοιχεία και ψάχνουμε εμένα. Όπως είναι λογικό δεν με βρίσκει. Μετά εισάγουμε εμένα και τρέχουμε ξανά την αναζήτηση η οποία με βρίσκει και εμφανίζει το τηλέφωνό μου. Εννοείται πως για να έχει πρακτική εφαρμογή ο κώδικας θα πρέπει να κάνουμε μια πολύ καλύτερη υλοποίηση των δομών και των συναρτήσεων και να επιλέξουμε και μια καλή hash function. Ελπίζω όμως ο παραπάνω να είναι αρκετά απλός και κατανοητός. 4
Re4cTiV3 Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 Ωραια εξηγηση! Εγω ειχα αυτην ερωτηση Ευχαριστω! Σε περιπτωση ΑΦΜ ομως δεν χρειαζεται καποια ειδικη hash συναρτηση σωστα; Εγω εχω μια "ασκηση" οπου εχω δυο structs τα οποια ειναι καπως ετσι struct afm { int afm; struct afm *next; struct dep *depPtr; } struct dep { int poso; int depAfm; struct dep *next; } κατι τετοιο δεν θυμαμαι τωρα γιατι ειμαι απο κινητο.. Η ασκηση ζηταει να να κανω μια απλη συνδεδεμενη λιστα με τις παραπανω δομες και μετα να εφαρμοσω hash πανω στην λιστα.. Γινεται με καποιο τροπο, αφου κανω το αναλογο hash insert στον πινακα, να κανω lookup και να εχω αμεση προσβαση στο "struct afm" ???
Star_Light Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 Καλημέρα και απο μενα. Μετα απο λιγο καιρο απουσιας ειπα να ξεσκουριασω λιγο.... > /************************************************************************ * Το πρόγραμμα υπολογιζει τις εμφανίσεις(πανω απο μια φορα) των γραμμάτων * σε μια πρόταση. Αν ένα γραμμα εμφανίζεται παραπανω απο μια φορα τυπώνονται * ο αριθμος εμφάνισης καθως και το γράμμα. Σε αντιθετη περίπτωση τυπώνεται * ενα μήνυμα οτι δεν υπάρχουν παραπανω εμφανισεις . Το πρόγραμμα δεν επεξεργάζεται * κενές ή άκυρες προτάσεις . */ #include <stdio.h> #include <ctype.h> #include <stdbool.h> #include <stdlib.h> #define ALPH_len 26 char check_letters[ALPH_len]={0} , letters[ALPH_len]= {0}; int i=0; void read( char ch ); void check( char [] , char []); void clear( char [] , char []); int main(void) { char ch = '0' ; for(; { puts(" Δώσε πρόταση : "); read(ch); check(check_letters , letters); clear(check_letters , letters); } return 0; } //---Διάβασμα εισόδου απο τον χρήστη ----------------------------------- void read(char ch) { bool sentimel = true; while((ch=tolower(getchar()))!='\n') { if( isalpha(ch) ) { letters[ch-'a']= ch; check_letters[ch -'a']++; sentimel = false; } if( !isalpha(ch) && sentimel ) { puts(" Δεν υπάρχει έγκυρη προταση. "); exit(EXIT_SUCCESS); } } // Εκτός loop if( sentimel ) { puts(" Kενή προταση. "); exit(EXIT_SUCCESS); } return; } //-- Τσεκάρισμα για παραπάνω απο μια εμφανίσεις των γραμμάτων----------- void check( char check_letters[ALPH_len] , char letters[ALPH_len]) { bool count = false; for(i=0; i<ALPH_len; i++) { if( check_letters[i] > 1 ) { printf("\nEμφάνιση γράμματος %c : %d φορές\n" , letters[i] , check_letters[i] ); count = true ; } } if( !count ) printf("\n Καμια εμφάνιση πανω απο μια φορα."); return; } //--- Καθαρισμός της μνήμης--------------------------------------------- void clear( char check_letters[ALPH_len] , char letters[ALPH_len] ) { i=0; while (i < ALPH_len) { check_letters[i] = 0; letters[i] = 0; ++i; } return; } http://ideone.com/IKMlh για καλυτερη στοιχιση. Δεν κρυβω οτι οι global και συγκεκριμενα ο μετρητης i μου δημιουργησαν κάποια bugs. Σαν αυτα που λεει και ο King στην Σελ. 223 P.S Δεν ειναι με strings η υλοποιηση (γιατι με δεικτες ειναι) . Προσωπικη επιλογη προς το παρον....
migf1 Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 Ωραια εξηγηση! Εγω ειχα αυτην ερωτηση Ευχαριστω! Σε περιπτωση ΑΦΜ ομως δεν χρειαζεται καποια ειδικη hash συναρτηση σωστα; Από τη στιγμή που τα ΑΦΜ είναι μοναδικά και χρησιμοποιούνται ως κλειδιά, τότε εκ 1ης όψεως δεν χρειάζονται hashing. Εγω εχω μια "ασκηση" οπου εχω δυο structs τα οποια ειναι καπως ετσι struct afm { int afm; struct afm *next; struct dep *depPtr; } struct dep { int poso; int depAfm; struct dep *next; } κατι τετοιο δεν θυμαμαι τωρα γιατι ειμαι απο κινητο.. Η ασκηση ζηταει να να κανω μια απλη συνδεδεμενη λιστα με τις παραπανω δομες και μετα να εφαρμοσω hash πανω στην λιστα.. Γινεται με καποιο τροπο, αφου κανω το αναλογο hash insert στον πινακα, να κανω lookup και να εχω αμεση προσβαση στο "struct afm" ??? Θα πρέπει να μας δείξεις την εκφώνηση της άσκησης. Από τα παραπάνω εγώ βλέπω μια απλή λίστα από ΑΦΜ, ο κάθε κόμβος της οποίας περιέχει μια άλλη απλή λίστα από dep's... αλλά από μόνο του δεν μας δίνει να καταλάβουμε τι ζητάει η άσκηση. ΥΓ. Παρεμπιπτόντως, μια πολύ ωραία online πηγή όχι μόνο για hashtables αλλά και για άλλες χρήσιμες δομές, είναι η Enternally Confuzzled. Navigation από το δέντρο στα αριστερά. Καλημέρα και απο μενα. Μετα απο λιγο καιρο απουσιας ειπα να ξεσκουριασω λιγο.... > /************************************************************************ * Το πρόγραμμα υπολογιζει τις εμφανίσεις(πανω απο μια φορα) των γραμμάτων * σε μια πρόταση. Αν ένα γραμμα εμφανίζεται παραπανω απο μια φορα τυπώνονται * ο αριθμος εμφάνισης καθως και το γράμμα. Σε αντιθετη περίπτωση τυπώνεται * ενα μήνυμα οτι δεν υπάρχουν παραπανω εμφανισεις . Το πρόγραμμα δεν επεξεργάζεται * κενές ή άκυρες προτάσεις . */ #include <stdio.h> #include <ctype.h> #include <stdbool.h> #include <stdlib.h> #define ALPH_len 26 char check_letters[ALPH_len]={0} , letters[ALPH_len]= {0}; int i=0; void read( char ch ); void check( char [] , char []); void clear( char [] , char []); int main(void) { char ch = '0' ; for(; { puts(" Δώσε πρόταση : "); read(ch); check(check_letters , letters); clear(check_letters , letters); } return 0; } //---Διάβασμα εισόδου απο τον χρήστη ----------------------------------- void read(char ch) { bool sentimel = true; while((ch=tolower(getchar()))!='\n') { if( isalpha(ch) ) { letters[ch-'a']= ch; check_letters[ch -'a']++; sentimel = false; } if( !isalpha(ch) && sentimel ) { puts(" Δεν υπάρχει έγκυρη προταση. "); exit(EXIT_SUCCESS); } } // Εκτός loop if( sentimel ) { puts(" Kενή προταση. "); exit(EXIT_SUCCESS); } return; } //-- Τσεκάρισμα για παραπάνω απο μια εμφανίσεις των γραμμάτων----------- void check( char check_letters[ALPH_len] , char letters[ALPH_len]) { bool count = false; for(i=0; i<ALPH_len; i++) { if( check_letters[i] > 1 ) { printf("\nEμφάνιση γράμματος %c : %d φορές\n" , letters[i] , check_letters[i] ); count = true ; } } if( !count ) printf("\n Καμια εμφάνιση πανω απο μια φορα."); return; } //--- Καθαρισμός της μνήμης--------------------------------------------- void clear( char check_letters[ALPH_len] , char letters[ALPH_len] ) { i=0; while (i < ALPH_len) { check_letters[i] = 0; letters[i] = 0; ++i; } return; } http://ideone.com/IKMlh για καλυτερη στοιχιση. ... Μπορείς να φτιάξεις την στοίχιση; Ακόμα και στο ideone είναι αλλοπρόσαλλη. ... Δεν κρυβω οτι οι global και συγκεκριμενα ο μετρητης i μου δημιουργησαν κάποια bugs. Σαν αυτα που λεει και ο King στην Σελ. 223 P.S Δεν ειναι με strings η υλοποιηση (γιατι με δεικτες ειναι) . Προσωπικη επιλογη προς το παρον.... Λόγω κακής στοίχισης δεν έχω την διάθεση να κοιτάξω προσεκτικά τον κώδικα, αλλά σε 1η ανάγνωση βλέπω διάφορα bad-practices, με 1ο και καλύτερο την χρήση καθολικών μεταβλητών (προσωπικά το έχω απορία γιατί επιμένεις στα globals παρόλο που όλοι σου έχουμε πει να τα αποφεύγεις). Ένα άλλο εμφανές bad-practice είναι η ανάμιξη πεζών και κεφαλαίων στο όνομα της σταθεράς ALPH_len. Επίσης, εκείνο το ch που περνάς ως όρισμα στην read() μέσα στην main() τι νόημα έχει; Γιατί π.χ. δεν είναι τοπική μεταβλητή της read() ;
migf1 Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 @Starlight: ο παρακάτω κώδικας κάνει ότι ο δικός σου συν μερικά ακόμα (π.χ δουλεύει για όλη τη πρόταση, μετράει κανονικούς και αντικανονικούς χαρακτήρες, προβλέπει εντολή εξόδου, κλπ). Επίσης, αλγοριθμικά διαφέρει στο ότι πρώτα διαβάζει την είσοδο σε ένα string και μετά την επεξεργάζεται (εσύ το κάνεις την επεξεργασία ταυτόχρονα με το διάβασμα). Τέλος δεν χρησιμοποιεί custom συναρτήσεις. > /************************************************************************ * Το πρόγραμμα υπολογιζει τις εμφανίσεις(πανω απο μια φορα) των γραμμάτων * σε μια πρόταση. Αν ένα γραμμα εμφανίζεται παραπανω απο μια φορα τυπώνονται * ο αριθμος εμφάνισης καθως και το γράμμα. Σε αντιθετη περίπτωση τυπώνεται * ενα μήνυμα οτι δεν υπάρχουν παραπανω εμφανισεις. */ #include <stdio.h> // printf(), puts(), fgets() #include <ctype.h> // isaplha() #include <string.h> // memset() #include <stdlib.h> // exit() #define MAXINPUT (255+1) #define MAXLETTS 26 #define EXITCHAR '@' /** ***************************************** */ int main( void ) { char input[ MAXINPUT ] = {'\0'}; int lettcount[ MAXLETTS ] = {0}; char *cp = NULL; int i=0, count=0, len=0, nValid=0, nInvalid=0; for (; { printf( "\nType a sentence (%c to exit): ", EXITCHAR ); // read and store the sentence into string: input if ( !fgets(input, MAXINPUT, stdin) ) { puts( "*** internal error, aborting..." ); goto exit_failure; } if ( EXITCHAR == *input ) // quit program break; if ( '\n' == *input ) // ask again continue; // count & store letter occurrences in array: lettcount[] // also count total length, valid letters & invalid chars for (cp=input, len=0, nValid=0; *cp; cp++,len++) { if ( isalpha(*cp) ) { lettcount[ tolower(*cp) - 'a' ]++; nValid++; } } nInvalid = len - nValid - 1; // print results for (i=0, count=0; i < MAXLETTS; i++) { if ( lettcount[i] > 1 ) { printf( "%c: %d occurrences\n", i+'a', lettcount[i] ); count++; } } if ( 0 == nValid ) puts( "invalid sentence: no letters found" ); else if ( 0 == count ) printf( "all %d letters appear just once.\n", len-1 ); else if ( nInvalid > 0 ) printf( "[ %d non-letter character(s) ignored ]\n", nInvalid ); // reset lettcounts memset( lettcount, 0, MAXLETTS * sizeof(int) ); } exit(0); exit_failure: system( "pause" ); // windows only exit(1); }
capoelo Δημοσ. 10 Αυγούστου 2012 Μέλος Δημοσ. 10 Αυγούστου 2012 > #include<stdio.h> #include<stdlib.h> int main(int argc,char *argv[]) { int i=0; char f[][3][80]={"add","substract",""}; int k=atoi(argv[2]); int j=atoi(argv[3]); if(f[i][0])printf("The sum is:%d\n",k+j); else if(f[i][1])printf("The result is:%d\n",j-k); system("Pause"); return 0; } Ποιο το λάθος μου εδώ;Μου βγάζει κανονικότατα το άθροισμα(ότι αριθμούς κι αν χρησιμοποιήσω)και εμφανίζει πρόβλημα στην αφαίρεση. Υ.Γ.Για να σας προλάβω,το πρόγραμμα δεν εκτελεί κανέναν απολύτως έλεγχο για το πιο είναι μεγαλύτερο και πιο μικρότερο επειδή απλά βαριόμουν να το γράψω,όχι επειδή δεν ξέρω ότι πρέπει να γίνει αυτός ο έλεγχος στη δεύτερη περίπτωση. > #include<stdio.h> #include<stdlib.h> #include<string.h> int main(int argc,char *argv[]) { int i=0; char f[][80]={"add","substract","multiply","divide",""}; int k=atoi(argv[2]); int j=atoi(argv[3]); if(!strcmp(f[0],argv[1]))printf("The sum is:%d\n",k+j); else if(!strcmp(f[1],argv[1])) { if(argv[2]>argv[3]) printf("The difference is:%d\n",k-j); else printf("The difference is:%d\n",j-k); } else if(!strcmp(f[2],argv[1])) printf("The result is:%d\n",k*j); else { if(argv[3]==0)printf("I can not divide,because the 2nd term is 0\n"); else printf("The result is:%d\n",k/j); } system("Pause"); return 0; } Αυτός είναι ο κώδικας μαζί με τις πράξεις πολ/μου και διαίρεσης.Το πρόβλημα τώρα είναι ότι στην αφαίρεση,παρά τον έλεγχο που έχω ενσωματώσει,αφαιρεί πάντα το argv[2] απο το argv[3] και ποτέ το ανάποδο και στη διαίρεση μου εμφανίζει μόνο το δεύτερο σκέλος του ελέγχου.
migf1 Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 ... Αυτός είναι ο κώδικας μαζί με τις πράξεις πολ/μου και διαίρεσης.Το πρόβλημα τώρα είναι ότι στην αφαίρεση,παρά τον έλεγχο που έχω ενσωματώσει,αφαιρεί πάντα το argv[2] απο το argv[3] και ποτέ το ανάποδο και στη διαίρεση μου εμφανίζει μόνο το δεύτερο σκέλος του ελέγχου. Σορρυ, αλλά προσωπικά έχω βαρεθεί να προσπαθώ να διαβάσω κώδικες "ορνιθοσκαλίσματα". Έχει μαλλιάσει η γλώσσα μας ρε παιδιά, είναι πια τόσο δύσκολο να γράφετε κώδικα που να μπορούν να τον σκανάρουν με 1 ανάγνωση κι άλλοι εκτός από εσάς τους ίδιους; Το μόνο που εντόπισα από την 1η ανάγνωση είναι πως δεν ελέγχεις για το αν υπάρχουν arguments στην command line πριν επιχειρήσεις να τα αναθέσεις με atoi στα k,j κλπ. Τα υπόλοιπα, σορρυ και πάλι αλλά δεν κάθομαι να βγάλω τα μάτια μου για να καταλάβω σε ποιο if αντιστοιχεί το κάθε else και ποιες γραμμές ανήκουν σε ποιο if και σε ποιο else. Αν είσαι τυχερός θα κάτσει να το κάνει κάποιο άλλο παιδι Ο παρακάτω κώδικας κάνει τις 4 βασικές αριθμητικές πράξεις (συν modulo) στα ακέραια command-line arguments του, απαιτώντας να είναι της μορφής: prog πράξη ακέραιος1 ακέραιος2... > #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <limits.h> #define MAXARGS 4 // max args we expect in the command line #define MAXOPS 3 // 1 operator and 2 operands // acceptable operators enum Operator { ERR = 0, ADD = '+', SUB = '-', MUL = 'x', DIV = '/', MOD = '%' }; #define VALID_OPERATOR(c) \ ( ADD == (c) || SUB == (c) || MUL == (c) || DIV == (c) || MOD == (c) ) /********************************************* * */ long long int usage( char *progname ) { printf( "usage: %s %c|%c|%c|%c|%c n1 n2\n", progname, ADD, SUB, MUL, DIV, MOD ); system( "pause" ); return LLONG_MIN; } /********************************************* * Parse the command line for 1 operator & 2 operands and store them in ops[]. * On error, set ops[0] to ERR and return false */ bool parse( char *argv[], int ops[] ) { int i = 0; // sanity checks if ( !argv || !ops || NULL == argv[1] || !VALID_OPERATOR( (int)argv[1][0] ) // first char of argv[1] ){ ops[0] = ERR; return false; } ops[0] = argv[1][0]; // get operator in ops[0] for (i=2; i < MAXARGS && NULL != argv[i]; i++) // get operands in ops[1] & [2] ops[i-1] = atoi( argv[i] ); // check if we got the expected number of args if ( i != MAXARGS ) { ops[0] = ERR; return false; } return true; } /********************************************** * Perform operation ops[0] on operands ops[1] and ops[2]. * Return the result, or LLONG_MIN on error. */ long long int calc( int ops[] ) { if ( !ops || ERR == ops[0] ) return LLONG_MIN; switch ( ops[0] ) { case ADD: return ops[1] + ops[2]; case SUB: return ops[1] - ops[2]; case MUL: return ops[1] * ops[2]; case DIV: if ( 0 == ops[2] ) { puts( "*** attempt to divide by 0 ***" ); return LLONG_MIN; } return ops[1] / ops[2]; case MOD: if ( 0 == ops[2] ) { puts( "*** attempt to divide by 0 ***" ); return LLONG_MIN; } return ops[1] % ops[2]; } return LLONG_MIN; } /**********************************************/ int main( int argc, char *argv[] ) { int ops[ MAXOPS ] = {0}; long long int res = LLONG_MIN; if ( !parse(argv, ops) // parsing failed || LLONG_MIN == (res = calc(ops)) // calc failed ) return usage( argv[0] ); printf( "%lld\n", res ); system( "pause" ); exit(0); }
Star_Light Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 migf1 βλέπω παλι βρηκες πολυ σοβαρα λαθη στο προγραμμα μου. Τι να σου πω ρε φιλε.... σου ειχα πει και παλιοτερα οτι ο καθενας εχει το στυλ του. Δεν μπορουμε να γραφουμε ιδιους κωδικες... Η χρηση των globals ειπα πως ειναι προσωπικη - συνειδητη επιλογη εξαρχης. Ειναι δικο μου θεμα αν θα τις χρησιμοποιησω ή οχι. Οσο για τον κωδικα που παραθετεις στην συνεχεια δεν θα κατσω να τον διαβασω γιατι δεν παιζεις με συναρτησεις και ειναι δυσαναγνωστος.... αναιρεις την ουσια του δομημενου προγραμματισμου ετσι που ειναι οι συναρτησεις???? ολα χυμα μεσα στην main ? ΚΟυραστηκε το ματι μου!!!!!!!! Μετα μου λες για τις στοιχισεις φιλε Παρολαυτα θα σε ακούσω και θα τις κανω τις βελτιώσεις.... > /************************************************************************ * Το πρόγραμμα υπολογιζει τις εμφανίσεις(πανω απο μια φορα) των γραμμάτων * σε μια πρόταση. Αν ένα γραμμα εμφανίζεται παραπανω απο μια φορα τυπώνονται * ο αριθμος εμφάνισης καθως και το γράμμα. Σε αντιθετη περίπτωση τυπώνεται * ενα μήνυμα οτι δεν υπάρχουν παραπανω εμφανισεις . Το πρόγραμμα δεν επεξεργάζεται * κενές ή άκυρες προτάσεις . */ #include <stdio.h> #include <ctype.h> #include <stdbool.h> #include <stdlib.h> #define alph_len 26 void read(char [] , char []); void check( char [] , char []); void clear( char [] , char []); int main(void) { char check_letters[alph_len]={0} , letters[alph_len]= {0}; for(; { puts(" Δώσε πρόταση : "); read(check_letters , letters); check(check_letters , letters); clear(check_letters , letters); } return 0; } //---Διάβασμα εισόδου απο τον χρήστη ----------------------------------- void read(char check_letters[alph_len] , char letters[alph_len]) { char ch; bool sentimel = true; while((ch=tolower(getchar()))!='\n') { if( isalpha(ch) ) { letters[ch-'a']= ch; check_letters[ch -'a']++; sentimel = false; } if( !isalpha(ch) && sentimel ) { puts(" Δεν υπάρχει έγκυρη προταση. "); exit(EXIT_SUCCESS); } } // Εκτός loop if( sentimel ) { puts(" Kενή προταση. "); exit(EXIT_SUCCESS); } return; } //-- Τσεκάρισμα για παραπάνω απο μια εμφανίσεις των γραμμάτων----------- void check( char check_letters[alph_len] , char letters[alph_len]) { bool count = false; int i; for(i=0; i<alph_len; i++) { if( check_letters[i] > 1 ) { printf("\nEμφάνιση γράμματος %c : %d φορές\n" , letters[i] , check_letters[i] ); count = true ; } } if( !count ) printf("\n Καμια εμφάνιση πανω απο μια φορα."); return; } //--- Καθαρισμός της μνήμης--------------------------------------------- void clear( char check_letters[alph_len] , char letters[alph_len] ) { int i=0; while (i < alph_len) { check_letters[i] = 0; letters[i] = 0; ++i; } return; }
migf1 Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 migf1 βλέπω παλι βρηκες πολυ σοβαρα λαθη στο προγραμμα μου. Τι να σου πω ρε φιλε.... σου ειχα πει και παλιοτερα οτι ο καθενας εχει το στυλ του. Δεν μπορουμε να γραφουμε ιδιους κωδικες... Η χρηση των globals ειπα πως ειναι προσωπικη - συνειδητη επιλογη εξαρχης. Ειναι δικο μου θεμα αν θα τις χρησιμοποιησω ή οχι. Οσο για τον κωδικα που παραθετεις στην συνεχεια δεν θα κατσω να τον διαβασω γιατι δεν παιζεις με συναρτησεις και ειναι δυσαναγνωστος.... αναιρεις την ουσια του δομημενου προγραμματισμου ετσι που ειναι οι συναρτησεις???? ολα χυμα μεσα στην main ? ΚΟυραστηκε το ματι μου!!!!!!!! Μετα μου λες για τις στοιχισεις φιλε Παρολαυτα θα σε ακούσω και θα τις κανω τις βελτιώσεις.... Δεν βρήκα σοβαρά λάθη στον κώδικά σου, βρήκα bad-practices... δεν είναι το ίδιο πράγμα. Πέρα όμως από αυτό, πρέπει να μας ξεκαθαρίσεις σε τι στοχεύεις όταν ποστάρεις κώδικες; Στοχεύεις στο να δείξεις στο φόρουμ μια λύση ενός προβλήματος, στοχεύεις στο να αποσπάσεις χρήσιμες για σένα και για άλλους παρατηρήσεις από πιο έμπειρους, στοχεύεις και στα 2 αυτά, στοχεύεις σε κάτι άλλο; Θεωρείς π.χ. τον εαυτό σου τόσο φτασμένο προγραμματιστή που έχει το ειδικό βάρος να βαφτίζει ως προσωπικο στυλ bad-practices παγιωμένα επί δεκαετίας από top κεφάλια της διαδρομής του προγραμματισμού από τη γέννησή της μέχρι σήμερα; Σε κάθε περίπτωση, τα bad-practices είναι bad-practices και είναι από σπάνιο έως αδύνατον να μείνουν ασχολίαστα από έμπειρους προγραμματιστές όταν ποστάρονται σε ένα προγραμματιστικό φόρουμ. Με το να υιοθετήσεις good-programming practices δεν κάνεις καμία χάρη σε μένα. Στο εαυτό σου κάνεις, σε περίπτωση που χρειαστεί να γράψεις κώδικα για να πιάσεις κάποια δουλειά μελλοντικά. Εγώ τα σχολιάζω και θα συνεχίσω να τα σχολιάζω, διότι το φόρουμ το διαβάζει πολύς κόσμος. Τυγχάνει στη C να έχω μακρόχρονη εμπειρία οπότε είμαι παραπάνω από εξοικειωμένος όχι μόνο με πολλά χαρακτηριστικά της γλώσσας, αλλά και με παγιωμένες, κοινές πρακτικές, τις οποίες και μένα μου τις έμαθαν (πολλές εκ των οποίων μάλιστα επιδίωξα μόνος μου να τις μάθω από πιο έμπειρους, ζητώντας μέχρι και απιατώντας την κριτική τους στους κώδικές μου... και ακόμα το κάνω όταν βρίσκω την ευκαιρία). Είμαι επίσης ανοιχτός σε οποιαδήποτε κριτική για όλους τους κώδικες που ποστάρω. Προφανώς δεν είσαι υπορεωμένος να διαβάσεις κανέναν από τους κώδικες που ποστάρω, όπως δεν είναι κανένας, όπως επίσης προφανώς δεν είμαι ούτε εγώ υποχρεωμένος να αποδεχτώ ως "προσωπικό στυλ" παγιωμένα και τεκμηριωμένα bad-practices. Επίσης δεν είμαι υποχρεωμένος να αφήνω ασχολιάστους κώδικες που προωθούν αυτά τα bad-practices. Btw... http://en.wikibooks.org/wiki/C_Programming/Preprocessor By convention, values defined using #define are named in uppercase. Although doing so is not a requirement, it is considered very bad practice to do otherwise. This allows the values to be easily identified when reading the source code. απλά ενα πολύ μικρό δείγμα για το ποιος από τους 2 κώδικες θωρείται να έχει good readability και ποιος όχι
imitheos Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 Λόγω κακής στοίχισης δεν έχω την διάθεση να κοιτάξω προσεκτικά τον κώδικα, αλλά σε 1η ανάγνωση βλέπω διάφορα bad-practices, με 1ο και καλύτερο την χρήση καθολικών μεταβλητών (προσωπικά το έχω απορία γιατί επιμένεις στα globals παρόλο που όλοι σου έχουμε πει να τα αποφεύγεις). Σορρυ, αλλά προσωπικά έχω βαρεθεί να προσπαθώ να διαβάσω κώδικες "ορνιθοσκαλίσματα". Έχει μαλλιάσει η γλώσσα μας ρε παιδιά, είναι πια τόσο δύσκολο να γράφετε κώδικα που να μπορούν να τον σκανάρουν με 1 ανάγνωση κι άλλοι εκτός από εσάς τους ίδιους; Το μόνο που εντόπισα από την 1η ανάγνωση είναι πως δεν ελέγχεις για το αν υπάρχουν arguments στην command line πριν επιχειρήσεις να τα αναθέσεις με atoi στα k,j κλπ. Τα υπόλοιπα, σορρυ και πάλι αλλά δεν κάθομαι να βγάλω τα μάτια μου για να καταλάβω σε ποιο if αντιστοιχεί το κάθε else και ποιες γραμμές ανήκουν σε ποιο if και σε ποιο else. Αν είσαι τυχερός θα κάτσει να το κάνει κάποιο άλλο παιδι Και εγώ πήγα να γκαρίξω για την εμφάνιση του κώδικα αλλά βλέποντας τι έκανε το code-tag στον δικό μου, αμφιβάλλω αν φταίνε τα παιδιά. Η χρηση των globals ειπα πως ειναι προσωπικη - συνειδητη επιλογη εξαρχης. Ειναι δικο μου θεμα αν θα τις χρησιμοποιησω ή οχι. Οσο για τον κωδικα που παραθετεις στην συνεχεια δεν θα κατσω να τον διαβασω γιατι δεν παιζεις με συναρτησεις και ειναι δυσαναγνωστος.... αναιρεις την ουσια του δομημενου προγραμματισμου ετσι που ειναι οι συναρτησεις???? ολα χυμα μεσα στην main ? ΚΟυραστηκε το ματι μου!!!!!!!! Μετα μου λες για τις στοιχισεις φιλε Φυσικά είναι δικό σου θέμα αν θα χρησιμοποιήσεις globals ή όχι. Νομίζεις θα κοπεί η όρεξη του migf1 αν συνεχίσεις να χρησιμοποιείς globals ? Ο migf1 σου έδωσε μια συμβουλή για το τι θεωρεί αυτός (και πολύς άλλος κόσμος) σωστό. Από εκεί και πέρα είναι δικαίωμά σου να μην την ακολουθήσεις. Γενικά όμως είσαι εριστικός. Διέκοψες την ερώτηση του Re4cTiV3 χωρίς να έχεις δική σου ερώτηση και απλά πέταξες ένα κώδικα χωρίς κανένα σχόλιο για αυτόν (το πρωί στο μήνυμά σου υπήρχε μόνο το κομμάτι πριν το ideone paste δηλαδή ένας σκέτος κώδικας). Παραβλέπω αυτό το γεγονός και θα πω μόνο ότι αφού δεν ήθελες κριτική γιατί πόσταρες τον κώδικα ?
Star_Light Δημοσ. 10 Αυγούστου 2012 Δημοσ. 10 Αυγούστου 2012 Κοιτα εγω πιστευω οτι ο κωδικας που ανεβασα ειναι μια πολυ καλη προσπαθεια αλλα εσυ θες να την υποβαθμισεις επειδη δεν βαλαμε κεφαλαια στα ονοματα των μακροεντολων. To ειπες και μονος σου οτι δεν εχει σοβαρα λαθη αλλωστε. Ενταξει ο καθενας εχει τους λογους του κ τις συμπαθειες του . Θα διαβασω αυτο που δινεις με την wikipedia. Τους κωδικες τους ανεβαζω προφανως και για να σχολιαζονται . Αν ηταν δεν θα τους ανεβαζα καν. Για τον κωδικα που ανεβασες σου ειπα ποια ειναι η κριτικη μου.... οχι ολα μεσα στην main(). 1
Προτεινόμενες αναρτήσεις