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

provlhma Turbo C...


PaniC_GR

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

Δημοσ.

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... :|

Δημοσ.

Καλησπέρα και χρόνια πολλά 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 σου δεν τα ανοίγεις ποτέ;

Δημοσ.

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...

Δημοσ.

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...

Δημοσ.
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...

 

Ααα καλά, άει πάμε.... ελληνική παιδεία.

Δημοσ.

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...

Δημοσ.

δεν έχω πρόβλημα με όποιον σε βοηθά, μπορεί να το έκανα και γω και να σου έστελνα βοήθεια. Απλά σχολιάζω το σλόγκαν σου : "τη δίνω και ότι κάτσει..."

Δημοσ.

Η λύση του 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 και πάνω».. οπότε αυτή η τακτική είναι μονόδρομος..

Δημοσ.

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 ;)

Δημοσ.

Καλησπέρα

 

Φίλε Panic ελπίζω να εκμεταλλεύτηκες δεόντως την παράταση.

Συγγνώμη για την καθυστερημένη απάντηση, αλλά μόλις (ξανα)βρήκα το thread με αναζήτηση, καθώς για κάποιο περίεργο λόγο δεν εμφανιζόταν στα ανανεωμένα από τον Πίνακα Ελέγχου.

 

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

Για τη σύνθετη μορφή της printf, θυμήσου λίγο τις εξηγήσεις για την αλλαγή γραμμής στην παλιά άσκηση με τον πίνακα. Θα μπορούσε να είναι πιό απλή, αν παραλείπαμε τους χαρακτήρες που δεν εμφανίζονται ποτέ, ώστε να ελπίζουμε ότι οι υπαρκτοί χαρακτήρες θα χωρέσουν σε μια οθόνη ο ένας κάτω από τον άλλο. Συμφωνώ κι εγώ με τον φίλο DirectX ότι η εμφάνισή τους είναι υπερβολή, όμως απ' ότι φαίνεται από το αρχικό σου μήνυμα είναι απαίτηση της εκφώνησης.

 

Η λύση του DirectX είναι περισσότερο προχωρημένη, αλλά σε συμβουλεύω να προσπαθήσεις να την καταλάβεις. Είναι εξαιρετική. Αν η υλοποίηση που δουλεύεις έχει κάποιο interactive help και μελετήσεις αυτές τις συναρτήσεις και όσες προτείνονται σαν παρόμοιες, θα έχεις κάνει ένα πολύ ουσιαστικό βήμα στην κατανόηση του πνεύματος της γλώσσας.

Παρότι ο φίλος DirectX προειδοποιεί (με υπερβολική μετριοφροσύνη) για την ύπαρξη bugs, δεν βλέπω να υπάρχει κάτι. Ισως μόνο κάποια σχολαστική υλοποίηση, να απαιτήσει και το stdio.h για τις βασικές συναρτήσεις I/O.

 

Το ΥΓ του DirectX, καλό θα είναι να διαβαστεί πολύ προσεκτικά. Οχι τόσο από τα μέλη αυτού του δικτυακού τόπου, αλλά κυρίως απ' όσους εμπλέκονται -με οποιοδήποτε τρόπο- σε εκπαιδευτικές διαδικασίες.

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

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