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

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

Δημοσ.

Καλησπέρα παιδιά,

καθώς πριν από λίγο καιρό άρχισα να ασχολούμαι με την C,θέλω τα φώτα σας για την υλοποίηση μιας άσκησης που έχω για την σχολη!! Η εκφώνηση είναι η εξής:http://cgi.di.uoa.gr/~ip/iphw1415_2.pdf

Τα ερωτήματα μου είναι τα εξής: Προγραμματιστικα ποιά είναι η καλύτερη μέθοδος για να υλοποιήσω την άσκηση ώστε να μην έχω bugs στο τέλος της? Είναι καλή λύση να ξεκινήσω υλοποιώντας κάθε κανόνα στοίχισης σύμφωνα με την εκφώνηση? Μπορείτε να μου δώσετε κάποια βοήθεια με κώδικα στον 3ο,4ο και 5ο κανόνα ώστε να καταλάβω τι παίζει?

Δημοσ.

Αυτο που σε νοιαζει ειναι ποτε θα πρεπει να ξεκινας νεα γραμμή (π.χ. μετα το ερωτηματικό)  και με τι indent.  

Γενικα θα εχεις ενα indent αρχικα 0, θα το αυξανεις κατα 1 οταν συναντας '{' και θα το μειωνεις οταν ερθει '}'.

Ειναι και αλλες περιπτωσεις, αλλα ξεκινα ενα ενα 

Δημοσ.

Αυτός είναι ο κώδικας που έχω μέχρι τώρα:

#include <stdio.h>
int main(void)
{
int linestarted,p1,p2,n,c,flag,p3,p4;
  p1=0;
  p2=0;
  flag=0;
  n=-2;
  p3=0;
  p4=0;
    printf("Input some characters, then press Ctrl+D.\n");
    while ((c=getchar())!= EOF){
      if(c=='#'){
      putchar©;
      while((c=getchar())!='\n')
    putchar©;
}
  if(c=='\''){
putchar©;
while((c=getchar())!='\'')
putchar©;
}
  if(c=='"'){
  putchar©;
  while((c=getchar())!='"')
  putchar©;
  }
     if(c=='{')
     p3++;
     if(c=='}')
      p4++;
     if(c=='(')
        p1++;
        if(c==')')
        p2++; 
        while((c==' ')||(c=='\n')||(c=='\t')){
               if(flag==0){
            flag=1;
            putchar(' ');
            }
            c=getchar();}
        if  (((c=='{')||(c=='}')||(c == ';'))&&(p1==p2)){      
             putchar©;
             putchar('\n');  }
         else  {
          flag=0;
            putchar©;}
       n=c;}
    return 0;
}
 
Επειδή συναντάω ορισμένα bugs...Μπορείς να με βοηθήσεις στην τροποποίηση του?
Δημοσ.

Αρκέτα δύσκολη για εισαγωγική άσκηση.

 

Πριν κανεις οτι κανεις, φτιαξε ενα workflow. Για να δεις όλα τα case που θα εχεις. Πχ ignore τα παντα μέχρι newline όταν εχεις #, ή να μην μετράς το ; {} όταν είναι σε quote κλπ κλπ

  • Like 1
Δημοσ.

Αυτό που με δυσκολεύει και δεν μπορώ να καταλάβω είναι το πώς πρέπει να κινηθώ προγραμματιστικά για να υλοποιήσω την άσκηση!!

Όπως βλέπεις μεμονωμένα τους περισσότερους κανόνες στοίχισης μπορώ να τους υλοποιήσω!!!Το πρόβλημα μου είναι το πως μπορούν να συνδυαστούν....Μπορείς να μου δώσεις μια βοήθεια? 

Δημοσ.

Ο ευκολότερος τρόπος να γίνει αυτό είναι με finite state machine.

 

Το finite state machine είναι μπακάλικα μια συνάρτηση η οποία παίρνει δύο παραμέτρους: την τρέχουσα "κατάσταση" (state) του συστήματος και την επόμενη είσοδο (εδώ, ένα ένα τους χαρακτήρες της εισόδο). Από αυτές τις δύο παραμέτρους προκύπτει α) το αν θα κάνεις κάτι επιτόπου και τι θα είναι αυτό και β) το ποιά θα είναι η επόμενη κατάσταση του συστήματος (η οποία σε συνδυασμό με το επόμενο τμήμα της εισόδου.... κλπ κλπ).

 

Το state είναι στην ουσία ένα σύνολο με N στοιχεία που δε μας ενδιαφέρει ποιά είναι, μας ενδιαφέρει μόνο να τα ξεχωρίζουμε. Οπότε σε πρώτη φάση ας πούμε για ευκολία ότι είναι οι ακέραιοι 1 ως N, όπου ο καθένας συμβολίζει "κάτι".

 

Ο ευκολότερος τρόπος να φτιάξεις το fsm είναι με ένα μεγάλο switch:

 

switch(state) {

    case 1:

        // ....

        break;

    // ...

    case N:

        // ....

        break;

}

 

αυτό θα μπει μέσα σε ένα μεγάλο while:

 

while(έχεις κι άλλη είσοδο) {

    char ch = διάβασε_τον_επόμενο_char_από_την_είσοδο();

    switch (state) { ... }

}

 

Τώρα το μόνο που μένει είναι μέσα στο switch να φτιάξεις τα case έτσι που με δεδομένο το ch και το state (τις δύο εισόδους) να κάνεις "κάτι" (αν χρειάζεται) και να αλλάζεις το state (πάλι αν χρειάζεται). Το πότε χρειάζεται και τι είναι η λογική του προγράμματος που θα γράψεις.

 

Ας πούμε τώρα ένα απλό παράδειγμα: η είσοδος αποτελείται μόνο από ψηφία και θαυμαστικά. Η έξοδος είναι: για κάθε ψηφίο που ακολουθεί θαυμαστικό το διπλάσιό του, αλλιώς το μισό (ακέραια διαίρεση).

 

Τα states είναι μόνο δύο: ή είσαι μετά από θαυμαστικό (έστω state 2) ή δεν είσαι (state 1). Το πρόγραμμα είναι χοντρικά:

int state = 1;
while(ch = getchar()) {
    switch (state) {
        case 1:
            if (ch == '!') { state = 2; continue; }
            else { printf("%d", (ch - '0') / 2); }
            break;
        case 2:
            if (ch == '!') { /* σφάλμα: 2 θαυμαστικά στη σειρά, κάνε ο,τι νομίζεις */ }
            else { printf("%d", (ch - '0') * 2); state = 1; }
    }
}

Το πρόγραμμα που σου ζητείται είναι αυτή η ιδέα αλλά στο λίγο πιο πολύπλοκο -- θα χρειστείς states για το αν είσαι μέσα σε string (οπότε τα { } και # δεν θα έχουν ιδιαίτερη μεταχείριση, τα κενά θα περνάνε αμετάβλητα κλπ ενώ με " θα βγαίνεις από το string) ή αν είσαι μέσα σε γραμμή #define οπότε δε θα στοιχίζεις, ή αν τίποτα από τα παραπάνω. Σε καθένα από αυτά τα state θα έχεις πολλούς ελέγχους να κάνεις για το τι χαρακτήρα διάβασες, θα χρειάζεται να θυμάσαι και ποιός ήταν ο προηγούμενος, θα χρειάζεται να θυμάσαι το τρέχον βάθος στοίχισης, κλπ.

 

Δυσκολάκι για φοιτητές "κατά τύχη βρέθηκα εδώ", about right για όποιον όντως θέλει να μάθει προγραμματισμό.

  • Like 1

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

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

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

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

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

Σύνδεση

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

Συνδεθείτε τώρα
  • Δημιουργία νέου...