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

Position wrap mapping


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

Δημοσ.

...

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

...

 

Αυτά είναι που με βιδώνουν!

 

Επειδή εσύ ΘΑ το έκανες με states πρέπει ντε και καλά να είναι αυτός καλύτερος τρόπος και μάλιστα και με τεράστια διαφορά.

 

Να προσθέσεις δηλαδή ακόμα ένα level of abstraction μέσα στο οποίο πρέπει να διαχειριστείς και low-level nested breaks, άρα με ειδκά if's στις τιμές επιστρφής των συναρτήσεων του extra layer (αυτός είναι ο ένας και μοναδικός τρόπος, δεν υπάρχει άλλος.... πόσο μάλιστα 1002 που λες... εκτός αν εννοείς τίποτα extra global variables ή τίποτα έξτρα arguments στις συναρτήσεις του extra layer, όπου και πάλι με if θα τα διαχειριστείς απ' έξω).

 

Κι όλα αυτά με κανένα απολύτως όφελος... το "να τρέξεις τον κώδικα στο μυαλό σου" δεν ξέρω από που προκύπτει... δηλαδή με switch δεν τον τρέχεις στο μυαλό σου, αλλά με if τον τρέχεις... τι να πω!

  • Απαντ. 30
  • Δημ.
  • Τελ. απάντηση

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

Δημοφιλείς Ημέρες

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

Δημοσ.

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

 

Δεν πρόκειται να συνεχίσω σ' αυτό το topic αλλά έτσι για το γαμώτο λύσε μου μια απορία.

 

Έχουμε τα εξής δεδομένα:

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

Όταν τα βάζεις αυτά μπροστά σου για να βγάλεις συμπέρασμα, τι συμπέρασμα βγάζεις; Εκφράσου ελεύθερα ή στείλε πμ αν θέλεις.

Δημοσ.

Από που προκύπτει πως εγώ δεν έχω χρησιμοποιήσει finaite states machines? Κάνεις υποθέσεις μόνος σου και μετά τις χρησιμοποιείς ως facts και επιχειρηματολογήσεις πάνω τους;

 

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

Δημοσ.

Ρε συ δε θα συνεννοηθούμε ποτέ σε τίποτα;

 

Finite state machine χρησιμοποίησες τελευταία φορά σήμερα το απόγευμα, αυτός ακριβώς είναι και ο λόγος που είπα ότι σαν λογική δεν διαφέρουν οι 2 προσεγγίσεις. Finite state machine με switch υποθέτω ότι δεν έχεις υλοποιήσει γιατί αν είχες δε θα χρειαζόταν να κάνουμε αυτή την κουβέντα τώρα. Όπως και να χει, είτε υποθέτω σωστά είτε όχι, ας τα αφήσουμε αυτά γιατί ξέρουμε πολύ καλά που οδηγούν.

 

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

 

Και σ' αυτό που όντως ειπώθηκε (στην ερώτησή μου) δεν απάντησες.

Δημοσ.

Σε ποια ερώτηση δεν απάντησα;

 

 

 

Ούτε εσύ πάντως μου έχεις απαντήσεις πως και γιατί είναι καλύτερα να κάνεις nested breaks μέσα από switch.

 

 

Δημοσ.

Σ' αυτήν: Όταν τα βάζεις αυτά μπροστά σου για να βγάλεις συμπέρασμα, τι συμπέρασμα βγάζεις;

 

Τα nested breaks είναι πάντα πρόβλημα και η απάντηση δεν ξέρω αν θα σου αρέσει αλλά είναι "refactor για να μη χρειάζονται", το οποίο σχεδόν πάντα σημαίνει "η function είναι τεράστια και έπρεπε να έχει ήδη σπάσει". Στις (μετρημένες στα δάχτυλα του ενός χεριού) περιπτώσεις που "αναγκάστηκα" να κάνω κάτι τέτοιο η τωρινή μου άποψη είναι πως όλα τα πλάσματα είναι του θεού, ακόμα και η goto.

Δημοσ.

Σ' αυτήν: Όταν τα βάζεις αυτά μπροστά σου για να βγάλεις συμπέρασμα, τι συμπέρασμα βγάζεις;

 

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

 

Τα nested breaks είναι πάντα πρόβλημα και η απάντηση δεν ξέρω αν θα σου αρέσει αλλά είναι "refactor για να μη χρειάζονται", το οποίο σχεδόν πάντα σημαίνει "η function είναι τεράστια και έπρεπε να έχει ήδη σπάσει". Στις (μετρημένες στα δάχτυλα του ενός χεριού) περιπτώσεις που "αναγκάστηκα" να κάνω κάτι τέτοιο η τωρινή μου άποψη είναι πως όλα τα πλάσματα είναι του θεού, ακόμα και η goto.

 

Ακριβώς! Είδες που μπορούμε να συνεννοηθούμε τελικά σε κάτι; ;)

 

Trust me λοιπόν, στον συγκεκριμένο parser η switch δεν είναι σίγουρα καλύτερη από τα if, στην χειρότερη να είναι ισοδύναμη... που κι αυτό είναι πολύ χλωμο. Κι αυτό διότι για να κάνω refactor προς αποφυγή των nested breaks πρέπει να περιπλέξω αχρείαστα τον κώδικα. Btw, καμία μου συνάρτηση δεν ξεπερνάει την μια οθόνη, με μόνη εξαίρεση αυτή με το main-loop που αγγίζει τις 2 οθόνες και κατά μέσο όρο είναι μισή οθόνη/συνάρτηση.

Δημοσ.

ΤΟ ΕΛΕΟΣ !!!!!!!!!!!!!

 

Θυμόταν κανείς σας πως η fgets() επιστρέφει NULL αν το file που διαβάζει τελειώνει σε κενή γραμμή;;;;;;;;;;;;;;;

 

Θα πηδηχτώ από το παράθυρο !!!!!!!!!!!!!!!!!!

 

 

 

_fgets.dat (με κενες γραμμές στο τέλος)

>
hello
cruel
world



 

Έξοδος...

>
1: hello
2: cruel
3: world
4:
5:
FGETS ERR
Πιέστε ένα πλήκτρο για συνέχεια. . .

 

_fgets.dat (χωρίς καμία κενή γραμμή στο τέλος)

>
hello
cruel
world

 

Έξοδος...

>
1: hello
2: cruel
3: worldΠιέστε ένα πλήκτρο για συνέχεια. . .

 

testing code

>
#include <stdio.h>
#include <stdlib.h>

// ---------------------------------------------------------------------------------
int main( void )
{
   char line[256] = {'\0'};

   FILE *fp = fopen("_fgets.dat", "r");
   if ( !fp ) {
       puts( "FP ERR" );
       system( "pause" );
       exit(1);
   }

   int i=0;
   while ( !feof(fp) )
   {
       if ( !fgets(line, 256, fp) ) {
           puts( "FGETS ERR" );
           system( "pause" );
           fclose(fp);
           exit(1);
       }
       i++;
       printf( "%d: %s", i, line );
   }

   fclose( fp );
   system("pause");
   exit( 0 );
}

 

 

 

Έχω πακετωθεί 4 ώρες για να το βρω, εξετάζοντας 1002 άλλα άσχετα πράγματα (που προφανώς δεν είχαν πρόβλημα) ... ΤΑ ΝΕΥΡΑ ΜΟΥ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 

ΥΓ. Προς το παρόν το 'λυσα με Search & Replace, όπου fgets αντικατάσταση με s_fgets (από την cstring library LIBS που έχω παρατήσει μισο-τελειωμένη). Οπότε προφανώς το είχα εντοπίσει ξανά τότε, αλλά δεν το θυμόμουν :( :( :( :(

 

 

 

@defacer:

 

Μιας και μόλις πρόσεξα το παρακάτω (το έκανες edit εκ των υστέρων ίσως ή ταυτόχρονα με όταν έγραφα καμιά απάντηση; ) ...

 

Post #19

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

 

Ειπώθηκε λοιπόν στο Post #17 το Νο.2, στο οποίο εμμέσως πλην σαφώς υπονοείς πως εγώ δεν το έχω κάνει και άρα δεν ξέρω αν είναι ή όχι καλύτερα.

 

 

 

 

EDIT:

 

Ξέχασα να δώσω τα ίδια με s_fgets(), την οποία την έχω κάνει να συμπεριφέρεται διαφορετικά (π.χ. δεν κρατάει το '\n' στο τέλος του string (οπότε το τυπώνω χειροκίνητα στην printf() του testing-code ...

 

 

 

testing code

>
#include <stdio.h>
#include <stdlib.h>

/* -------------------------------------------------------------------------------
* char *s_fgets( char *s, const int len, FILE *fp )
*    char *s        : c-string to be read
*    const int len    : max chars to be read, including '\0'
*    FILE *fp    : pointer to the file, chars will be read from
*
* Read into existing cstring s up to (len-1) chars from the file pointed to by fp,
* or either a newline char or EOF is found in the file. Null terminate s, removing the
* trailing char if necessary. If more than (len-1) chars have been found before the
* newline char, they are ignored.
*
* Return a pointer to the start of read s, or NULL on error
*
* Differences over fgets():
*    -    checks if s or fp pointers are NULL
*    -    rejects the '\n' from the end of s after reading it
*    -    does NOT set errno, neither file descriptor flags
* -------------------------------------------------------------------------------
*/
char *s_fgets( char *s, const int len, FILE *fp )
{
   register int i=0;

   if ( !s || !fp )                /* non-existant s or stram    */
       return NULL;                /* ... early exit             */
   if ( len < 0 )                    /* invalid len                */
       return s;                /* ... early exit             */

                           /* read chars                 */
   for (i=0; (s[i]=getc(fp)) != EOF && s[i] != '\n' && i < len-1; i++)
       ;                    /* ... empty loop-body        */
   s[i] = '\0';                    /* null-terminate s           */

       return s;
}

// ---------------------------------------------------------------------------------
int main ( void )
{
   char line[256] = {'\0'};

   FILE *fp = fopen("_fgets.dat", "r");
   if ( !fp ) {
       puts( "FP ERR" );
       system( "pause" );
       exit(1);
   }

   int i=0;
   while ( !feof(fp) )
   {
       if ( !s_fgets(line, 256, fp) ) {
           puts( "S_FGETS ERR" );
           system( "pause" );
           fclose(fp);
           exit(1);
       }
       i++;
       printf( "%d: %s\n", i, line );
   }

   fclose( fp );
   system("pause");
   exit( 0 );
}

 

Έξοδος από _fgets.dat (με κενές γραμμές στο τέλος)

>
1: hello
2: cruel
3: world
4:
5:
6:
Πιέστε ένα πλήκτρο για συνέχεια. . .

 

 

Δημοσ.

ΤΟ ΕΛΕΟΣ !!!!!!!!!!!!!

 

Θυμόταν κανείς σας πως η fgets() επιστρέφει NULL αν το file που διαβάζει τελειώνει σε κενή γραμμή;;;;;;;;;;;;;;;

 

 

 

Αλλάζοντας την printf σε printf( "%d: %d %s", i, *line, line ); ώστε να εμφανίζει και τον 1ο χαρακτήρα του string παίρνω το παρακάτω

>
% ./a.out 
1: 104 hello
2: 99 cruel
3: 119 world
4: 10 
5: 10 
FGETS ERR

 

το οποίο μου φαίνεται κανονική συμπεριφορά της fgets. Όπως στις μη-κενές γραμμές αποθηκεύει το string + τον χαρακτήρα newline, στις κενές γραμμές δεν επιστρέφει NULL αλλά αποθηκεύει μόνο τον χαρακτήρα newline. Αυτό σε gcc σε linux, clang σε linux, gcc σε solaris. Μήπως δεν κατάλαβα καλά τι εννοείς ?

 

Στην s_fgets δεν θα έπρεπε ο έλεγχος για "i < len - 1" να είναι πριν το getc για να καλύπτει την περίπτωση όπου len = 1 ?

Δημοσ.

...

Μήπως δεν κατάλαβα καλά τι εννοείς ?

 

Εκεί που λέει FGETS_ERR είναι μια κενή γραμμή (η οποία όμως συγκριτικά με τις προηγούμενες διαφοροποιείται στο ότι ακολουθείται από EOF). Σε αυτή την γραμμή επιστρέφει NULL η fgets().

 

Είναι documented πως για να εξετάσει κανείς αν το NULL της fgets() οφείλεται σε error ή σε eof πρέπει να εξετάζεται ξεχωριστά με τις ferror() και feof(), αντίστοιχα, αλλά εγώ δεν το θυμόμουν !!!!!!!!!

 

Για αυτό ρώτησα αν το θυμόταν κανείς απ΄έξω :P

 

Δοκίμασέ το και με ένα απλό '\n' αμέσως μετά το "world"... πάλι NULL θα επιστρέψει.

 

...

Στην s_fgets δεν θα έπρεπε ο έλεγχος για "i < len - 1" να είναι πριν το getc για να καλύπτει την περίπτωση όπου len = 1 ?

 

Από ότι το βλέπω τώρα πρόχειρα, όχι. Δεν κρατάει το '\n' η s_fgets().

Δημοσ.

 

 

Εκεί που λέει FGETS_ERR είναι μια κενή γραμμή (η οποία όμως συγκριτικά με τις προηγούμενες διαφοροποιείται στο ότι ακολουθείται από EOF). Σε αυτή την γραμμή επιστρέφει NULL η fgets().

 

Είναι documented πως για να εξετάσει κανείς αν το NULL της fgets() οφείλεται σε error ή σε eof πρέπει να εξετάζεται ξεχωριστά με τις ferror() και feof(), αντίστοιχα, αλλά εγώ δεν το θυμόμουν !!!!!!!!!

 

Για αυτό ρώτησα αν το θυμόταν κανείς απ΄έξω :P

 

Δοκίμασέ το και με ένα απλό '\n' αμέσως μετά το "world"... πάλι NULL θα επιστρέψει.

 

Α τώρα κατάλαβα τι λες. Δεν φαίνεται από το φόρουμ αλλά το δεύτερο _fgets.dat που έχεις δώσει δεν έχει καθόλου newline μετά το world. Το αρχείο τελειώνει στο world, έτσι ? Σε αυτή τη περίπτωση δεν παίρνω FGETS ERR όντως. Έσβησες εσύ επίτηδες την newline ?

 

Δεν πήγε εκεί το μυαλό μου γιατί όσα αρχεία έχω δουλέψει πάντα έχουν newline και στην τελευταία γραμμή. Και το vim και όλοι οι editors προσθέτουν αυτόματα newline στην τελευταία γραμμή.

 

Το "πρόβλημα" σου υπάρχει επειδή χρησιμοποιείς ως συνθήκη στο while την feof οπότε όταν υπάρχει η newline τρέχει ξανά η fgets.

 

Από ότι το βλέπω τώρα πρόχειρα, όχι. Δεν κρατάει το '\n' η s_fgets().

Δεν μιλούσα για το '\n'. Η fgets αντιγράφει n - 1 χαρακτήρες και ο nιοστός είναι το '\0'. Έτσι για n = 1, δεν θα διαβάσει κανένα χαρακτήρα και απλά θα γράψει το '\0'. Η s_fgets όταν κληθεί με len = 1, στο for θα κληθεί το s = getc και θα αποθηκεύει ένα χαρακτήρα, σωστά ?

Δημοσ.

Α τώρα κατάλαβα τι λες. Δεν φαίνεται από το φόρουμ αλλά το δεύτερο _fgets.dat που έχεις δώσει δεν έχει καθόλου newline μετά το world. Το αρχείο τελειώνει στο world, έτσι ? Σε αυτή τη περίπτωση δεν παίρνω FGETS ERR όντως. Έσβησες εσύ επίτηδες την newline ?

 

Δεν πήγε εκεί το μυαλό μου γιατί όσα αρχεία έχω δουλέψει πάντα έχουν newline και στην τελευταία γραμμή. Και το vim και όλοι οι editors προσθέτουν αυτόματα newline στην τελευταία γραμμή.

 

Δεν την έσβησα, εξαρχής το έγραψα το παράδειγμα χωρίς newline (και το σημείωσα στην παρένθεση, πως δεν έχει καμία κενή γραμμή στο τέλος). Στο επόμενο παράδειγμα έβαλα 3 κενές γραμμές.

 

Το "πρόβλημα" σου υπάρχει επειδή χρησιμοποιείς ως συνθήκη στο while την feof οπότε όταν υπάρχει η newline τρέχει ξανά η fgets.

 

+ ότι μέσα στις συναρτήσεις bool parseUntil_xxx() έχω συνθήκες, του στυλ...

 

>
if ( !fgets(blabla) )
   return false;

 

Προς το παρόν η s_fgets() δείχνει να διορθώνει ανώδυνα το πρόβλημα (έως ότου σκάσει πουθενά αλλού κι αυτή :lol:)

 

EDIT

 

Που να πάει το μυαλό σου εκεί πέρα ρε συ; Ούτε το δικό μου πήγαινε για περίπου 4 ώρες :( :( :(

 

...

Δεν μιλούσα για το '\n'. Η fgets αντιγράφει n - 1 χαρακτήρες και ο nιοστός είναι το '\0'. Έτσι για n = 1, δεν θα διαβάσει κανένα χαρακτήρα και απλά θα γράψει το '\0'. Η s_fgets όταν κληθεί με len = 1, στο for θα κληθεί το s = getc και θα αποθηκεύει ένα χαρακτήρα, σωστά ?

 

Σωστά, τον οποίον όμως θα τον μηδενίσει αμέσως μετά το loop. Είναι documented στα σχόλιά της πως κρατάει len-1 ωφέλιμους χαρακτήρες (γιατί ο τελευταίος είναι reserved για '\0').

Δημοσ.

Που να πάει το μυαλό σου εκεί πέρα ρε συ; Ούτε το δικό μου πήγαινε για περίπου 4 ώρες :( :( :(

 

Δεν πήγε το μυαλό μου γιατί αφενός αποφεύγω να ελέγχω με feof λόγω ότι βαράει _αφού_ έχεις διαβάσει και τον τελευταίο χαρακτήρα αλλά πιο πολύ γιατί έχω συνηθίσει όλα τα αρχεία να έχουν στο τέλος newline.

 

Σωστά, τον οποίον όμως θα τον μηδενίσει αμέσως μετά το loop. Είναι documented στα σχόλιά της πως κρατάει len-1 ωφέλιμους χαρακτήρες (γιατί ο τελευταίος είναι reserved για '\0').

 

Ναι φυσικά θα τον μηδενίσει. Τζάμι παίζει σε αυτό. Δεν το διατύπωσα καλά μάλλον για αυτό δεν φάνηκε αυτό που ήθελα να πω.

 

>
int main(void)
{
       char line[256] = {'\0'};
       FILE *fp;
       int c;

       strcpy(line, "hello");
       c = '\0';
       fp = fopen("_fgets.dat", "r");
       fgets(line,1,fp);
       c = getc(fp);
       printf("c=%c - s[0]=%d - s=%s\n", c, *line, line);
       fclose( fp );

       strcpy(line, "hello");
       c = '\0';
       fp = fopen("_fgets.dat", "r");
       s_fgets(line,1,fp);
       c = getc(fp);
       printf("c=%c - s[0]=%d - s=%s\n", c, *line, line);
       fclose( fp );

       return 0;
}

Έξοδος:
c=h - s[0]=0 - s=
c=e - s[0]=0 - s=

 

Δες τον παραπάνω κώδικα (χάριν ευκολίας χωρίς ελέγχους). Και στις δύο περιπτώσεις παίρνουμε ένα string με κανένα οφέλιμο χαρακτήρα και τον 1ο χαρακτήρα το '\0' δηλαδή συμπεριφορά που έπρεπε να έχουμε. Η fgets όμως διαβάζει (1-1=0) μηδέν χαρακτήρες οπότε η getc που εκτελείται μετά επιστρέφει το 'h' που είναι ο 1ος χαρακτήρας που έχει το αρχείο μας. Η s_fgets ενώ μεν μηδενίζει τη σωστή θέση, έχει πρώτα διαβάσει τον χαρακτήρα οπότε χάνουμε το 1ο χαρακτήρα και η getc επιστρέφει 'e'. Γίνομαι τιτίζης πάλι :) αλλά μια και είπες ότι μπορεί να σκάσει κάπου η s_fgets είπα να το αναφέρω.

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

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