PaniC_GR Δημοσ. 8 Μαΐου 2005 Δημοσ. 8 Μαΐου 2005 kalhspera paidia k xronia polla se olous vasika thelw na postarw ena provlhma...askhsh...loipon... Να φτιάξετε ένα πρόγραμμα το οποίο θα «διαβάζει» από το πληκτρολόγιο μία μεγάλη πρόταση και θα βγάζει τα εξής στοιχεία: Α) Από πόσες λέξεις αποτελείται η πρόταση; (Σημείωση: Οι λέξεις διαχωρίζονται από ένα ή και περισσότερα κενά) Β) Ποιά είναι η μικρότερη και ποια η μεγαλύτερη λέξη σε πλήθος χαρακτήρων; Γ) Βγάλτε στατιστικά επί της χρήσης των χαρακτήρων με τη μορφή: Η πρόταση αποτελείται από: 4 - a 2 - b 0 - c ...... 1 - z Σημείωση: Το πρόγραμμα να επιλυθεί αυστηρά με χρήση δεικτών (pointers) paides den exw kanei tpt k den xerw an prolavainw na thn modarw toso oso enas expert ston programmatismo mia megalh help giati den exw kanei tpt...opia ethmi lush tha voithouse kyriolektika...thx se olous... :|
gerontas Δημοσ. 8 Μαΐου 2005 Δημοσ. 8 Μαΐου 2005 Καλησπέρα και χρόνια πολλά PaniC_GR. Από την άσκηση που ζητάς το πιό ζόρικο κομμάτι είναι το (Β). Για ν' απλοποιήσουμε το (Α) και το (Γ) ξεκινάμε μ' ένα κόλπο: Σβήνουμε τα (πιθανά) κενά της αρχής, και του τέλους και μετρέπουμε όποια ομάδα κενών υπάρχει σ' ένα μόνο κενό. Αυτό γίνεται αντίστοιχα με τις συναρτήσεις del_init_spaces, del_trail_spaces(char* s) και del_mid_spaces; Από κεί και πέρα ο αριθμός των λέξεων προκύπτει εύκολα σαν (Αρ.Κενών + 1). Στην πραγματικότητα η count_words μετράει κενά. Για το μέτρημα των χαρακτήρων (συνάρτηση count_chars) φτιάχνουμε ένα πίνακα 26 θέσεων. Με βάση το παράδειγμα που έδωσες, υποθέτω ότι εκτός από κενά, υπάρχουν μόνο λατινικά μικρά. Αν δεν έχω καταλάβει καλά, προφανώς πρέπει να αλλάξει η διάσταση του πίνακα και το if μέσα στη συνάρτηση. Ο υπολογισμός του μήκους είναι λίγο πιό δύσκολος, γι αυτό και φρόντισα να τον απομονώσω στις δυό τελευταίες συναρτήσεις: Αν δεν δουλέψει κι αν δεν προτείνει κάποιος άλλος κάτι ευκολώτερο, ας χαθεί μια ερώτηση κι όχι όλη η άσκηση 8) Αυτό που κάνει η special_words είναι να ξεκινάει απ' την αρχή του string ψάχνοντας για κενό. Μόλις το βρεί, καλεί την repl_words που απομονώνει τους χαρακτήρες σε μια λέξη (temp) ελέγχοντας το μήκος της. Αν πρέπει την αποθηκεύει σαν μικρότερη ή μεγαλύτερη, ορίζει νέα αρχή τον επόμενο χαρακτήρα από το κενό κ.ο.κ μέχρι το τέλος του string. Αυτός είναι ο κώδικας που έγραψα πρόχειρα: >#include <stdio.h> #include <conio.h> #include <string.h> #include <ctype.h> #include <alloc.h> #include <mem.h> #define N 100 void del_init_spaces(char* s); void del_trail_spaces(char* s); void del_mid_spaces(char* s); int count_words(char* s); void count_chars(char* s); void special_words(char* s); void repl_words(char* s,char* lw,char* sw,int* p,int* q); void main(void) { char s[N]; int i; clrscr(); printf("Input a string:"); gets(s); del_init_spaces(s); del_trail_spaces(s); del_mid_spaces(s); printf("Number of Words=%d\n",count_words(s)); count_chars(s); special_words(s); getch(); } void del_init_spaces(char* s) { char *t; for(t=s;*t==' ';t++); strcpy(s,t); } void del_trail_spaces(char* s) { char *t; int n=strlen(s); for(t=s+n-1;*t==' ';t--); *(t+1)='\0'; } void del_mid_spaces(char* s) { char *t,*u; for(t=s;*t!='\0';t++){ if (*t==' '){ for (u=t+1;*u==' ';u++); strcpy(t+1,u); } } } int count_words(char* s) { int n=0; char *t; for (t=s;*t!='\0';t++) if (*t==' ') n++; return n+1; } void count_chars(char* s) { unsigned m[26]; char *c,i; for (i=0;i<26;i++) m[i]=0; for (c=s;*c;c++){ if (islower(*c)) m[*c-'a']++; } printf("\nSYXNOTHTA XARAKTHRWN\n"); for (i=0;i<26;i++) printf("%5c_%3u%c",(char)(i+'a'),m[i],((i+1)%6?'\0':'\n')); printf("\n"); } void special_words(char* s) { int arxh=0,telos=0,mhkos; char *sw,*lw,*c,*temp; sw = (char *) malloc(strlen(s)); lw = (char *) malloc(strlen(s)); strcpy(sw,s); strcpy(lw,""); for (c=s;*c;c++){ if (*c!=' ') telos++; else repl_words(s,lw,sw,&arxh,&telos); } repl_words(s,lw,sw,&arxh,&telos); printf("\nMEGALYTERH LEXH:%s, MHKOS=%d\n",lw,strlen(lw)); printf("MIKROTERH LEXH:%s, MHKOS=%d\n",sw,strlen(sw)); } void repl_words(char* s,char* lw,char* sw,int* p,int* q) { int mhkos; char *temp; mhkos=*q-*p; temp = (char *) malloc(mhkos+1); movmem(s+(*p), temp, mhkos); *(temp+mhkos)='\0'; if (strlen(temp)<strlen(sw)) strcpy(sw,temp); if (strlen(temp)>strlen(lw)) strcpy(lw,temp); free(temp); (*q)++; *p=*q; } Εννοείται ότι οι ερωτήσεις είναι ευπρόσδεκτες. ΥΓ: Τα pm σου δεν τα ανοίγεις ποτέ;
PaniC_GR Δημοσ. 9 Μαΐου 2005 Μέλος Δημοσ. 9 Μαΐου 2005 ella file mou gerontas vasika den mporw na ta dokimasw ola ayta...etimh tha tin eperna tin askhsh k tha tin edina k oti katsei swsta... aplos na rwthsw na mou exigiseis ligo tis vivliothikes pou perneis #include <ctype.h> #include <alloc.h> #include <mem.h> gia na poume giati tis valame... to pm to eida file thx k pali alla hmoun ektos...
PaniC_GR Δημοσ. 9 Μαΐου 2005 Μέλος Δημοσ. 9 Μαΐου 2005 akoma mia mikrh exigisei gia tin printf... printf("%5c_%3u%c",(char)(i+'a'),m,((i+1)%6?'\0':'\n')); kapws pio apla i pio aplh printf den yparxei??? akoma gia... movmem k malloc...ti akrivos kanoun gerontas k an xrisimopioude me vash tis vivliothikes???...ayta paides,gerontas den tha exw tin dinatothta na xanakanw post mono tis apadiseis mporw na dw...thx man gia allh mia fora...thx...
hayzel Δημοσ. 9 Μαΐου 2005 Δημοσ. 9 Μαΐου 2005 ella file mou gerontas vasika den mporw na ta dokimasw ola ayta...etimh tha tin eperna tin askhsh k tha tin edina k oti katsei swsta... Ααα καλά, άει πάμε.... ελληνική παιδεία.
PaniC_GR Δημοσ. 9 Μαΐου 2005 Μέλος Δημοσ. 9 Μαΐου 2005 kamia fora file hayzel den prepei na krinoume xwris na exoume gnwsh twn katastasewn...to tha "etimh tha tin eperna k tha tin edina ..." paei sto oti den exw thn eikanothta aytes tis stigmes gia dokimes k giafto zhtisa exarxhs thn katalilh vohtheia...sigoura poloi den goustaroun na dinoun teties vohthies alla ti na kanw afou eiparxei kapia anagh...opios thelisei einai to thema...
hayzel Δημοσ. 9 Μαΐου 2005 Δημοσ. 9 Μαΐου 2005 δεν έχω πρόβλημα με όποιον σε βοηθά, μπορεί να το έκανα και γω και να σου έστελνα βοήθεια. Απλά σχολιάζω το σλόγκαν σου : "τη δίνω και ότι κάτσει..."
PaniC_GR Δημοσ. 9 Μαΐου 2005 Μέλος Δημοσ. 9 Μαΐου 2005 kalos man...k egw den eipa tpt aplos ekatse ayth thn fora na mhn mporw na kanw kati... thx gerontas...
Directx Δημοσ. 10 Μαΐου 2005 Δημοσ. 10 Μαΐου 2005 Η λύση του Gerontas θεωρώ πως θα κάνει τον καθηγητή σου ευτυχισμένο καθώς χρησιμοποιεί αυστηρά pointers σε αντίθεση με την δικιά μου που χρησιμοποιεί pointers και συνηθισμένες C ρουτίνες διαχείρισης τους. Παρ’ όλα αυτά θεώρησα πως έχει ενδιαφέρον οπότε την παραθέτω (δίχως περαιτέρω ανάλυση) προς κάθε ενδιαφερόμενο. > // CountPhrases (c) DIRECTX #include <stdio.h> #include <string.h> #include <alloc.h> #include <stdlib.h> #include <conio.h> #define _MAXIMUM_INPUT 513 #define _LARGE_WORD 0 #define _SMALL_WORD 1 #undef _DEBUG_DATABASE_DATA typedef struct { char *pszAddress; long lLength; }WordRecord; int nCharToCheck; char *pszUserInputBuffer = NULL, *pszToken = NULL, *pDatabase = NULL; long lWordCount = 0, lDatabaseOffset = 0; long _InsertWord (char *pszWord,long lDatabaseOffset); void _PrintDatabase (void); void _PrintSmallLargeWord (int nSwitch); void _PrintStatistics (int nCharacterToCheckFor); int _MyCompareFunction (const void *pRecord_A, const void *pRecord_; void main() { // Allocate User Input Buffer if((pszUserInputBuffer=(char*)malloc(_MAXIMUM_INPUT))==NULL) { printf(" System Error: Not enough memory to hold User input buffer!!\n"); return; } // Clean up User Input Buffer memset(pszUserInputBuffer,0,_MAXIMUM_INPUT); // Read User Input (Maximum Input 512 Bytes!!) printf(" Input:"); gets(pszUserInputBuffer); // User Input Check (Quit on nothing); if(!strlen(pszUserInputBuffer)) { printf(" Info: Nothing typed!\n"); free(pszUserInputBuffer); return; } // Word Count (Each word gets separated by spaces) if((pszToken=strtok(pszUserInputBuffer," "))!=NULL) { do{ ++lWordCount; // Insert current word into our Words (p)Database lDatabaseOffset = _InsertWord(pszToken,lDatabaseOffset); // Print each found word //printf(" %ld] %s\n",lWordCount,pszToken); }while((pszToken=strtok(NULL," "))!=NULL); #ifdef _DEBUG_DATABASE_DATA // For debugging purposes, dump pDatabase records.. _PrintDatabase(); #endif // Print found words printf("\n Words Found: %ld\n",lWordCount); /* Sort pDatabase structures & print largest/smaller word only if we got more than 1 words else it's pointless! */ if(lWordCount>1) { // Sort pDatabase records to find the largest and smaller words.. qsort(pDatabase,lDatabaseOffset/sizeof(WordRecord),sizeof(WordRecord), _MyCompareFunction); // Print the largest and smaller word.. _PrintSmallLargeWord(_LARGE_WORD); _PrintSmallLargeWord(_SMALL_WORD); } /* Get characters statistics */ for(nCharToCheck=33;nCharToCheck<=127;nCharToCheck++) { _PrintStatistics(nCharToCheck); } } // Free used memory! if(pDatabase!=NULL ){ free(pDatabase); } if(pszUserInputBuffer!=NULL){ free(pszUserInputBuffer); } getch(); } long _InsertWord(char *pszWord,long lDatabaseOffset) { WordRecord *pRecord; /* Allocate or re-allocate (expand) pDatabase memory length to hold a new WordRecord struct (considerate as our database field). */ if((pDatabase=(char*)realloc(pDatabase,lDatabaseOffset+sizeof(WordRecord)))==NULL) { printf(" System Error: Not enough memory to hold a new WordRecord!!\n"); return 0; } // Create in-memory a new *pRecord struct if((pRecord=(WordRecord*)malloc(sizeof(WordRecord)))==NULL) { free(pDatabase); return -1L; } /* Clean-up newly created pRecord struct and utilize it with current data Detail: We do not copy appart from the word length the entire word string but a reference to it's begining address within the pszUserInputBuffer. */ memset(pRecord,0,sizeof(WordRecord)); pRecord->pszAddress = pszWord; pRecord->lLength = strlen(pszWord); // Copy pRecord struct into in-memory pDatabase struct memcpy(&pDatabase[lDatabaseOffset],pRecord,sizeof(WordRecord)); // Free pRecord struct.. free(pRecord); pRecord = NULL; return lDatabaseOffset+=sizeof(WordRecord); } #ifdef _DEBUG_DATABASE_DATA void _PrintDatabase(void) { long lRecordIndex; WordRecord *pRecord = NULL; for(lRecordIndex=0;lRecordIndex!=lDatabaseOffset;lRecordIndex+=sizeof(WordRecord)) { pRecord = &pDatabase[lRecordIndex]; printf("%.2ld] ADDRESS = %p\n",1+(lRecordIndex/sizeof(WordRecord)),pRecord->pszAddress); printf(" LENGTH = %d\n",pRecord->lLength); } } #endif int _MyCompareFunction (const void *pRecord_A, const void *pRecord_ { // Our simple compare function for the C qsort (nothing special) int nCompare = 0; // Cast const void* [aka. anything] to WordRecord C struct WordRecord *pWordRecord_A = (WordRecord*)pRecord_A, *pWordRecord_B = (WordRecord*)pRecord_B; if(pWordRecord_A->lLength>pWordRecord_B->lLength){ nCompare = -1; } if(pWordRecord_A->lLength<pWordRecord_B->lLength){ nCompare = 1; } return nCompare; } void _PrintSmallLargeWord (int nSwitch) { /* If nSwitch is zero print the first (largest) Record of pDatabase else the last (smaller) one. */ WordRecord *pRecord; char *pszWord = NULL; if(!nSwitch) { pRecord = (WordRecord*)&pDatabase[0]; } else { pRecord = (WordRecord*)&pDatabase[lDatabaseOffset-sizeof(WordRecord)]; } /* Allocate a large enough buffet to hold pRecord->lLength word */ if((pszWord=(char*)malloc(pRecord->lLength+1))==NULL) { printf(" System Error: Not enough memory to store pszWord buffer!!\n"); return; } // Copy pRecord->pszAddress into pszWord buffer memset(pszWord,0,pRecord->lLength+1); memcpy(pszWord,pRecord->pszAddress,pRecord->lLength); // Print it on screen printf("%s word: %s (Length: %ld)\n",(!nSwitch)?"Largest":"Smaller", pszWord,pRecord->lLength); // Free pszWord buffer free(pszWord); } void _PrintStatistics (int nCharacterToCheckFor) { /* Print if exists the number of nCharacterToCheckFor occurances within pszUserInputBuffer. */ long lCharIndex, lCharsFound = 0; char *pszCharacter; for(lCharIndex=0;lCharIndex!=_MAXIMUM_INPUT;lCharIndex++) { if(pszUserInputBuffer[lCharIndex]==nCharacterToCheckFor) { lCharsFound++; } } // Do not print anything if lCharsFound is zero!! if(lCharsFound>0) { printf(" %ld - '%c'\n",lCharsFound,nCharacterToCheckFor); } } Δομή: 1.Δεσμεύουμε με την βοήθεια της malloc ως Input buffer 512 bytes (pszUserInputBuffer) 2.Λαμβάνουμε την είσοδο του χρήστη με την gets 3.Εαν το μέγεθος του pszUserInputBuffer είναι ίσο με μηδέν διακόπτουμε 4.Διαφορετικά βρίσκουμε κάθε *λέξη του pszUserInputBuffer χρησιμοποιώντας δυο κλήσεις στην strtok ενώ με την βοήθεια της _InsertWord την αποθηκεύουμε στην μνήμη του υπολογιστή (pDatabase). Η πρώτη κλήση strtok επιστρέφει την πρώτη λέξη του pszUserInputBuffer, ενώ οι επόμενες τις επόμενες λέξεις κ.ο.κ. ως ότου λάβουμε NULL. Για κάθε λέξη που βρίσκουμε αυξάνουμε το lWordCount. 5. Εάν έχουμε βρει περισσότερες από 1 λέξεις στο lWordCount τότε καλούμε την C ρουτίνα qsort η οποία ταξινομεί με γνώμονα την ρουτίνα μας _MyCompareFunction τις αποθηκευμένες στο pDatabase λέξεις. Ύστερα με την ρουτίνα _PrintSmallLargeWord τυπώνουμε στην οθόνη την Μεγαλύτερη & Μικρότερη λέξη. 6.Τέλος με την _PrintStatistics ελέγχουμε για την εμφάνιση κάθε χαρακτήρα από το βασικό ASCII SET ξεκινώντας από το 33 (!) ως το 127 (Δ) ASCII character, δλδ. Ολόκληρο το Λατινικό Αλφάβητο + αρκετούς ειδικούς χαρακτήρες. * = Ως λέξη αναγνωρίζω κάθε χαρακτήρα που υπάρχει μεταξύ διαστήματος, δεν θεωρώ ότι είναι δύσκολο να το αλλάξει κανείς (απλά ας ελέγξουμε το μέγεθος του pszToken για >1). Λεπτομέρειες: 1.Η _InsertWord λειτουργεί συνδυάζοντας τα α)pDatabase και β) τον δικό μας τύπο typedef struct WordRecord. Με δυο λόγια μεγαλώνει (realloc) το μέγεθος του pDatabase ώστε να χωρά ένα ακόμα WordRecord διατηρώντας παράλληλα τα υπάρχοντα στοιχεία. Το WordRecord περιέχει το μέγεθος της λέξης και την θέση (διεύθυνση) κάθε λέξης στο pszUserInputBuffer. Το lDatabaseOffset ουσιαστικά περιέχει το πραγματικό μέγεθος του pDatabase. Σκεφθείτε κάθε WordRecord που προσθέτει η _InsertWord ως Record (πεδίο) στην pDatabase.. 2.Η _MyCompareFunction είναι μια τυπική qsort compare ρουτίνα, με την διαφορά ότι κάνει cast το const void pointer σε WordRecord* pointers για να επιτευχθεί η δυνατότητα σύγκρισης βάση του lLength member. 3.Η _PrintSmallLargeWord απλά παρουσιάζει το πρώτο (μεγαλύτερη λέξη κατά qsort) ή το τελευταίο (μικρότερη λέξη ομοίος) WordRecord του pDatabase buffer. 4.Η _PrintStatistics ψάχνει συνολικά το pszUserInputBuffer για τον χαρακτήρα nCharacterToCheckFor, εάν δεν τον βρει κατά την γνώμη μου είναι λογικό να μην τον παρουσιάζει καθόλου (πχ. 0 - c) αν κάτι τέτοιο όμως δεν είναι επιθυμητό απλά αφαιρούμαι την συνθήκη «if(lCharsFound>0)»… Όπως πάντα ο κώδικας έχει αναπτυχθεί σε Borland C/C++ Builder, τα σχόλια είναι αγγλικά (καθώς διατηρώ προσωπικό web-archive όλων των listings που σχεδιάζω και δημοσιεύω) και φυσικά συνιστώ προσοχή διότι μπορεί να υπάρχουν bugs!! Καλή τύχη!! Υ.Γ. Η έννοια που έχουν οι ασκήσεις είναι να φέρουν σε επαφή τον φοιτητή ή την φοιτήτρια (political correct) με το αντικείμενο οπότε ειλικρινά δεν πριμοδοτώ την επίλυση τους από άλλους -από την άλλη πλευρά όμως λόγο της εμπειρίας μου ως πτυχιούχου Κλασσικού ΑΕΙ (δυστυχώς δεν είχα την τύχη να σπουδάσω προγραμματισμό )- μου είχε τύχει να δω καθηγητές που ..απλά δεν.. κάνουν ..την δουλεία τους.. (το λειτούργημα τους κατά την γνώμη μου).. αφήνοντας τους φοιτητές τους στο «έλεος του Θεού» έχοντας όμως απαιτήσεις.. «Cambridge και πάνω».. οπότε αυτή η τακτική είναι μονόδρομος..
PaniC_GR Δημοσ. 15 Μαΐου 2005 Μέλος Δημοσ. 15 Μαΐου 2005 file directx exeis dikio gia to Y.G. loipon telika dothike paratash sthn parousiasi tou probl opote exw twra ton xrono na to meletisw pados thx k apo esena gia thn dikia sou lush na ste kala paides giati pou k pou xriazodai teties vohthies,sigoura o provlhmatismos einai dikos mou twra...thx
gerontas Δημοσ. 22 Μαΐου 2005 Δημοσ. 22 Μαΐου 2005 Καλησπέρα Φίλε Panic ελπίζω να εκμεταλλεύτηκες δεόντως την παράταση. Συγγνώμη για την καθυστερημένη απάντηση, αλλά μόλις (ξανα)βρήκα το thread με αναζήτηση, καθώς για κάποιο περίεργο λόγο δεν εμφανιζόταν στα ανανεωμένα από τον Πίνακα Ελέγχου. Τα αρχεία που αναφέρεις χρησιμοποιούνται για να δηλωθούν κάποιες από τις συναρτήσεις που χρησιμοποιούνται παρακάτω, που φρόντισα να είναι οι ελάχιστες δυνατές. Αν για κάποια εξακολουθείς να έχεις απορίες, μην διστάσεις να επανέλθεις. Για τη σύνθετη μορφή της printf, θυμήσου λίγο τις εξηγήσεις για την αλλαγή γραμμής στην παλιά άσκηση με τον πίνακα. Θα μπορούσε να είναι πιό απλή, αν παραλείπαμε τους χαρακτήρες που δεν εμφανίζονται ποτέ, ώστε να ελπίζουμε ότι οι υπαρκτοί χαρακτήρες θα χωρέσουν σε μια οθόνη ο ένας κάτω από τον άλλο. Συμφωνώ κι εγώ με τον φίλο DirectX ότι η εμφάνισή τους είναι υπερβολή, όμως απ' ότι φαίνεται από το αρχικό σου μήνυμα είναι απαίτηση της εκφώνησης. Η λύση του DirectX είναι περισσότερο προχωρημένη, αλλά σε συμβουλεύω να προσπαθήσεις να την καταλάβεις. Είναι εξαιρετική. Αν η υλοποίηση που δουλεύεις έχει κάποιο interactive help και μελετήσεις αυτές τις συναρτήσεις και όσες προτείνονται σαν παρόμοιες, θα έχεις κάνει ένα πολύ ουσιαστικό βήμα στην κατανόηση του πνεύματος της γλώσσας. Παρότι ο φίλος DirectX προειδοποιεί (με υπερβολική μετριοφροσύνη) για την ύπαρξη bugs, δεν βλέπω να υπάρχει κάτι. Ισως μόνο κάποια σχολαστική υλοποίηση, να απαιτήσει και το stdio.h για τις βασικές συναρτήσεις I/O. Το ΥΓ του DirectX, καλό θα είναι να διαβαστεί πολύ προσεκτικά. Οχι τόσο από τα μέλη αυτού του δικτυακού τόπου, αλλά κυρίως απ' όσους εμπλέκονται -με οποιοδήποτε τρόπο- σε εκπαιδευτικές διαδικασίες.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.