johnykim Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Καλησπέρα. Θέλω να διαγράψω κάποιες τιμές από έναν μονοδιάστατο πίνακα,άλλα έχω κάποιο πρόβλημα.Ο κώδικας είναι ο παρακάτω: >#include <stdio.h> #include <stdlib.h> main() { char pinakas[10]; int i=0; printf("Dwse times pinaka\n"); gets(pinakas); //scanf("%s",pinakas); for (i=0;i<10;i++) { if (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' || pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9') { printf("\nMh dineis arithmo\n"); pinakas[i]='0; //pinakas[i]=' '; } } printf("\nXarakthres = %s\n",pinakas); printf("Plithos = %lu\n",strlen(pinakas)); system("PAUSE"); return 0; } Σε μια συμβολοσειρά που δίνει ο χρήστης, θέλω να εμφανίζω το πλήθος των χαρακτήρων που δίνει,αλλά όχι τους αριθμούς.Έτσι μηδενίζω τις συγκεκριμένες τιμές με μια if(η if μπορεί να γίνει καλύτερη με επανάληψη ,αλλά κάνω δοκιμές ακόμα). Όταν δίνω πρώτα γράμματα ή άλλους χαρακτήρες εκτός αριθμούς,και μετά δίνω αριθμούς το πρόγραμμα λειτουργεί.Όταν όμως δίνω πρώτα αριθμούς και μετά άλλους χαρακτήρες, επιστρέφουν οι printf μηδέν. Δοκίμασα να χρησιμοποιήσω την scanf ,αντί για την gets,έτσι ώστε να μην μετράει τα κενά ,και αντί να μηδενίζω τις τιμές που δεν θέλω, να τις αντικαθιστώ με κενό όπου δεν θα έχει διαβάσει η scanf.Δυστυχώς όμως στο πλήθος είναι μέσα και οι αριθμοί(κενά).
bnvdarklord Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Αντικατεστησε το for που εχεις με αυτο > int plithos = 0; for (i=0;i<10;i++) { if (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' || pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9') { continue; } else plithos ++; } και μετα τυπωσε το plithos
parsifal Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Ούτε if ούτε counters: > scanf("%9[A-Za-z]s", pinakas); Και με μία strlen στο τέλος είσαι αρχηγός. edit: Άκυρο, δεν είναι σωστή η λύση που προτείνω. Sorry!
johnykim Δημοσ. 24 Ιουνίου 2010 Μέλος Δημοσ. 24 Ιουνίου 2010 Αντικατεστησε το for που εχεις με αυτο > int plithos = 0; for (i=0;i<10;i++) { if (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' || pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9') { continue; } else plithos ++; } και μετα τυπωσε το plithos >#include <stdio.h> #include <stdlib.h> main() { char pinakas[10]; int i; int p=0; printf("Dwse times pinaka\n"); gets(pinakas); //scanf("%s",pinakas); for (i=0;i<10;i++) { if (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' || pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9') { continue; } else { p++; } } printf("\nXarakthres = %s\n",pinakas); printf("Plithos = %d\n",p); system("PAUSE"); return 0; } Τι λάθος κάνω; Το πλήθος δεν βγαίνει σωστό.. @parsifal,αν και είδα το edit,θα το δοκίμαζα αν μου έλεγες τι ακριβώς διαβάζεις με την scanf..
parsifal Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 @parsifal,αν και είδα το edit,θα το δοκίμαζα αν μου έλεγες τι ακριβώς διαβάζεις με την scanf.. Η scanf με τη συγκεκριμένη σύνταξη διαβάζει το πολύ 9 χαρακτήρες, με scanset A-Za-z μέχρι να συναντήσει χαρακτήρα που δεν ανήκει σε αυτό το scanset. Όπως είπα όμως, δεν κάνει αυτό που ζητάς γιατί ακριβώς σταματά όταν συναντήσει χαρακτήρα εκτός scanset, δεν τον απορρίπτει απλώς και πάει παρακάτω. Άρα, αν η συμβολοσειρά που εισάγει ο χρήστης: 1. Αρχίζει με χαρακτήρα εκτός scanset, π.χ. "1abc" ή 2. Περιέχει εμβόλιμα τέτοιους χαρακτήρες, π.χ. "a1bc" ο κώδικας δε θα έχει επιθυμητή συμπεριφορά.
imitheos Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 > main() Να δηλώνεις την main πάντα ως int main(void); > char pinakas[10]; gets(pinakas); Η gets δεν πρέπει να χρησιμοποιείται ποτέ επειδή δεν ελέγχει το μέγεθος του buffer (επίσης θεωρείται deprecated και θα πάψει να υπάρχει στις διάφορες libc). Εσύ δηλώνεις τον πίνακα με μέγεθος 10. Αν ο χρήστης δώσει 20 χαρακτήρες τότε αυτοί οι χαρακτήρες θα γραφτούν σε περιοχή μνήμης που δεν θα έπρεπε (πιθανότατα θα σβήσουν τα i,p και ποιος ξέρει τι άλλο). Μπορείς να χρησιμοποιείς την fgets ή άλλες με ίδια λειτουργία. > for (i=0;i<10;i++) Εκτελείς το for 10 φορές ενώ ο χρήστης μπορεί να δώσει 6 χαρακτήρες. Έλεγξε με την strlen το μέγεθος. > if (pinakas[i]=='0' || pinakas[i]=='1' || pinakas[i]=='2' || pinakas[i]=='3' || pinakas[i]=='4' || pinakas[i]=='5' || pinakas[i]=='6' || pinakas[i]=='7' || pinakas[i]=='8' || pinakas[i]=='9') Αν χρησιμοποιείς ASCII, τότε οι αριθμοί είναι συνεχόμενοι και έχουν τιμές 0x30-0x39 οπότε μπορείς να το χρησιμοποιήσεις αυτό για να μην έχεις όλο αυτό το if > system("PAUSE"); Μην χρησιμοποιείς την system("PAUSE"). Αφενός η system είναι πολύ βαριά και αφετέρου το πρόγραμμά σου θα παίζει μόνο σε Windows. Χρησιμοποίησε μια εντολή που να δέχεται ένα χαρακτήρα όπως scanf,getchar. @parsifal,αν και είδα το edit,θα το δοκίμαζα αν μου έλεγες τι ακριβώς διαβάζεις με την scanf.. Η scanf που έδωσε ο parsifal διαβάζει 9 αλφαριθμητικούς χαρακτήρες (αν δεν κάνω λάθος δεν χρειάζεται το s στο τέλος). Το πρόγραμμά σου θα μπορούσε να γίνει ως εξής: > #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char pinakas[10]; int i; int s, p=0; printf("Dwse times pinaka\n"); fgets(pinakas, 10, stdin); s=strlen(pinakas); if (pinakas[s-1]==0xa) s--; for (i=0;i<s;i++) { if ((pinakas[i]<0x30) || (pinakas[i]>0x39)) p++; } printf("\nXarakthres = %s\n",pinakas); printf("Plithos = %d\n",p); i=getchar(); return 0; }
parsifal Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Ορίστε, ο παρακάτω κώδικας πρέπει να κάνει ακριβώς αυτό που θέλεις: > #include <stdio.h> #include <string.h> int main(void) { char pinakas[10] = "", c; int i, index; printf("Eisagete symvoloseira: "); for(i = 0; i < 9 && (c = getchar()) != '\n';) { if(c >= '0' && c <= '9') continue; index = strlen(pinakas); pinakas[index] = c; pinakas[index + 1] = '\0'; i++; } printf("Xarakthres = %s\n", pinakas); printf("Plithos = %d\n", strlen(pinakas)); return 0; } Τσέκαρέ τον και αν έχεις απορίες, εδώ είμαστε!
imitheos Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 parsifal ftw Αντί για το index+strlen, δεν θα μπορούσε να χρησιμοποιηθεί το i ? Στην συγκεκριμένη περίπτωση δεν παίζει ρόλο, αλλά γενικά να μην χρησιμοποιείται μεταβλητή τύπου char στις συναρτήσεις που επιστρέφουν χαρακτήρα.
parsifal Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Αντί για το index+strlen, δεν θα μπορούσε να χρησιμοποιηθεί το i ? Στην συγκεκριμένη περίπτωση δεν παίζει ρόλο, αλλά γενικά να μην χρησιμοποιείται μεταβλητή τύπου char στις συναρτήσεις που επιστρέφουν χαρακτήρα. Για το 1ο, ναι, έχεις δίκιο. Είναι όντως άσκοπη η κλήση της strlen, το i μέσα στο βρόχο δίνει την ίδια τιμή. Για το 2ο, δεν κατάλαβα που αναφέρεσαι ακριβώς.
imitheos Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Για το 2ο, δεν κατάλαβα που αναφέρεσαι ακριβώς. Εγκυκλοπαιδικά το ανέφερα. Στην συγκεκριμένη περίπτωση δεν παίζει ρόλο. Πχ όμως στις getc,fgetc αν η μεταβλητή είναι τύπου char μπορούν να δημιουργηθούν προβλήματα.
parsifal Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Α, λες για το implicit conversion από int σε char που γίνεται εδώ: > c = getchar(); Ναι, η getchar επιστρέφει int, σωστός και σε αυτό.
imitheos Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Α, λες για το implicit conversion από int σε char που γίνεται εδώ: > c = getchar(); Ναι, η getchar επιστρέφει int, σωστός και σε αυτό. Δεν πειράζει το conversion αυτό καθεαυτό αλλά υπό ορισμένες συνθήκες μπορεί να προκύψει overflow. Συχνά σε προγράμματα υπάρχει έλεγχος αν ισούται ο χαρακτήρας που επιστράφηκε με το EOF που σημαίνει ότι έγινε κάποιο σφάλμα. Συνήθως το EOF ορίζεται ως -1. Όταν ο τύπος της μεταβλητής είναι char, τότε αν διαβαστεί ο χαρακτήρας 255 (0xFF) αυτό θα μεταφραστεί σε -1 οπότε το σώμα του ελέγχου θα εκτελεστεί ενώ δεν υπήρχε λάθος. Με int δεν γίνεται αυτό γιατί το 255 και το -1 είναι διαφορετικές τιμές. Στην δική σου περίπτωση δεν υπάρχει πρόβλημα απλά το ανέφερα εγκυκλοπαιδικά για κάποιον που θα διαβάσει στο μέλλον το thread.
parsifal Δημοσ. 24 Ιουνίου 2010 Δημοσ. 24 Ιουνίου 2010 Κι όμως imitheos, το σχόλιό σου είναι εύστοχο και στην περίπτωση του κώδικα που παρέθεσα. Γιατί; Γιατί δεν υπάρχει εγγύηση ότι ο χρήστης π.χ. δε θα καλέσει το πρόγραμμα με piping/redirection εισόδου από έξοδο τρίτου προγράμματος ή από αρχείο. Οπότε εκεί θα υπάρξει πρόβλημα όταν στο αρχείο, πριν τον EOF χαρακτήρα, δεν υπάρχει newline character για να τερματιστεί σωστά η for. Λαμβάνοντας λοιπόν υπ' όψιν αυτό, ορίστε μία βελτιωμένη έκδοση: > #include <stdio.h> #include <string.h> int main(void) { char array[10] = ""; int i, c; printf("Please enter a string: "); for(i = 0; i < 9 && (c = getchar()) != '\n' && c != EOF;) { if(c >= '0' && c <= '9') continue; array[i] = c; i++; } array[i] = '\0'; printf("String = %s\n", array); printf("String length = %d\n", i); return 0; } Εκτός της μεταβλητής c που έγινε τύπου int, προστέθηκε έλεγχος και για EOF. Οπότε τώρα ο κώδικας θα λειτουργεί σωστά και με ανακατεύθυνση εισόδου από αρχείο. Π.χ.: a1b2c3d4e5f6g7 > C:\Users\parsifal>program.exe < input.txt Please enter a string: String = abcdefg String length = 7
johnykim Δημοσ. 25 Ιουνίου 2010 Μέλος Δημοσ. 25 Ιουνίου 2010 Παιδιά ευχαριστώ πολύ για τον χρόνο σας! Τα είδα,λειτουργούν! Κάποιες απορίες που έχω, θα σας πω αύριο.
johnykim Δημοσ. 25 Ιουνίου 2010 Μέλος Δημοσ. 25 Ιουνίου 2010 Καλημέρα Λοιπόν ,χθες το βράδυ μπερδευόμουν στον κώδικα του parsifal με τον μετρητή i και το πλήθος strlen(pinakas). Μετά κατάλαβα αυτό που είπε ο imitheos Μια απορία που έχω : Η "continue;" τι ακριβώς κάνει βρε παιδιά; Αφού έχουμε δώσει ήδη όλες τις τιμές της συμβολοσειράς(που μπορεί να είναι και αριθμοί) ,μετά η "continue;"(αν υπάρχει αριθμός)τον διαγράφει; Πως δεν υπολογίζεται στο πλήθος ο κάθε αριθμός με την "continue;" ; Μια αλλαγή που έκανα είναι "pinakas[10]='\0';" εκτός επανάληψης.Δεν είναι πιο βαρύς ο κώδικας να αντικαθιστά το " '\0'; " στην for κάθε φορά; @imithee, επικεντρώθηκα πιο πολύ στον κώδικα του parsifal , επειδη μου φάνηκε πιο εύκολος.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.