Spiroslp Δημοσ. 17 Μαΐου 2011 Δημοσ. 17 Μαΐου 2011 Καλησπέρα. Η άσκηση την έχεις ένας φίλος μου και δεν θυμάμαι να το βοηθήσω σε μια μικρή λεπτομέρεια. Η Άσκηση ζητάει να δηλώνουμαι έναν δυαδικό πίνακα και να τον γεμίζουμε και τον εκτυπώνουμε. Αλλά αυτό που ζητάει και δεν θυμάμαι είναι ότι άμα δώσουμε χαρακτήρα να βγάζει μήνυμα λάθους και να συνεχίζει. Πως το κάνουμε αυτό; Εδώ ο κώδικας που δεν μου βγαίνει: > #include <stdio.h> #include <stdlib.h> int main() { int i,j, pin [2][3]; char c; for(i=0;i<2;i++) { for(j=0;j<3;j++) { printf("Dose noymero\n"); scanf ("%d",&pin[i][j]); if( pin[i][j] == c) printf("Akyro\n"); } } for(i=0;i<2;i++) { for(j=0;j<3;j++) { printf("[%d] [%d] %d\n",i,j,pin[i][j]); } } return 0; }
migf1 Δημοσ. 17 Μαΐου 2011 Δημοσ. 17 Μαΐου 2011 Αντί να διαβάζεις integers, διάβαζε strings και κράτα τα μόνο αν είναι αριθμοί. Θα χρειαστεί να χρησιμοποιήσεις τη στάνταρ βιβλιοθήκη ctype.
Spiroslp Δημοσ. 18 Μαΐου 2011 Μέλος Δημοσ. 18 Μαΐου 2011 Σωστό αλλα μας είχε πει η καθηγήτρια παλιά ότι γίνεται και χωρίς να προσθέσεις το ctype απλά μόνο με το stdio και το stdlib.
Timonkaipumpa Δημοσ. 18 Μαΐου 2011 Δημοσ. 18 Μαΐου 2011 1ον Στο if, συγκρίνεις κάτι που έχει τιμή με κάτι που δεν έχει τιμή (τι τιμή έχει το c ; ) 2ον Μπορείς να διαβάζεις χαρακτήρες και να ελέγχεις εάν η τιμή τους είναι μέσα στα όρια του αλφάβητου (δεν θυμάμαι από που μέχρι που είναι.... ) συμπεριλαμβάνοντας και τα κεφαλαία. Φυσικά θα πρέπει να βρεις και τα σημεία στίξης κτλ κτλ κτλ. Οπότε δες απλά ποια είναι τα όρια των χαρακτήρων που είναι αριθμοί, δηλαδή τι τιμή έχει μία μεταβλητή char, με το char να είναι '1', '2', κτλ κτλ κτλ
Directx Δημοσ. 18 Μαΐου 2011 Δημοσ. 18 Μαΐου 2011 Θα μπορούσες να χρησιμοποιήσεις την strspn, αν επιτρέπεται βέβαια (είναι δηλωμένη στο string.h) ώστε να εξετάσεις αν η είσοδος του χρήστη αποτελείται μόνο από αριθμητικούς χαρακτήρες και τούτο σκεπτόμενος ότι καθώς η strspn επιστρέφει το μήκος του κειμένου που απαρτίζεται από ένα ορισμένο σετ χαρακτήρων (πχ. 0123456789) αν υπάρχουν άλλοι άγνωστοι χαρακτήρες τότε το μήκος αυτό θα διαφέρει από το ανάλογο της strlen. Από εκεί και πέρα η ανάγνωση του πληκτρολογίου μπορεί να γίνει με την βοήθεια της fgets η οποία είναι αρκετά σταθερή κατά την ανάγνωση του stdin (με μόνο μειονέκτημα ότι προσθέτει το CR/LN '\n' στο τέλος του string) και την sscanf η οποία δρα σαν την scanf μόνο που διαβάζει πληροφορίες από το string-buffer (μεγέθους BUFSIZ -δηλωμένο constant στην stdio.h) που ορίζουμε (αντί του stdin). Ακολουθεί ένα μικρό παράδειγμα γραμμένο σε C++ Builder 2009: > #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { int i,j, pin [2][3]; char c, szNum[bUFSIZ]; for(i=0;i<2;i++) { for(j=0;j<3;j++) { /* Loop until valid number */ while(1) { printf("Dose noymero\n"); /* Read stdin, up to BUFSIZ, into szNum buffer */ fgets(szNum, BUFSIZ, stdin); /* Anything to process (fgets appends \n auto.)? */ if(!strcmp(szNum, "\n")) continue; /* No.. */ /* szNum should only contain numeric chrs. (minus fgets \n) */ if(strspn(szNum, "0123456789") != strlen(szNum) - 1) printf("Bad input - %s\n", szNum); else break; } /* Works like scanf but instead of stdin uses szNum */ sscanf(szNum, "%d", &pin[i][j]); if( pin[i][j] == c) printf("Akyro\n"); } } for(i=0;i<2;i++) { for(j=0;j<3;j++) { printf("[%d] [%d] %d\n",i,j,pin[i][j]); } } getchar(); return 0; } ΕΞΟΔΟΣ: > Dose noymero 1 Dose noymero 2a Bad input - 2a Dose noymero 2 Dose noymero 3 Dose noymero 4 Dose noymero 5.000 Bad input - 5.000 Dose noymero 5000 Dose noymero 6000 [0] [0] 1 [0] [1] 2 [0] [2] 3 [1] [0] 4 [1] [1] 5000 [1] [2] 6000 Υ.Γ. Φυσικά, όπως ελέχθη, μπορεί να γραφθεί πολύ απλά, δίχως καν την stdlib.h ή την ctype ή string.h κτλ. με απλό έλεγχο κάθε chr. του string για ASCII τιμές 0 ως 9 (ή \n λόγο fgets) και απόρριψη της εισόδου σε κάθε διαφορετικό χαρακτήρα: > /* Return 0 on first non numeric P character */ int _isNumber(char *P) { while(*P) { if((*P < '0' || *P > '9') && *P != '\n') return 0; P++; } return 1; }
migf1 Δημοσ. 18 Μαΐου 2011 Δημοσ. 18 Μαΐου 2011 [snip] Υ.Γ. Φυσικά, όπως ελέχθη, μπορεί να γραφθεί πολύ απλά, δίχως καν την stdlib.h ή την ctype ή string.h κτλ. με απλό έλεγχο κάθε chr. του string για ASCII τιμές 0 ως 9 (ή \n λόγο fgets) και απόρριψη της εισόδου σε κάθε διαφορετικό χαρακτήρα: [snip] Κάτι τέτοιο σκεφτόμουν κι εγώ, όταν ο φίλος Spiroslp διευκρίνισε πως του είπαν να γίνει μόνο με stdio.h και stdlib.h, αλλά με λίγο διαφορετική υλοποίηση. Η αναφορά στην stdlib.h έγινε κατά πάσα πιθανότητα για τις συναρτήσεις atoi(), atol(), strtol() κλπ που μετατρέπουν strings σε αριθμούς. Επίσης αντί για fgets() και sscanf() εγώ χρησιμοποιώ μια δική μου συνάρτηση: s_get() που δουλεύει σαν την fgets(), αλλά δεν χρειάζεται filestream στα ορίσματα και σβήνει και το '\n' στο τέλος, πριν επιστρέψει (την συμπεριλαμβάνω σχεδόν σε όλα τα παραδείγματα που έχω ποστάρει ) Επίσης, εφόσον μας έχουν αποκλείσει την ctype.h, φτιάχνω τη δική μου έκδοση του macro isdigit(), που το ονομάζω is_digit(). Και τέλος, φτιάχνω και μια συνάρτηση s_isnumber() η οποία επιστρέφει TRUE (μη μηδενική τιμή) αν το string περιέχει μονάχα αριθμητικούς χαρακτήρες (αλλιώς FALSE). > #include <stdio.h> #include <stdlib.h> // για το atoi() #define MAX_INPUTLEN 255 #define is_digit(c) ( (c) >= '0' && (c) <= '9' ) // ------------------------------------------------------------------------------------ // Διαβάζει μέχρι len-1 χαρακτήρες από το πληκτρολόγιο, μηδενίζει τον len-οστο // και τους αποθηκεύει στο string s // char *s_get(char *s, size_t len) { char *cp; for (cp=s; (*cp=getc(stdin)) != '\n' && (cp-s) < len-1; cp++ ) ; // for-loop με κενό σώμα *cp = '\0'; // μηδενισμός τελικού χαρακτήρα return s; } // ------------------------------------------------------------------------------------ // Επιστρέφει TRUE αν όλοι οι χαρακτήρες του string s είναι αριθμοί, αλλιώς FALSE // int s_isnumber(const char *s) { if ( !s ) return 0; register char *cp; for (cp=s; *cp && is_digit(*cp); cp++) ; return (*cp && cp != s); } // ------------------------------------------------------------------------------------ int main( void ) { int i,j, pin[2][3]; char s[MAX_INPUTLEN] = ""; // Είσοδος for(i=0;i<2;i++) { for(j=0;j<3;j++) { printf("Dwste noymero gia th thesh [%d][%d]: ", i,j); s_get(s, MAX_INPUTLEN); while ( !s_isnumber(s) ) { printf("\tden dwsate noymero, janadokimaste: "); s_get(s, MAX_INPUTLEN); } pin[i][j] = atoi(s); // μετατρέπει το s σε integer } } putchar('\n'); // Έξοδος for(i=0; i<2; i++) for(j=0; j<3; j++) printf("[%d] [%d] %d\n",i,j,pin[i][j]); putchar('\n'); printf("pathste ENTER gia termatismo..."); fflush(stdin); getchar(); exit(0); }
Spiroslp Δημοσ. 19 Μαΐου 2011 Μέλος Δημοσ. 19 Μαΐου 2011 Παιδιά με την ctype πως θα το κάνω; Ποιος θα είναι ο κώδικας;
Directx Δημοσ. 20 Μαΐου 2011 Δημοσ. 20 Μαΐου 2011 Παιδιά με την ctype πως θα το κάνω; Ποιος θα είναι ο κώδικας; Μπορείς να χρησιμοποιήσεις την isdigit της ctype.h η οποία επιστρέφει μηδέν σε περίπτωση μη αριθμητικού χαρακτήρα. Από εκεί και πέρα λοιπόν με την βοήθεια ενός for ή while loop (ειδικά σε περίπτωση που παίζεις με δείκτες) μπορείς να εξετάσεις τους χαρακτήρες που εισήγαγε ο χρήστης στο πρόγραμμα διακόπτοντας στον πρώτο μη αριθμητικό χαρακτήρα και ζητώντας εκ νέου εισαγωγή. Ακολουθεί ένα απλό παράδειγμα (δοκιμασμένο σε C++ Builder 2009) το οποίο λύνει το ζήτημα είτε με την ctype (αν ορίσεις το _USE_CTYPE ως #define) είτε δίχως αυτή. > #include <stdio.h> #define _USE_CTYPE #ifdef _USE_CTYPE #include <ctype.h> #endif int main(void) { int i,j, pin [2][3]; char c, szNum[bUFSIZ] = ""; /* CType version? */ #ifdef _USE_CTYPE printf("CTYPE VERSION\n"); #endif for(i=0;i<2;i++) for(j=0;j<3;j++) { /* Loop until valid number */ while(1) { char *ptrNum, cBadInput = 0; printf("Dose noymero\n"); /* Read stdin, up to BUFSIZ, into szNum buffer (returns ptr. to szNum) */ ptrNum = fgets(szNum, BUFSIZ, stdin); /* Remove trailing \n from szNum (if szNum not NULL) */ while(ptrNum && *ptrNum) if(*ptrNum == '\n' && !*(ptrNum + 1)) { *ptrNum = 0; break; } else ptrNum++; /* Empty string? */ if(!szNum[0]) continue; /* Yes, redo input! */ /* Get a pointer to szNum buffer */ ptrNum = (char*)szNum; /* Check each ptrNum chr. for not been a numeric and if so stop! */ while(ptrNum && *ptrNum) { #ifdef _USE_CTYPE /* CType depended version */ if(!isdigit(*ptrNum)) { cBadInput = 1; break; } #else /* Plain stdio.h version */ if(*ptrNum < '0' || *ptrNum > '9') { cBadInput = 1; break; } #endif ptrNum++; } /* Good input? */ if(cBadInput) printf(" Bad input - %s\n", szNum); else /* Works like scanf but instead of stdin uses szNum */ if(!sscanf(szNum, "%d", &pin[i][j])) printf(" Invalid input - %s\n", szNum); /* Ooops! */ else break; } if(pin[i][j] == c) printf("Akyro\n"); } printf("\n"); for(i=0;i<2;i++) for(j=0;j<3;j++) printf("[%d] [%d] %d\n",i,j,pin[i][j]); printf("\nPress Enter to exit.."); getchar(); return 0; } Καλή συνέχεια! Υ.Γ. Αν σε δυσκολεύουν οι pointers μπορεί να υλοποιηθεί και δίχως αυτούς.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.