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

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

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

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

Δημοσίευσηαπό migf1 » 13 Αύγ 2011, 06:38

stamatiou έγραψε:Εγώ αυτό που δεν καταλαβαίνω στον κώδικα είναι ότι:
1. Στην arrisfull arrisempty ελέγχει εάν στην πρώτη το περιεχόμενο είναι 0 αλλά αν είναι 0 ο πρώτος χαρακτήρας αν είναι 0 δεν σημαίνει ότι είναι άδειος ο πίνακας και το ίδιο για την arrisfull.
2. Στη arrisempty ελέγχεις το χαρακτήρα πριν το lenght, στο lenght συμπεριλαμβάνεται το '\0' και αν όχι γιατί ελέγχεις το len-1;

Έχεις δίκιο που μπερδεύτηκες, γιατί το πρόγραμμα ήρθε αμέσως μετά τα strings. Βασικά εδώ δεν έχουμε string αλλά έναν απλό πίνακα από int (δηλαδή όχι από char).

Η λογική του είναι πως όταν ο πίνακάς μας είναι κενός όλα του τα στοιχεία περιέχουν μια τιμή που έχουμε διαλέξει για αυτή τη δουλειά, την οποία την πρωτο-ορίζω στην σταθερά EMPTY_ELEMVAL, με το #define στην αρχή του προγράμματος. Αυτή την τιμή τη βάζουμε ίση με κάτι που δεν μπορεί υπο κανονικές συνθήκες να θεωρηθεί έγκυρη τιμή για τα στοιχεία του πίνακά μας.

Ίσως το 0 να μην είναι καλή επιλογή. Αν θεωρήσουμε ότι ο πίνακάς μας φτιάχνεται για να δέχεται αποκλειστικά θετικές τιμές ή 0, τότε μπορούμε να αλλάξουμε την EMPTY_ELEMVAL π.χ. σε -1. Οπότε όποιο στοιχείο του πίνακα βλέπουμε πως έχει αυτή τη τιμή, το θεωρούμε κενό.

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

Επιστρέφοντας λίγο πάλι στη λογική του προγράμματος, θεωρούμε πως ο πίνακάς μας ξεκινάει κενός, π.χ. με τιμές {0, 0, 0, 0, 0, 0, 0, 0, 0, 0} και όταν δεν είναι κενός οι τιμές που περιέχει είναι συνεχόμενες ξεκινώντας από την αρχή του. Δηλαδή, αν προσθέσουμε για παράδειγμα τις τιμές 99 και 1000 θα πρέπει να μπουν στις 2 πρώτες θέσεις του και οι υπόλοιπες θα παραμείνουν κενές (δηλαδή με τιμή EMPTY_ELEMVAL).

Οπότε με αυτές τις διευκρινήσεις, νομίζω γίνεται πιο εμφανής ο ρόλος των ARR_ISFULL() και ARR_ISEMPTY(). Αν όχι, εδώ είμαστε :)

Για τη 2η ερώτησή τώρα, όταν π.χ. το συνολικό μήκος του πίνακα είναι 10 στοιχεία, το τελευταίο του στοιχείο είναι το 9 (και όχι το 10) γιατί η αρίθμηση των θέσεων ξεκινάει από το 0.

Btw, τα έγραψες ανάποδα, το ARR_ISEMPTY() ελέγχει την 1η θέση αν είναι EMPTY_ELEMVAL, ενώ το ARR_ISFULL() ελέγχει την τελευταία θέση αν είναι EMPTY_ELEMVAL ;)

Όταν κατανοήσετε πως ακριβώς δουλεύουν οι συναρτήσεις, μπορείτε να φτιάξετε άλλη μια που θα μηδενίζει μονομιάς όλα τα στοιχεία του πίνακα, θα τους βάζει δηλαδή την τιμή EMPTY_ELEMVAL. Τώρα που η EMPTY_ELEMVAL ισούται με 0 ο μηδενισμός του πίνακα μπορεί να γινει πολύ γρήγορα με τη συνάρτηση memset (που την έχω σε σχόλια) αλλά η memset δεν μπορεί να βάλει αρνητικές τιμές. Οπότε αν π.χ. το EMPTY_ELEMVAL θέλετε να το αλλάξετε ας πούμε σε -1, θα χρειαστεί να φτιάξετε μια δικιά σας συνάρτηση, π.χ. void arr_reset(int arr, int maxelems);

Μπορείτε επίσης να προσαρμόσετε τον κώδικα ώστε το πρόγραμμα να κρατάει και μια ακόμα μεταβλητή η οποία θα αντιστοιχεί στο τρέχον μήκος του πίνακα.

Για παράδειγμα, αν ο πίνακας έχει την μορφή: {90, 20, 30, 0, 0, 0, 0, 0, 0, 0} τότε το τρέχον μήκος του είναι 3, διότι έχει τιμές στα 3 πρώτα στοιχεία του.

Προφανώς αυτή η μεταβλητή θα πρέπει να ενημερώνεται και από τις συναρτήσεις που προσθαφαιρούν στοιχεία στον πίνακα, και από τη συνάρτηση που θα τον κάνει reset.

Σε αυτές τις περιπτώσεις είναι πάντα καλύτερα να χρησιμοποιηθεί κάποια δομή που θα περιέχει τον πίνακα και μια μεταβλητή για το τρέχον μήκος του, ώστε να μην τα περνάτε ξεχωριστά σε κάθε συνάρτηση.

Για παράδειγμα:

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

#define MAX_ELEMENTS 10
#define EMPTY_ELEMVAL 0

#define ARR_ISEMPTY(arr) ( (arr)[0] == EMPTY_ELEMVAL )
#define ARR_ISFULL(arr, maxlen) ( (arr)[(maxlen)-1] != EMPTY_ELEMVAL )

typedef struct {
int len;
int arr[ MAX_ELEMENTS] ;
} List;

// -----------------------------------------------------------------------------
void list_reset( List *list, int maxelems)
{
register int i;

for (i=0; i<maxelems; i++)
list->arr[i] = EMPTY_ELEMVAL;
list->len = 0;

return;
}
// -------------------------------------------------------------------------------------
int list_append( List *list, int maxelems, int val)
{
if ( ARR_ISFULL( list->arr, maxelems ) )
return -1;

if ( ARR_ISEMPTY( list->arr ) ) {
list->arr[0] = val;
list->len = 1;
return 0;
}

register int i;
for (i=maxelems-1; list->arr[i] == EMPTY_ELEMVAL; i--)
;
list->arr[++i] = val;
(list->len)++;

return i;
}
// -------------------------------------------------------------------------------------
void list_print( List list, int maxelems )
{
register int i;

for (i=0; i < maxelems; i++)
printf("%d ", list.arr[i] );
putchar('\n');

return;
}
// -----------------------------------------------------------------------------
int main( void )
{
List mylist;

list_reset( &mylist, MAX_ELEMENTS);
list_append( &mylist, MAX_ELEMENTS, 999);
list_print( mylist, MAX_ELEMENTS );

return 0;
}

Βασικά αν κρατάμε ενημερωμένο το list->len, τότε η list_append() γίνεται πανεύκολη, διότι απλά τσεκάρουμε να μην είναι κενός ο πίνακας και κατόπιν γράφουμε: list->arr[ list->len ] = val; (list->len)++;

Αλλά πριν πάμε σε αυτά, βεβαιωθείτε πως καταλαβαίνετε πως λειτουργούν οι συναρτήσεις στο αρχικό πρόγραμμα (βάλτε σχόλια δίπλα σε ΚΑΘΕ γραμμή).

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

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

Δημοσίευσηαπό Star_Light » 13 Αύγ 2011, 11:01

Καλημεεεερα! Λοιπον ειναι απλα ενας κωδικας ο οποιος αρχικα επρεπε να υπολογισει το περιττο αθροισμα των στοιχειων που εδινε ενας χρηστης και αποθηκευονται σε εναν πινακα. Μετα σκεφτηκα να τον επεκτεινω και προσθεσα και αλλη μια συναρτηση μεσα η οποια δινει το αρτιο αθροισμα και τελος προσθεσα και μια switch η οποια αναλογα με το τι θελει ο χρηστης (περιττο/αρτιο) αθροισμα καλει και την αντιστοιχη συναρτηση.... (μενει και μια τριτη επιλογη να επιστρεφει το αθροισμα κανονικα χωρις αρτια ή περιττα στοιχεια αλλα δεν το εχω προσθεσει ακομη τωρα μολις το σκεφτηκα για να δειχνει πιο ολοκληρωμενο)

http://codetidy.com/1023/

οποιος θελει να παρει ματι τον κωδικα :lol:

Π.Σ φυσικα κανω το λαθος παλι να παιζω με global.... και τελος η μονη ιδιαιτεροτητα αυτου του κωδικα ειναι οτι περναει σαν ορισμα μεσα σε συναρτησεις εναν πινακα.
Γνώσεις ⇛ 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 » 13 Αύγ 2011, 11:04

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

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

Δημοσίευσηαπό Star_Light » 13 Αύγ 2011, 11:13

migf1 έγραψε:Καλημέρα, για να μη δω τον κώδικα, η εκφώνηση δεν καθορίζει πότε θα σταματάει η είσοδος. Από default οι πίνακες έχουν πεπερασμένο μήκος, άρα να υποθέσω πως θα διαβάζει από την κύρια είσοδο μέχρι να γεμίσει ο πίνακας και θα αγνοεί τυχόν έξτρα αριθμούς;


Οπα ναι παραλειψη μου..... η εκφωνηση συγκεκριμενοποιει την εισοδο σε 10 θεσεις... μεχρι 10 αριθμους μπορει να δωσει ο χρηστης ;)
να σε προετοιμασω για τα αγγλικα μου πριν τον δεις οτι ειναι μετριοτατα!!! :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++

Δημοσίευσηαπό migf1 » 13 Αύγ 2011, 11:15

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

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

Δημοσίευσηαπό Star_Light » 13 Αύγ 2011, 11:51

NAI εννοειται , οποτε εχεις χρονο ;)
Γνώσεις ⇛ 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 » 13 Αύγ 2011, 11:55

Έτοιμη :)

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

#include <stdio.h>
#include <stdlib.h>
// -----------------------------------------------------------------------------------
int main( void )
{
int arr[10] = {0};
char inbuf[256] = "";
register int i=0, sum = 0, evsum = 0, odsum = 0;;

do {
printf("Enter #%2d: ", i+1);
fgets(inbuf, 256, stdin);
arr[i] = atoi(inbuf);
sum += arr[i];
if ( arr[i]%2 )
odsum += arr[i];
else
evsum += arr[i];
} while ( ++i < 10 );

printf("\n\nTotal sum:\t%d\nEven sum:\t%d\nOdd sum:\t%d\n", sum, evsum, odsum);

return 0;
}

Κάτσε να της βάλω κι επιλογή του χρήστη για το ποια αθροίσματα θέλει να υπολογίζονται.

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

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

Δημοσίευσηαπό Star_Light » 13 Αύγ 2011, 12:11

ναι :P βασικα αρκετα πιο συμπαγης και περιεκτικος κωδικας!!! Τον δικο μου πως τον ειδες?
Γνώσεις ⇛ 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 » 13 Αύγ 2011, 12:12

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

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

Δημοσίευσηαπό migf1 » 13 Αύγ 2011, 12:25

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

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

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