Προς το περιεχόμενο

Ερωτήσεις για C


capoelo

Προτεινόμενες αναρτήσεις

Απλά από συνήθεια, πάνε τώρα πάνω από 15 χρόνια που σε κάποιο βιβλίο για Windows προγραμματισμό είχα πετύχει ένα μικρό πίνακα ο οποίος χρησιμοποιούσε αυτά τα prefix (πιθανότητα και άλλα που δεν τα θυμάμαι πια ή ...εισήγαγα και κάποια δικά μου που προέκυψαν στην πορεία :-D), κοιτάζοντας από περιέργεια εδώ (μιας και το κουβεντιάζουμε)  βλέπω ότι κάποια πράγματα που θυμάμαι από τότε ακόμα χρησιμοποιούνται (..με την διαφορά ότι εγώ έχω συνηθίσει πχ. το "b = bool" και το "n = integer δίχως διάκριση count ή index" [η Wikipedia λαμβάνει υπόψη της και αυτή την εκδοχή, και την άλλη όπου "f = bool" και "i = integer/index"] - αλλά σαφέστατα δεν πρόκειται για θέσφατα τα οποία χρησιμοποιώ παντού, κάθε άλλο σέβομαι πάντα την σήμανση των άλλων project ή ακόμα και την μη σήμανση αν έτσι έχει αποφασιστεί.

 

Η μία εκδοχή (η κακή, με τα "b" και "n") είναι η λεγόμενη Systems Hungarian, ενώ η άλλη (η καλή) Apps Hungarian. Υπάρχει εκτενής βιβλιογραφία αν θέλεις να ψάξεις με λίγο Google, αλλά long story short:

 

Η Systems δεν προσφέρει τίποτα καθώς αν πας π.χ. να προσθέσεις δύο μεταβλητές nStrLength και nOtherLength απλά έχεις γράψει 2 n παραπάνω χωρίς λόγο. Η apps όμως σε εμποδίζει να κάνεις λογικά λάθη, γιατί αν πας αντίστοιχα να προσθέσεις cchStrLength (count of characters, όχι με την έννοια του data type αλλά με τη γενική) με cbOtherLength (count of bytes) τότε είναι άμεσα εμφανές ότι προσθέτεις ανόμοια πράγματα => bug.

 

Αυτο που μου δινεις εδω δεν τρεχει ..... Αν βαλω την συναρτηση ετσι οπως ειναι στο προγραμμα θα μου βγαζει λαθος αποτελεσματα . Δοκιμασε το και εσυ να δεις. Παρολαυτα το 1ο loop που εχω εγω ειναι περιττο η δικια σου εκδοση ειναι πιο συμπτυγμενη. Ωστοσο δεν θα περασω const char * γιατι το string το περιμενω απο τον χρηστη και δεν ειναι literal. Επισης αυτο με το s[0] και s[N] που λες δεν το καταλαβαινω.... που εχω δει οτι ειναι ισα? Επισης γιατι αν η λεξη ειναι παλινδρομη να επιστρεψω 0 και οχι 1 που σαν τιμη μεσα στην if θα δουλεψει απευθειας και δεν θα χρειαστει να χρησιμοποιήσω ! μπροστα απο την κληση της συνάρτησης ωστε !0 = 1 . ΓΙα το is_palindrome δεν εχεις αδικο συνηθως τετοια ονομασια περιμενει διτιμη εκτιμηση bool κτλπ .

 

Αν θέλεις πες μου τι είναι αυτό που το εμποδίζει να τρέξει, εγώ το βλέπω μια χαρά. const char* μπορείς πάντα να περάσεις (ο compiler αυτόματα μετατρέπει char* σε const char* όταν είναι απαραίτητο) και "πρέπει" να περάσεις εφόσον δεν πρόκειται να αλλάξεις το string argument.

 

Με το s[0] και s[N] εννοώ πως οι 2 pointers κάποια στιγμή θα διασταυρωθούν. Εκείνη τη στιγμή έχεις ήδη συγκρίνει τους πρώτους μισούς χαρακτήρες με τους δεύτερους μισούς, το να συνεχίσεις μέχρι το τέλος του string και να συγκρίνεις πάλι τους δεύτερους μισούς με τους πρώτους είναι τζάμπα δουλειά. Αν ρίξεις μια ματιά και ο Directx παραπάνω με το for δε συνεχίζει το loop αφότου διασταυρωθούν οι pointers.

 

Η περιγραφή σου για την επιστρεφόμενη τιμή δεν συμφωνεί με τον κώδικα που έδωσα (τα λες ανάποδα).

 

Τέλος φυσικά και δεν πρέπει να αφήσεις το string χωρίς null terminator. Απλά η is_palindrome δε χρειάζεται να τον ακουμπήσει παρά μόνο μία φορά για να δει πού τελειώνει το string κατα τα γνωστά.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 1,6k
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Η μία εκδοχή (η κακή, με τα "b" και "n") είναι η λεγόμενη Systems Hungarian, ενώ η άλλη (η καλή) Apps Hungarian. Υπάρχει εκτενής βιβλιογραφία αν θέλεις να ψάξεις με λίγο Google, αλλά long story short[..]

Χμ.. το είδα, εγώ έχω συνηθίσει την System Hungarian πλέον, με βολεύει περισσότερο να θυμάμαι άμεσα το data type παρά την "λογική ερμηνεία" του τι εξυπηρετεί στον κώδικα, σίγουρα όμως κάποιος που έχει συνηθίσει διαφορετικά (App Hungarian) τα βλέπει αλλιώς (δεκτό - ότι βολεύει τον καθένα).

 

Ίσως σε κανένα νεότερο project δοκιμάσω και την δεύτερη μεθοδολογία πάντως, για να βγάλω σαφέστερα συμπεράσματα :-)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Χμ.. το είδα, εγώ έχω συνηθίσει την System Hungarian πλέον, με βολεύει περισσότερο να θυμάμαι άμεσα το data type παρά την "λογική ερμηνεία" του τι εξυπηρετεί στον κώδικα, σίγουρα όμως κάποιος που έχει συνηθίσει διαφορετικά (App Hungarian) τα βλέπει αλλιώς (δεκτό - ότι βολεύει τον καθένα).

 

Ίσως σε κανένα νεότερο project δοκιμάσω και την δεύτερη μεθοδολογία πάντως, για να βγάλω σαφέστερα συμπεράσματα :-)

Ένα παράδειγμα που δινόταν συχνά ήταν το excel από ό,τι θυμάμαι το οποίο είχε πάρα πολλές γραμμές κώδικα λόγω των πολλών λειτουργιών και γινόταν ένας ψιλοχαμός. Αν δεις δύο μεταβλητές imitsos, ikotsos ξέρεις μονάχα ότι έχουν ακέραιο τύπο οπότε δεν κερδίζεις και πολλά (ειδικά με ένα καλό IDE που αμέσως θα σου πετάξει την definition και θα δεις πολύ εύκολα ότι πχ είναι long int). Έτσι γίνονταν από λάθος διάφορες πράξεις με μεταβλητές που δεν έπρεπε. Ενώ όταν βλέπεις rowmitsos, colkotsos ξέρεις ότι η μία μεταβλητή έχει κάποια σχέση με γραμμές ενώ η άλλη έχει να κάνει με στήλες. Δεν είναι και τόσο σημαντική πληροφορία αλλά ξέρεις τουλάχιστον ότι οι μεταβλητές δεν έχουν σχέση μεταξύ τους οπότε αν δεις κάπου μια έκφραση rowmitsos + colkotsos αυτό έχει γίνει από λάθος. Έτσι η "καλή" hungarian βοήθησε να επιλυθούν πολλά λογικά bugs του excel που αλλιώς ήταν δύσκολο να βρεθούν μέσα στο haystack των άπειρων γραμμών κώδικα.

 

Φυσικά το αναφέρω ιστορικά/εγκυκλοπαιδικά και όχι για να σε αναγκάσω να αλλάξεις στυλ.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ένα παράδειγμα που δινόταν συχνά ήταν το excel από ό,τι θυμάμαι το οποίο είχε πάρα πολλές γραμμές κώδικα λόγω των πολλών λειτουργιών και γινόταν ένας ψιλοχαμός. Αν δεις δύο μεταβλητές imitsos, ikotsos ξέρεις μονάχα ότι έχουν ακέραιο τύπο οπότε δεν κερδίζεις και πολλά (ειδικά με ένα καλό IDE που αμέσως θα σου πετάξει την definition και θα δεις πολύ εύκολα ότι πχ είναι long int). Έτσι γίνονταν από λάθος διάφορες πράξεις με μεταβλητές που δεν έπρεπε. Ενώ όταν βλέπεις rowmitsos, colkotsos ξέρεις ότι η μία μεταβλητή έχει κάποια σχέση με γραμμές ενώ η άλλη έχει να κάνει με στήλες. Δεν είναι και τόσο σημαντική πληροφορία αλλά ξέρεις τουλάχιστον ότι οι μεταβλητές δεν έχουν σχέση μεταξύ τους οπότε αν δεις κάπου μια έκφραση rowmitsos + colkotsos αυτό έχει γίνει από λάθος. Έτσι η "καλή" hungarian βοήθησε να επιλυθούν πολλά λογικά bugs του excel που αλλιώς ήταν δύσκολο να βρεθούν μέσα στο haystack των άπειρων γραμμών κώδικα.

 

Φυσικά το αναφέρω ιστορικά/εγκυκλοπαιδικά και όχι για να σε αναγκάσω να αλλάξεις στυλ.

Ενδιαφέρον, πράγματι η MS εφάρμοσε πολλές καινοτομίες κατά την ανάπτυξη του EXCEL και γενικότερα των λογισμικών του Office στην προσπάθεια της να κρατήσει σε χαμηλό ποσοστό τα software bugs - ένα τμήμα από την εμπειρία της αυτή είχε καταγραφεί στο "Writing Solid Code" του Steve Maguire (κάποτε είχα την ευκαιρία να διαβάσω μερικά κεφάλαια αλλά όχι το συνολικό βιβλίο).
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Φυσικά το αναφέρω ιστορικά/εγκυκλοπαιδικά και όχι για να σε αναγκάσω να αλλάξεις στυλ.

 

Ως κάποιος που πολλές φορές μιλάει με απόλυτο τρόπο, να συμφωνήσω και να επαυξήσω λέγοντας πως δεν είμαστε programming style nazi εδώ.

 

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

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@defacer και @migf1 έχετε δικιο.

Ο αλγοριθμος :

 

- ΔΙΑΒΑΣΕ ΜΙΑ ΛΕΞΗ
- ΔΙΕΤΡΕΞΕ ΤΗΝ ΛΕΞΗ ΑΠΟ ΤΗΝ ΑΡΧΗ ΩΣ ΤΟ ΤΕΛΟΣ ΚΑΙ ΑΠΟ ΤΟ ΤΕΛΟΣ ΩΣ ΤΗΝ ΑΡΧΗ
- ΑΝ ΟΛΑ ΤΑ ΓΡΑΜΜΑΤΑ ΤΟΥ ΤΕΛΟΥΣ ΕΙΝΑΙ ΙΣΑ ΜΕ ΑΥΤΑ ΤΗΣ ΑΡΧΗΣ ΜΕΧΡΙ ΝΑ ΦΤΑΣΕΙΣ ΣΤΗΝ ΜΕΣΗ ΤΗΣ ΛΕΞΗΣ ΤΟΤΕ ΑΥΤΗ ΕΙΝΑΙ ΠΑΛΙΝΔΡΟΜΗ

 

ειναι πιο σωστος απο αυτον που εγραψα εγω στην αρχη. Thanks

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Καλησπερα

 

εχω μια εργασια στην C.

ο κωδικας μου ειναι αυτος:

 

 

#include <stdio.h>
FILE * cfptr;
char c[4][10]={{0}};
char choice;
void alternative();
void closeseat1();
void total();
int seats=0;  
int i,j;            
int counter_e,counter_f; 
void close_first_class();
void close_eco_class();
int main(){
    while(choice != 'Q' && seats < 40)
    {
        alternative();
        scanf("%c", &choice);
        if(choice == 'F'){
            close_first_class();
        } else if(choice == 'E'){
            close_eco_class();
        } else if(choice == 'Q'){
        printf("\nTelos tou programmatos");
        cfptr=fopen("theseis.dat","w+");
        fprintf(cfptr,"Exoun krathtei %d oikonomikes kai %d first class theseis\n",counter_e,counter_f);
        fclose(cfptr);
        total();
        }
    }
    return 0;
}
void alternative(){
        printf("parakalw pliktrologiste F gia prwth thesi \n");
        printf("parakalw pliktrologiste E gia oikonomiki thesi \n");
        printf("parakalw pliktrologiste Q gia eksodo apo to programma\n");
}
void total(){
        printf("Sthn prwti thesi exoun kraththei %d theseis\n", counter_e);
        printf("Sthn oikonomiki thesi exoun kraththei %d theseis \n", counter_f);
}
//sunarthsh gia klhsh first class theshs
void close_first_class(){
    for (i=0;i<5;i++){
        for(j=0;j<4;j++){
            if(c[i+1][j+1] == 0){
                c[i+1][j+1] = 1;
                printf("\nDesmeutike h first class thesh %d %d \n", i+1,j+1);
                counter_f += 1;
                seats++;
                break;
            }
        }
    }
}
//sunartsh gia klhsh economic class theshs
void close_eco_class(){
    for (i=5;i<9;i++){
        for(j=0;j<4;j++){
            if(c[i+1][j+1] == 0){
                c[i+1][j+1] = 1;
                printf("\nDesmeutike h oikonomiki thesh %d %d\n", i+1,j+1);
                counter_e += 1;
                seats++;
                break;              
            }
        }
    }
}

 

 

 

ειναι 40 θεσεις,10 σειρες,4 θεσεων η καθε μια.θελω οταν παταει ο χρηστης F να κλεινει μια first class θεση (οι 5 πρωτες σειρες) και οταν παταει Ε να κλεινεται μια οικονομικης κατηγοριας(οι υπολοιπες σειρες).

Το προβλημα με τον κωδικα τωρα οπως ειναι,οταν παταω Ε κλεινει μια θεση οικονομικη,αλλα ξεκιναει απο την σειρα 9! δηλαδη πχ μου εμφανιζει την πρωτη φορα οτι κλειστηκε η θεση 9 1,επειτα η 9 2 κτλπ...

επισης,οταν παταω F,μου τις κλεινει ολες μαζι..το αποτελεσμα με την πρωτη φορα που παταω F ειναι:

 

Desmeutike h first class thesh 1 1
Desmeutike h first class thesh 2 1
Desmeutike h first class thesh 3 1
Desmeutike h first class thesh 4 1
Desmeutike h first class thesh 5 1

 

 

μπορειτε να με βοηθισετε με αυτα τα λαθη?? ευχαριστω

Επεξ/σία από Maarks
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Κατ'αρχήν δες τον πίνακα c. τον ορίζεις σαν c[4][10] ενω τα i,j πάνε ανάποδα στα loops.

 

Δευτερον, στην first class (όπως και στην economy αλλα εκεί δεν θα σου δουλευει γιατι το i ξεκινάει απο 5 που είναι εκτός πινακα) κάνεις break μονο από το loop του j κι όχι κι από το i.

 

Επίσης γιατί ελέγψεις το c[i+1] και δεν ξεκινάς από το c. Οι πίνακες ξεκινάνε από το 0 στη C.

 

Δε σχολιάζω το γεγονός με τις global μεταβλητές αλλά αφού τις χρησιμοποιείς θα μπορούσες να γράψεις πολύ πιο απλό κώδικα.

 

Δοκίμασε λιγο αυτα για αρχή και βλέπεις...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

εκανα τις διορθωσεις που μου ειπες και τωρα λειτουργει μια χαρα οπως βλεπω!! ευχαριστω!

 

υγ:με τις global μεταβλητες πως θα μπορουσα δηλαδη να το γραψω πιο απλα που ειπες φιλε?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μάλλον ήταν λίγο βιαστικό το "πολυ πιο απλό κώδικα" :) Απλά όταν βλέπω global γυαλίζει το μάτι μου :P

(καλό είναι να αρχικοποιήσεις επίσης τις μεταβλητές counter_f = counter_e = 0 στην αρχή)

 

Τώρα για να αποφύγεις να διατρέχεις τον πίνακα κάθε φορά, θα μπορουσες να χρησιμοποιήσεις κάτι τέτοιο για τη νέα θέση

(αφου κάνεις έναν έλεγχο για counter_f <= 20 )

c[(counter_f-1)%4][(counter_f-1)/4] = 1;

και κάτι ανάλλογο για την economy...

 

edit:

Επίσης, καλό είναι να κάνεις έλεγχο όταν ανοίγεις το αρχείο:

if ( (cfptr=fopen("theseis.dat","w+")) == NULL ){
   fprintf(stderr,"Error on opening file...\n");
   exit(-1); // ή ό,τι άλλο θέλεις να κάνει το πρόγραμμα σε περίπτωση λάθους.
}
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

 

Μάλλον ήταν λίγο βιαστικό το "πολυ πιο απλό κώδικα" :) Απλά όταν βλέπω global γυαλίζει το μάτι μου :P

(καλό είναι να αρχικοποιήσεις επίσης τις μεταβλητές counter_f = counter_e = 0 στην αρχή)

 

Τώρα για να αποφύγεις να διατρέχεις τον πίνακα κάθε φορά, θα μπορουσες να χρησιμοποιήσεις κάτι τέτοιο για τη νέα θέση

(αφου κάνεις έναν έλεγχο για counter_f <= 20 )

c[(counter_f-1)%4][(counter_f-1)/4] = 1;

και κάτι ανάλλογο για την economy...

 

edit:

Επίσης, καλό είναι να κάνεις έλεγχο όταν ανοίγεις το αρχείο:

if ( (cfptr=fopen("theseis.dat","w+")) == NULL ){
   fprintf(stderr,"Error on opening file...\n");
   exit(-1); // ή ό,τι άλλο θέλεις να κάνει το πρόγραμμα σε περίπτωση λάθους.
}

μαλιστα,ευχαριστω!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@defacer και @migf1 έχετε δικιο.

Ο αλγοριθμος :

 

- ΔΙΑΒΑΣΕ ΜΙΑ ΛΕΞΗ

- ΔΙΕΤΡΕΞΕ ΤΗΝ ΛΕΞΗ ΑΠΟ ΤΗΝ ΑΡΧΗ ΩΣ ΤΟ ΤΕΛΟΣ ΚΑΙ ΑΠΟ ΤΟ ΤΕΛΟΣ ΩΣ ΤΗΝ ΑΡΧΗ

- ΑΝ ΟΛΑ ΤΑ ΓΡΑΜΜΑΤΑ ΤΟΥ ΤΕΛΟΥΣ ΕΙΝΑΙ ΙΣΑ ΜΕ ΑΥΤΑ ΤΗΣ ΑΡΧΗΣ ΜΕΧΡΙ ΝΑ ΦΤΑΣΕΙΣ ΣΤΗΝ ΜΕΣΗ ΤΗΣ ΛΕΞΗΣ ΤΟΤΕ ΑΥΤΗ ΕΙΝΑΙ ΠΑΛΙΝΔΡΟΜΗ

 

ειναι πιο σωστος απο αυτον που εγραψα εγω στην αρχη. Thanks

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

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το πολύ μέχρι τη μέση αλλά και από τις 2 μεριές = το πολύ 1 πλήρη φορά = από 1 μέχρι 2 φορές συνολικά. Η αρχική version τη διέτρεχε 3 φορές. Χωρίς creative accounting.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το πολύ μέχρι 1 1/2 φορές τη διατρέχουμε, για αυτό βάζουμε 2 δείκτες και τους μετακινούμε ταυτόχρονα.

 

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

 

 

Π.χ. με unique data: 0 1 2 3 4 5 6 7 8 9 10

 

δεν υπάρχει περίπτωση να διατρέξουμε την λίστα παραπάνω από μισή φορά για να εντοπίσουμε το οποιοδήποτε μέλος της. Το worst case είναι μισή φορά, όταν δεν υπάρχει μέσα στη λίστα αυτό που ψάχνουμε, όταν δηλαδή συναντηθούν οι 2 δείκτες στο μέσο των data.

 

ΥΓ. "Διατρέχουμε" = # of loop-iterations.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επισκέπτης
Αυτό το θέμα είναι πλέον κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...