stamatiou έγραψε:@migf1 Αυτό τελικά είναι σωστό; http://forum.ubuntu-gr.org/viewtopic.php?p=207768#p207768
Δυστυχώς όχι.
Το κύριο πρόβλημά του είναι το λανθασμένο μέγεθος του πίνακα usedvals, το οποίο πρέπει να είναι maxvals+1, διότι στους παραγόμενους τυχαίους θέλουμε να περιλαμβάνεται και ο maxval, άρα ο πίνακας πρέπει να έχει θέσεις από 0 έως maxval (άρα συνολικό πλήθος: maxval+1).
Κατόπιν, στο do-while που ελέγχεις για τη μοναδικότητα του random, ελέγχεις για != TRUE (δηλαδή FALSE) ενώ πρέπει να ελέγχεις για == TRUE. Δηλαδή σε αυτό το loop θέλεις συνεχή παραγωγή τυχαίων, όσο οι παραγόμενοι τυχαίοι είναι μαρκαρισμένοι ως χρησιμοποιημένοι (TRUE) στον usedvals.
Έπειτα, εκείνο το if μέσα στο for και είναι περιττό και επαναλαμβάνεται χωρίς λόγο σε κάθε επανάληψη του for. Ότι έλεγχο ή διόρθωση θέλεις να κάνεις για το maxval πρέπει να τα κάνεις πριν ξεκινήσεις το βασικό σου for-loop.Παρεμπιπτόντως, επειδή πρέπει να ελεγχθεί η τιμή του maxval για να καθορίσει το μέγεθος του πίνακα usedvals, τον ορίζουμε ως δέικτη και όταν ελέγξουμε/διορθώσουμε την τιμή της maxval τον κάνουμε calloc() (και free() στο τέλος).
Ακόμα, δεν ενημερώνεις το τελικό table->buflen πριν τερματίσεις την συνάρτηση.
Και τέλος, υπάρχει μια περίπτωση που η συνάρτησή σου δεν δείχνει να λαμβάνει υπόψη της: όταν το buffer είναι μισογεμάτο πριν περαστεί στη συνάρτηση. Η λογική της συνάρτησής σου είναι να σβήνει τυχόν υπάρχουσες τιμές στα στοιχεία του buffer και να τις αντικαθιστά με τυχαίες.
Παραθέτω τον κώδικα της συνάρτησης που αντιμετωπίζει όλα τα παραπάνω...
- Κώδικας: Επιλογή όλων
/* --------------------------------------------------------------------------------
* Γεμίζει το buffer της δομής table με μοναδικές ψευδοτυχαίες τιμές από 0 έως maxval,
* ξεκινώντας από το πρώτο κενό στοιχείο του buffer.
* Σε περίπτωση επιτυχίας ενημερώνει το τρέχον μήκος του buffer στη δομή κι επιστρέφει
* TRUE. FALSE επιστρέφει όταν το buffer είναι ήδη γεμάτο ή δεν υπάρχει καν ή όταν το
* όρισμα table περαστεί στη συνάρτηση με τιμή NULL ή όταν δεν υπάρχει επαρκής
* ελέυθερη μνήμη για τη δημιουργία του προσωρινού πίνακα usedvals (τον χρειάζεται για
* να ελέγχει τη μοναδικότητα των παραγόμενων ψευδοτυχαίων τιμών).
* ΣΗΜΑΝΤΙΚΟ:
* Αν το όρισμα maxval είναι μικρότερο από το μέγιστο μήκος του buffer, τότε
* μετατρέπεται αυτόματα να είναι ίσο (αυτό είναι απαραίτητο για να μην μπαίνει
* σε ατέρμονο βρόγχο η παραγωγή των τυχαίων... π.χ. αν το μέγιστο μήκος του
* buffer είναι 12 στοιχεία και το maxval δοθεί με τιμή 10, μόλις γεμίσουν τα
* πρώτα 10 στοιχεία δεν υπάρχουν άλλοι μοναδικοί τυχαίοι για τα 2 στοιχεία
* που υπολείπονται).
* --------------------------------------------------------------------------------
*/
Bool table_fill_unique_randomly( Table *table, int maxval )
{
Bool *usedvals = NULL; /* για έλεγχο μοναδικότητας */
int tempval = 0; /* προσωρινός ψευδοτυχαίος */
register int i = 0; /* μετρητής για το buffer */
if ( !table ) /* έλεγχος ασφαλείας */
return FALSE; /* ... πρόωρη έξοδος αποτυχίας */
if ( !table->buffer ) /* το buffer δεν υπάρχει */
return FALSE; /* ... πρόωρη έξοδος αποτυχίας */
if ( table->buflen == table->bufmaxlen ) /* το buffer είναι γεμάτο */
return FALSE; /* ... πρόωρη έξοδος αποτυχίας */
if (maxval < table->bufmaxlen - table->buflen ) /* είναι το maxval πολύ μικρό? */
maxval = table->bufmaxlen - table->buflen; /* διόρθωσέ το */
usedvals = calloc( maxval+1, sizeof(int) ); /* δημιουργία maxval+1 θέσεων */
if ( !usedvals ) /* αποτυχία δημιοργίας */
return FALSE; /* ... πρόωρη έξοδος */
for (i=table->buflen; i < table->bufmaxlen; i++)/* γέμισμα buffer με τυχαίους */
{ /* ... */
do { /* ... συνεχής */
tempval = rand() % (maxval + 1);/* ... παραγωγή τυχαίου */
} while ( usedvals[ tempval ] == TRUE );/* ... μέχρι να είναι μοναδικός*/
/* ... */
table->buffer[i] = tempval; /* αποδοχή ττυχαίου στο buffer */
usedvals[ tempval ] = TRUE; /* χαρτγράφησή του ως used */
}
table->buflen = table->bufmaxlen; /* ενημέρωση τρέχοντος μήκους */
if ( usedvals ) { /* έλεγχος ασφαλείας */
free( usedvals ); /* ... αποδέσμευση μήμης */
usedvals = NULL; /* ... καλού-κακού */
}
return TRUE; /* επιστροφή επιτυχίας */
}
ΥΓ. Τις συναρτήσεις που φτιάχνεις γιατί δεν τις δοκιμάζεις πρώτα για να δεις αν δουλεύουν σωστά με διάφορα test-cases;



