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

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

Δημοσ.

imitheos

Προσωπικά μου αρέσει πολύ το Allman αλλά με το else να είναι στην ίδια γραμμή με το closing bracket του if και το δικό του opening, π.χ.

 

>
if ( checkSomething )
{
 doThis;
} else {
 doThat;
}

 

Ο λόγος είναι ότι με βολεύει να αλλάζω if's ή να απενεργοποιώ if's (όταν δεν έχουν else) βάζοντας μόνο σχόλια στην γραμμή του if...

 

@migf1

goto ? Είδα κάπου goto? :P

 

Καλό υπόλοιπο καλοκαιριού!

 

Υ.Γ. Το space στο indentation ήταν 2 κενά...

  • Απαντ. 1,6k
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοσ.

 

Διαβάζοντας τον κώδικα στα γρήγορα βλέπω ότι μετράς την εμφάνιση των γραμμάτων ως char, πράγμα που περιορίζει την ακρίβεια σου στους 127 χαρακτήρες, θα μπορούσες να προτιμήσεις το int αντί του char ώστε να αυξήσεις το εύρος των τιμών σου.

Ευχαριστω. Αν ο χρήστης δωσει τον ιδιο χαρακτηρα 128 φορες μεσα στην προταση (πραγμα σπανιο βεβαια)

θα κρασαρει το προγραμμα. Το σκεφτηκα και εγω αυτο με τον εναν πινακα να γινει int

κατι δεν μου κολλαγε καλα.

 

Κακώς δεν σου κόλλαγε καλά :)

 

Παλαιότερα σε DOS αν εξαιρέσουμε XMS,EMS,κτλ μπορούσες να δεις 640Κ μνήμης. Από αυτά αφαιρούσες τη μνήμη που έπιαναν highmem,emm386,mscdex,mouse,κτλ οπότε πρακτικά είχες γύρω στα 560Κ διαθέσιμα. Όσοι ήξεραν να παίξουν με τα αρχεία εκκίνησης έβαζαν όλα τα παραπάνω να φορτώνονται στην "High" περιοχή οπότε ελευθέρωναν χαμηλή μνήμη και μπορούσες να έχεις περίπου 624Κ ελεύθερα από τα 640Κ. Γενικά όμως σκέψου ότι είχες το πολύ 560Κ σε segments των 64Κ στη διάθεσή σου. Για αυτό το λόγο κοινή πρακτική ήταν να χρησιμοποιείται ο μικρότερος τύπος που σε καλύπτει. Και σήμερα μπορείς να έχεις πχ 16Κ μνήμη αν προγραμματίζεις για κάποιο embedded σύστημα αλλά τότε γνωρίζεις τα ιδιαίτερα χαρακτηριστικά της πλατφόρμας και θα πάρεις ανάλογες αποφάσεις.

 

Στις δικές μας πλατφόρμες η σύμβαση που προτείνει πολύς κόσμος είναι η παρακάτω.

 

Σε ενδιαφέρει κάποιο συγκεκριμένο εύρος ? Τότε χρησιμοποίησε τον ανάλογο τύπο όπως πχ uint32_t. Οποτεδήποτε δεν σε ενδιαφέρει το εύρος χρησιμοποίησε int.

 

Και ένα loop counter που πάει από το 1 μέχρι να το 10 να έχεις, use int :P

 

imitheos

Προσωπικά μου αρέσει πολύ το Allman αλλά με το else να είναι στην ίδια γραμμή με το closing bracket του if και το δικό του opening, π.χ.

 

Ο λόγος είναι ότι με βολεύει να αλλάζω if's ή να απενεργοποιώ if's (όταν δεν έχουν else) βάζοντας μόνο σχόλια στην γραμμή του if...

 

Αυτό αναφέρει και το άρθρο στο wikipedia ως πλεονέκτημα. Πλέον δεν μας νοιάζει ο χώρος που χαραμίζεται λόγω των παραπανίσιων LF (ή CR/LF) οπότε το Allman θεωρείται από τα καλύτερα ειδικά για αρχάριους (οι περισσότεροι φοιτητές που είχα ρωτήσει έβρισκαν πιο δύσκολη την ανάγνωση κώδικα με K&R και προτιμούσαν Allman).

 

Εγώ χρησιμοποιώ K&R με 8άρια tabs αλλά και το Allman μαρέσει. Whitesmith, Gnu και τα υπόλοιπα δεν τα μπορώ :P

 

Υ.Γ. Το space στο indentation ήταν 2 κενά...

 

Διαπίστωσα χτες κατά τύχη αυτό που είπε ο DirectX ότι αν κατεβάσεις το διακόπτη, τότε δεν χαλάει η στοίχιση. Τουλάχιστον μέχρι τώρα δηλαδή δεν μου έχει χαλάσει.

Δημοσ.

Ναι (για μένα!) γιατί πρέπει πρώτα να ελέγξεις αν υπάρχει χώρος για store μέσα στον πίνακα σου. Αν αποτύχει να μην συνεχίσει να διαβάζει τον επόμενο χαρακτήρα. Έχω μια υποψία οτι εκείνο το 100, πρέπει να γίνει 99 αλλά δεν είμαι σίγουρος. :unsure:

 

Oχι δεν εχει σημασια μιας και χρησιμοποιειται ο τελεστης && . Δεν γινεται τιποτα αν δεν δωσουν και οι 2 πλευρες αληθες. Αρα ειτε αριστερα το πας ειτε δεξια αν ειναι FALSE ενας απο τους 2 τελεστέους θα σταματησει εκει και δεν θα μπει καθολου στο σωμα του βροχου. Το 100 καλως ειναι επειδη η αριθμιση ξεκινα απο το 0 και πάει ως το 100.... ( i < 100 ) το 100 δεν ειναι μικροτερο του 100 αρα θα δωσει FALSE αρα δεν θα έχεις overflow. Απο 0....99 θα εισαι σε καθε περιπτωση. Γενικα σε τετοιες περιπτώσεις μπορεις να χρησιμοποιήσεις ειτε i=0 .... i < n ειτε i=1 ...i <= n-1 οποτε θα παει απο 1 έως 100 .

 

Tωρα ειναι εντάξει ? Χρησιμοποιω K&R μιας και δεν βαζω καθολου braces σε single statements μεσα σε σωματα της if κτλπ ... ηταν δηλαδη και ενα τριτο στυλ αναμεικτο imithee :P

 

http://ideone.com/GPKK1

 

Τις δηλωσεις των τοπικων μεταβλητων μεσα στην συναρτηση να τις εχω στο ιδιο level με τα loops απο κατω ????

 

Για την συναρτηση input_process δεν μου ειπες πως σου φαινεται... παραγεμισμενη? Κανει παραπανω πραγματα απο οσα χρειαζεται ?

 

p.s Παντως και εγω σε μερικους κωδικες ειδα οτι πχ

 

http://ideone.com/3vW4T

 

Αυτο συμφωνα με αυτο που έγραψες δεν ειναι σωστο γιατι το { κατω απο την for δεν ειναι K&R style αλλα Allman . Ετσι δεν ειναι?

Δημοσ.

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

 

Η πιο γρήγορη λύση είναι να δηλώσεις μέσα στη for τους πίνακες,αφού έτσι κι αλλιώς εκεί έχουν μόνο εμβέλεια και να πετάξεις έξω το memset!

 

ή να βάλεις αυτό memset(check_letters , 0 , ALPH_LEN*sizeof(int)); αν θες οι πίνακες σου να έχουν εμβέλεια σε όλη την main.

 

Oχι δεν εχει σημασια μιας και χρησιμοποιειται ο τελεστης && . Δεν γινεται τιποτα αν δεν δωσουν και οι 2 πλευρες αληθες. Αρα ειτε αριστερα το πας ειτε δεξια αν ειναι FALSE ενας απο τους 2 τελεστέους θα σταματησει εκει και δεν θα μπει καθολου στο σωμα του βροχου. Το 100 καλως ειναι επειδη η αριθμιση ξεκινα απο το 0 και πάει ως το 100.... ( i < 100 ) το 100 δεν ειναι μικροτερο του 100 αρα θα δωσει FALSE αρα δεν θα έχεις overflow. Απο 0....99 θα εισαι σε καθε περιπτωση. Γενικα σε τετοιες περιπτώσεις μπορεις να χρησιμοποιήσεις ειτε i=0 .... i < n ειτε i=1 ...i <= n-1 οποτε θα παει απο 1 έως 100 .

Σε είπα για μένα :). Θα προτιμούσα να μου έβγαζε πρώτα FALSE από το μέγεθος και μετά απο το storing.Επίσης επιμένω στο ALPH_LEN-1. Αλλά αφού κάνεις μετά memset, το καθαρίζεις.

Δημοσ.

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

 

Η πιο γρήγορη λύση είναι να δηλώσεις μέσα στη for τους πίνακες,αφού έτσι κι αλλιώς εκεί έχουν μόνο εμβέλεια και να πετάξεις έξω το memset!

 

ή να βάλεις αυτό memset(check_letters , 0 , ALPH_LEN*sizeof(int)); αν θες οι πίνακες σου να έχουν εμβέλεια σε όλη την main.

 

 

Σε είπα για μένα θα ήταν προτιμότερο να ελέγξει πρώτα το μέγεθος και μετά να κάνω store.

 

Ναι αλλα αμα βαλω τις δηλωσεις μεσα στην for(; ; ) σε κάθε loop θα εκτελουνται και αυτες :-S , θα καταργουνται μολις τελειωνει το μπλοκ τους και μετα ξανα τα ιδια .

στο μεταξυ εχεις απολυτο δικιο.... δεν εκανα χθες βραδυ ολα τα test εισοδου ξανα στο πορογραμμα :-/ κατι πρεπει να γινεται σε κάθε αλλαγη για να βλεπεις αν ολα δουλευουν οπως τα θες.

 

Ειχα μεινει με την εντύπωση οτι ο πινακας ειναι char :D αλλα το μεγεθος ειναι 104 bytes οποτε η memset πρεπει να γεμισει ολο αυτο το size. Βεβαια να πουμε οτι μονο για το 0 σε int μπορεις να την χρησιμοποιησεις οπως βλεπω εδω γιατι αν πηγαιναμε να γεμισουμε με μια τιμη πχ 10 δεν θα ηταν αποτελεσματικο.

 

Απλα χθες βραδυ επειδη ημουν κουρασμενος δεν τσεκαρισα οτι ο τυπος στην τεκμηριωση της συναρτησης ηταν char... Αρα 6 * 1 = 6 bytes εφοσον char = 1 byte. Και απλα γεμιζε με τον '-' τις θέσεις.

  • Like 1
Δημοσ. (επεξεργασμένο)

>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int main(void)
{
   char s[150]; 
   int hist[26] = { 0 };
   int len;
   int i;

   printf("Dose protash gia analush:\n");
   fgets(s, 150, stdin);
   len = strlen(s);
   if (s[len - 1] == '\n')
       s[len - 1] = 0;

   for (i = 0; i < len; i++)
       if (isalpha(s[i]))
           hist[tolower(s[i]) - 'a']++;

   for (i = 0; i < 26; i++)
       if (hist[i] > 1)
           printf("To '%c' emfanisthke %3d fores\n", 'a' + i, hist[i]);

   return 0;
}

 

Μια απλή έκδοση χωρίς καν να χρειάζεται συναρτήσεις θα μπορούσε να ήταν η παραπάνω. Επίσης δεν αποθηκεύω σε 2ο πίνακα τα γράμματα μια και αυτά μπορούν εύκολα να υπολογιστούν από την θέση του ιστογράμματος.

Επεξ/σία από imitheos
  • Like 1
Δημοσ.

Ναι έχεις δικιο σε αυτο..... βλεπω εδω οτι και στην δικη μου υλοποιηση ο 2ος πίνακας ειναι περιττός. Αν βάλω μεσα στην printf

το 'α' + i που βάζεις !!!! Για μενα και οι 2 υλοποιησεις ειναι ενταξει γιατι και 2ο πινακα να χρησιμοποιησεις απο chars αυτος πιανει μονο 26 bytes .

 

Ο δικος σου κωδικας ομως κρασάρει για input > 150 chars.

Δημοσ.

Ο δικος σου κωδικας ομως κρασάρει για input > 150 chars.

 

Η fgets δεν συμπεριφέρεται όπως η gets. Όπως βλέπεις δέχεται μέγεθος και διαβάσει μόνο όσο της λες. Με λίγα λόγια θα αγνοήσει ό,τι δώσεις από τον 150 χαρακτήρα και πέρα αλλά δεν θα κρασάρει.

Δημοσ.

Η fgets δεν συμπεριφέρεται όπως η gets. Όπως βλέπεις δέχεται μέγεθος και διαβάσει μόνο όσο της λες. Με λίγα λόγια θα αγνοήσει ό,τι δώσεις από τον 150 χαρακτήρα και πέρα αλλά δεν θα κρασάρει.

 

Aυτο εννοω... δεν θα κανει την δουλεια που θελεις το προγραμμα.

Γιατι αν έβαζες ενα μηνυμα "Δεν βρεθηκε διπλη εμφανιση γραμματος" μετα την if

θα σου εκτυπωνε αυτο ενω εσυ ειχες δωσει τον 'Κ' 151 φορες.

 

Δεν κρασαρει η συναρτηση... ολοκληρο το προγραμμα ετσι οπως το εχεις φτιαξει

λογω αυτης της συναρτησης θα δωσει λαθος αποτελεσμα. Τελοςπαντων ωραιο το κολπακι

μεσα στην printf. ;D

 

Οποτε ολοκληρωμενα θα έχουμε κατι τέτοιο :

 

http://ideone.com/j33N3

 

κουκλι... κουκλι :P

Δημοσ.

Aυτο εννοω... δεν θα κανει την δουλεια που θελεις το προγραμμα.

Γιατι αν έβαζες ενα μηνυμα "Δεν βρεθηκε διπλη εμφανιση γραμματος" μετα την if

θα σου εκτυπωνε αυτο ενω εσυ ειχες δωσει τον 'Κ' 151 φορες.

 

>
% python -c "print 'k' * 160" | ./a.out
Dose protash gia analush:
To 'k' emfanisthke 149 fores

 

Μια χαρά δουλεύει η fgets και διαβάζει 149 'κ' + το μηδέν. Όταν το ιστόγραμμά σου είναι char και δώσεις 151 φορές (ή και 128 φορές) ένα χαρακτήρα φυσικά δεν θα παίξει σωστά επειδή το συχνότερο είναι ο σκέτος char να υλοποιείται ως signed char οπότε το > 1 που ελέγχει το if δεν ισχύει.

 

Αν δουλεύεις με unsigned char ή καλύτερα int, τότε θα εμφανίσει κανονικά 149.

Δημοσ.

>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int main(void)
{
char s[150];
int hist[26] = { 0 };
int len;
int i;

printf("Dose protash gia analush:\n");
fgets(s, 150, stdin);
len = strlen(s);
if (s[len - 1] == '\n')
s[len - 1] = 0;

for (i = 0; i < len; i++)
if (isalpha(s[i]))
hist[tolower(s[i]) - 'a']++;

for (i = 0; i < 26; i++)
if (hist[i] > 1)
printf("To '%c' emfanisthke %3d fores\n", 'a' + i, hist[i]);

return 0;
}

 

Μια απλή έκδοση χωρίς καν να χρειάζεται συναρτήσεις θα μπορούσε να ήταν η παραπάνω. Επίσης δεν αποθηκεύω σε 2ο πίνακα τα γράμματα μια και αυτά μπορούν εύκολα να υπολογιστούν από την θέση του ιστογράμματος.

 

Στο if μέσα στο τελευταίο for θες >= 1, μιας και η αρχικοποίηση είναι στο 0, ή πιο απλά

 

>
if (hist[i])

Δημοσ.

 

 

Στο if μέσα στο τελευταίο for θες >= 1, μιας και η αρχικοποίηση είναι στο 0, ή πιο απλά

 

>
if (hist[i])

 

Προσπάθησα να αντιγράψω τη λειτουργία του προγράμματος του starlight που εμφάνιζε μόνο όσα γράμματα εμφανίζονται πάνω από μία φορά. Αν θέλεις να εμφανίζεται η συχνότητα όλων των γραμμάτων της πρότασης, τότε έχεις δίκιο ότι πρέπει να γίνει >= 1

Δημοσ.

Προσπάθησα να αντιγράψω τη λειτουργία του προγράμματος του starlight που εμφάνιζε μόνο όσα γράμματα εμφανίζονται πάνω από μία φορά. Αν θέλεις να εμφανίζεται η συχνότητα όλων των γραμμάτων της πρότασης, τότε έχεις δίκιο ότι πρέπει να γίνει >= 1

 

Ναι βασικα αυτο που λες ειναι η φιλοσοφια του προγραμματος.

Αν ενα γραμμα εμφανιζεται μια φορα δεν με ενδιαφερει να το εμφανισω.

Αλλιως πειραζετε την συνθηκη μεσα στο if... καντε οτι θέλετε εγω έδωσα τον κώδικα

και για διορθωση μιας και οσα περισσοτερα ματια τον βλεπουν τοσο το καλυτερο αλλα και γιατι οχι και σαν budget αμα τον χρειαστει κανεις για καμια ασκηση στην σχολη του

τετοιες βαζουν δεν βαζουν δυσκολοτερες. Στο 1ο ετος τουλαχιστον :P

 

Στο στυλακι των K&R αν θυμαμαι καλα (γιατι ειμαι απο Windows τωρα) ακομη και μετα απο loop

το brace μπαινει ακριβως διπλα πχ while ( ... ) { ...

και το ending brace κανονικα κατα μηκος κατω απο το while... επειδη ειδα σε κωδικα οτι το { μπηκε κατω απο το while και ο κωδικας ειχε K&R style .... αυτο συνεπαγεται ανομοιογενεια ή ειναι ενταξει?

 

Πρεπει να παω να δω τι θα κανω με το προτζεκτ που εχω στην VB το καθυστερησα επειδη προχθες σκεφτηκα αυτη την ασκηση μονος και ηθελα να την φτιαξω... και απο οσο ειδατε κ εσεις ο κυριος κορμος μπορει να βγηκε γρηγορα αλλα τα μερεμετια..... ηθελαν περισσοτερο χρονο. Θα τα ξαναπουμε

 

R34ctive δεν σε πιάνω.... γιατι να επιμεινεις στο ALPH_LEN-1 σαν μηκος εφοσον στην συνθηκη έχω την επιλογη του < ALPH_LEN ? :D

 

//---------------------------------OFF (ΑΝΑΘΕΜΑ τα tags που δεν μπαινουν μεσα )------------------------------------------------

>Στο αλλο δεν σε καταλαβαινω.... εσυ βαζεις με τον && 2 τελεστεους....
αριστερα κ δεξια... αν ενας απο αυτους ειναι FALSE
δεν γινεται κατι και δεν μπαινεις στο loop
πως θα μπορεσεις να δεις ποιο απο τα 2 ειναι FALSE?
δεν σε καταλαβαινω.... 
δηλαδη τι σημασια εχει απο που θα σου βγαλει
FALSE ρε συ? εσενα σε νοιαζει και τα 2 να μην ειναι FALSE.

//---------------------------------------------------------------------------------

 

Οπα ακυρο τωρα καταλαβα..... αν δεν μπει θα ξερεις οτι δεν μπηκε λογω του οτι ξεπεραστηκε το μέγεθος.

Σε μικρο προγραμμα αυτο ειναι οκ αλλα σε πολυ μεγαλο πως θα το εχεις στο μυαλο σου??? τελοςπαντων οκ εσυ ξερεις :P

Δημοσ.

Ή θα δηλώσεις τον πίνακα ALPH_LEN + 1 ή θα βάλεις στο loop ALPH_LEN - 1

 

Δες ένα μικρό παράδειγμα χωρίς +1 ή -1

 

>
#include <stdio.h>

#define MAX_LEN (5)

void foo(char *let)
{
 while(*let != '\0')
	 printf("%c",*let++);

 puts("\n");

}

int main(void)
{
 char letters[MAX_LEN] = { 0 };
 int i=0;

 while(i < MAX_LEN && scanf("%c",&letters[i]) != EOF && letters[i] != '\n')
		 i += 1;
		
 printf("=====\n");
 foo(letters);

 return 0;	
}

Έξοδος:
insomnia
=====
insom#V

 

 

Στο τέλος σε έναν πίνακα χαρακτήρων πρέπει να είναι NULL(κανονικά) γι αυτό.

Δημοσ.

α μαλιστα... εσυ λες για τα C-strings. Οπου θα πρεπει να τερματίζονται με έναν κενο χαρακτήρα στο τέλος τους.

Nαι σωστο ειναι αυτο αλλα δεν με ενδιαφερει εδω.

 

Εδω απλα εκμεταλευομαι το γεγονος οτι η getchar αποθηκευει τους χαρακτηρες που παιρνει στο buffer και σταματαει με το ENTER.

To μονο που υπάρχει εφοσον απλοποιηθηκε ο κωδικας ειναι οι θεσεις των γραμμάτων στον πινακα check_letters , η getchar διαβαζει εναν χαρακτηρα καθε φορα και αυξάνει την αντιστοιχη θέση του πίνακα αναλογα με το γραμμα. Δεν υπάρχει C-string. Ο πινακας δεν ειναι καν πινακας χαρακτηρων ειναι πίνακας ακεραίων . ;)

 

Το τελευταιο γράμμα που μπορει να δωσει ο χρηστης εδω ειναι το [25] . Για αυτο και ... < ALPH_LEN (26) .

 

Αν εσυ δώσεις a πχ τοτε έχεις check_letters[ch-'a'] => check_letters['a' - 'a'] => check_letters[0] ( ASCII(a) - ASCII(a) = 0 απο πινακα ASCII ) αρα οσες φορες ο χρηστης δώσει a θα αυξάνεται η θέση [0] οποτε μετα στην άλλη συναρτηση την check() οταν το i θα ειναι 0 τοτε το στοιχειο 'a' + 0 ( 97 + 0 = 97 ) δηλαδη το a θα έχει εμφανιστεί check_letters[0] φορες :P ομοιως και για το τελευταιο στοιχειο στην αλφαβητικη ακολουθια... αρα δεν θες καποιον χαρακτηρα τερματισμου σαν σημαια εδω. Τι να τον κανεις?

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

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