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

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

Δημοσ.

>
#include <stdio.h>

int main(void)
{
   int num = 26;
   int dig, i;
   int found = 0;

   printf("%d = ", num);
   for (i = 31; i >= 0; i--) {
       dig = num >> i;
       if (dig)
           found = 1;
       if (found == 0)
           continue;

       if (dig & 1)
           printf("1");
       else
           printf("0");
   }
   printf("\n");

   return 0;
}
Έξοδος:
26 = 11010

 

Αν δεν γίνεται να χρησιμοποιηθεί πίνακας (πχ γιατί δεν έχουν διδαχθεί ακόμη οι πίνακες), ένας όχι και τόσο αποδοτικός τρόπος είναι ο παραπάνω. Χάριν ευκολίας θεωρώ ότι ο int έχει 32 bits το οποίο φυσικά δεν είναι σίγουρο. Ο κώδικας παίρνει σβάρνα όλα τα ψηφία αλλά τυπώνει μόνο από το πρώτο άσσο και έπειτα λόγω της μεταβλητής found.

 

Edit: grrr ο editor μου έφαγε το μήνυμα.

 

Αν δεν έχουν διδαχθεί ούτε οι shifting και bitwise τελεστές, τότε το πιο εύκολο είναι με τον πίνακα που πρότεινε ο migf1 και την συνεχόμενη διαίρεση που έδειξες. Όσον αφορά το μέγεθος του πίνακα μπορούμε χωρίς να χαραμίσουμε πολύ μνήμη να θεωρούμε ως μέγεθος του τον αριθμό bits του τύπου το οποίο είναι γνωστό στον compiler. Αν υποθέσουμε ότι ο int έχει 32bit μέγεθος στην πλατφόρμα μας, τότε όποια τιμή και να μας δώσει ο χρήστης θα έχει το πολύ 32 δυαδικά ψηφία οπότε ορίζουμε τον πίνακα να έχει 32 στοιχεία.

  • Απαντ. 32
  • Δημ.
  • Τελ. απάντηση

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

Δημοφιλείς Ημέρες

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

Δημοσιευμένες Εικόνες

Δημοσ.

 

 

>
#include <stdio.h>

int main(void)
{
   int num = 26;
   int dig, i;
   int found = 0;

   printf("%d = ", num);
   for (i = 31; i >= 0; i--) {
       dig = num >> i;
       if (dig)
           found = 1;
       if (found == 0)
           continue;

       if (dig & 1)
           printf("1");
       else
           printf("0");
   }
   printf("\n");

   return 0;
}
Έξοδος:
26 = 11010

 

 

 

...

Χάριν ευκολίας θεωρώ ότι ο int έχει 32 bits το οποίο φυσικά δεν είναι σίγουρος. Ο κώδικας παίρνει σβάρνα όλα τα ψηφία αλλά τυπώνει μόνο από το πρώτο άσσο και έπειτα λόγω της μεταβλητής found. Όσον αφορά το μέγεθος του πίνακα μπορούμε χωρίς να χαραμίσουμε πολύ μνήμη να θεωρούμε ως μέγεθος του τον αριθμό bits του τύπου το οποίο είναι γνωστό στον compiler.

 

>
...
   for (i = sizeof(num)*CHAR_BITS-1; i >= 0; i--) {
...

 

Δημοσ.

Να ρωτησω κάτι...

Διαφορά --χ απο το χ-- ποια είναι??

 

Δοκίμασέ το με αυτόν τον κώδικα...

>
x = 3;
printf( "x = 3; --x: %d\n", --x );
printf( "x: %d\n", x );

x = 3;
printf( "x = 3; x--: %d\n", x-- );
printf( "x: %d\n", x );

Δημοσ.

 

 

>
...
   for (i = sizeof(num)*CHAR_BITS-1; i >= 0; i--) {
...

Ναι φυσικά αλλά υπέθεσα ότι δεν θα έχουν μάθει κάτι τέτοιο (CHAR_BIT btw όχι BITS).

 

Να ρωτησω κάτι...

Διαφορά --χ απο το χ-- ποια είναι??

Στη προκειμένη περίπτωση του for καμμία. Γενικά το ένα πρώτα κάνει την αύξηση/μείωση και μετά επιστρέφει την νέα τιμή ενώ το άλλο πρώτα επιστρέφει τιμή και μετά κάνει την αλλαγή.

 

>
#include <stdio.h>

int main(void)
{
int a = 3;
int b, c;

b = a++;
c = ++a;

printf("a = %d, b = %d, c = %d\n", a, b, c);

return 0;
}
Έξοδος:
a = 5, b = 3, c = 5

Όπως βλέπεις το b έχει την τιμή 3 γιατί το a++ πρώτα επέστρεψε την τιμή του a που τότε ήταν 3 και μετά έκανε την αύξηση σε 4. Έπειτα που έχουμε c = ++a πρώτα γίνεται η αύξηση οπότε το a γίνεται από 4 (που έγινε με την προηγούμενη αύξηση) σε 5 και έπειτα επιστρέφει την τιμή 5 στην μεταβλητή c.

Δημοσ.

Δοκίμασέ το με αυτόν τον κώδικα...

>
x = 3;
printf( "x = 3; --x: %d\n", --x );
printf( "x: %d\n", x );

x = 3;
printf( "x = 3; x--: %d\n", x-- );
printf( "x: %d\n", x );

Δεν μου απάντησες όμως ποια η διαφορα :)

 

Επίσης για το 16δικο δεν θα χρειαστώ και πίνακα με ψηφία??

'A', 'B', 'C', 'D', 'E', 'F'??

Δημοσ.

Σου απάντησα με κώδικα, που δείχνει την διαφορά τους (με επιπλέον λόγια απάντησε ο imitheos) ;)

 

Για hex, προφανώς θα χρειαστείς να χρησιμοποιήσεις τα ABCDEF... θα τα βάλεις σε πίνακα; σε c-string; σε switch-statement; όλα αποδεκτές υλοποιήσεις είναι (ανάλογα και τι έχετε μάθει και τι όχι).

Δημοσ.

Α δεν το είδα sorry...

Ναι σε string θα το βάλω...

 

Υπάρχουν και συναρτήσεις που το κάνουν κατευθείαν? :blink:

Ετσι μου ειπε ενα καθηγητής και εγώ έγραψα ολόκληρο κώδικα....(αν θέλετε σας τον στέλνω τρέχει τζι τζι :P)

 

Να ρωτήσω κάτι??Η αντίστροφη διαδικασία δηλαδή απο 2αδικο σε 10δικο πως γίνεται ακριβώς γιατί σκάλωσα? :wacko:

Στο χαρτί το ξέρω αλλά σε πρόγραμμα?

Δεν μπορώ να σκεφτώ εντολή....

Δημοσ.

Να ρωτήσω κάτι??Η αντίστροφη διαδικασία δηλαδή απο 2αδικο σε 10δικο πως γίνεται ακριβώς γιατί σκάλωσα? :wacko:

Στο χαρτί το ξέρω αλλά σε πρόγραμμα?

Δεν μπορώ να σκεφτώ εντολή....

 

Δήλωσε μια μεταβλητή με αρχική τιμή 0 για τον αριθμό σου και επίσης μια μεταβλητή με αρχική τιμή 1 η οποία θα σημαίνει τις δυνάμεις του δύο. Ξεκίνα από το τελευταίο ψηφίο και πρόσθεσε την αντίστοιχη δύναμη του δύο. Πολλαπλασίασε την μεταβλητή της δύναμης επί δύο για να πάρεις την επόμενη δύναμη. Συνέχισε μέχρι να μην υπάρχουν άλλα δυαδικά ψηφία.

 

>
Ο δοσμένος δυαδικός είναι το 11010
Δεκαδικός = 0
Δύναμη = 1

Για κάθε ψηφίο από το τέλος:
   Δεκαδικός = Δεκαδικός + Ψηφίο * Δύναμη
   Δύναμη = Δύναμη * 2

1ο ψηφίο από τέλος = 0 οπότε Δεκαδικός = 0 + 0 * 1 = 0
Δύναμη = 1 * 2 = 2
2ο ψηφίο = 1 οπότε Δεκαδικός = 0 + 1 * 2 = 2
Δύναμη = 2 * 2 = 4
κτλ και στο τέλος θα έχουμε ότι Δεκαδικός = 2 + 8 + 16 = 26

Δημοσ.

...

Υπάρχουν και συναρτήσεις που το κάνουν κατευθείαν? :blink:

Ετσι μου ειπε ενα καθηγητής και εγώ έγραψα ολόκληρο κώδικα....(αν θέλετε σας τον στέλνω τρέχει τζι τζι :P)

...

 

Ποιο πράγμα υπάρχουν συναρτήσεις που το κάνουν κατευθείαν; Ίσως εννοεί τις strtoul()/strtol() που παίρνουν την επιθυμητή βάση μετατροπής ως όρισμα και πρέπει να διαβάζεις τον αρχικό αριθμό ως string.

 

Αλλά δεν μετατρέπουν από τη μια βάση στην άλλη. Αν π.χ. σου δώσει "24AF" και έχεις βάση 16 απλώς θα σου επιστρέψει τον ακέραιο με την τιμή που αντιστοιχεί σε αυτό το ας το πούμε 16αδικά εκφρασμένο c-string. Αν έχεις βάση 10 τότε το "24AF" σαν είσοδος θα σου επιστρέψει σφάλμα.

Δημοσ.

Μήπως εννοεί κανένα τρικ σε στυλ sscanf(.. "%x", ..) όπου διαβάζεις από την είσοδο (πχ. fgets) έναν δεκαεξαδικό (ως αλφαριθμητικό) και μέσο sscanf και %x τον περνάς σε int και τον εκτυπώνεις με %d ύστερα ως dec.

Δημοσ.

Ιδέα δεν έχω τι εννοεί ο καθηγητής του φίλου. Υπάρχει και ο %i specifier που επιτρέπει στον χρήστη να ορίσει μόνος του την βάση (π.χ. με fgets(input, ...); sscanf(input, "%i", &num); το "023" το σώζει οκταδικά στον num, το "0x23" το σώζει 16αδικά και το "23" δεκαδικά ) αλλά όλα αυτά νομίζω κάνουν defeat το νόημα της άσκησης.

 

Μήπως ο καθηγητής έχει υπόψιν του τίποτα non-standard συναρτήσεις μετατροπής από τη μια βάση στην άλλη; Δεν ξέρω.

Δημοσ.

Έτοιμες συναρτήσεις θα υπάρχουν για σχεδόν τα πάντα που θα κάνεις σε ασκήσεις αλλά αυτό είναι το νόημα. Να γράψεις ένα σωρό κώδικες όπως είπες και να εξασκηθείς. Αλλιώς θα μας έδιναν ένα κομπιουτεράκι στο δημοτικό αντί να μας μάθουν διαίρεση :P

 

Ωραίες ιδέες πάντως και του DirectX και του migf1. Σημείωσε τες. Αν θες ρώτα τον καθηγητή την επόμενη φορά που θα τον δεις και πες μας για να μας φύγει η περιέργεια :P

 

Ένα άλλο πιθανό σενάριο είναι ο "b" conversion specifier. Σε μερικές υλοποιήσεις (ειδικά στα Windows), οι printf, scanf, κτλ υποστήριζαν σαν επέκταση και τον %b εκτός από τους κλασικούς %d, %x, %o,κτλ. Με αυτόν εμφανίζουμε / ζητάμε δυαδική μορφή αλλά δεν είναι μέρος του προτύπου. Δεν είναι βέβαια συνάρτηση αλλά αν δουλεύει windows χρόνια ίσως να είχε στο μυαλό του αυτόν.

Δημοσ. (επεξεργασμένο)
[..]Ένα άλλο πιθανό σενάριο είναι ο "b" conversion specifier. Σε μερικές υλοποιήσεις (ειδικά στα Windows), οι printf, scanf, κτλ υποστήριζαν σαν επέκταση και τον %b εκτός από τους κλασικούς %d, %x, %o,κτλ. Με αυτόν εμφανίζουμε / ζητάμε δυαδική μορφή αλλά δεν είναι μέρος του προτύπου. Δεν είναι βέβαια συνάρτηση αλλά αν δουλεύει windows χρόνια ίσως να είχε στο μυαλό του αυτόν.

Yeap!! Πάνε πραγματικά πολλά χρόνια και δεν θυμάμαι σε ποίον compiler το είχα συναντήσει, πιθανότατα επρόκειτο για τον MS - C 6.1 για DOS (διαφορετικά πάμε σε C μεταφραστές της AMIGA -αλλά δεν νομίζω..), θυμάμαι εκτύπωνε κανονικά στο STDOUT δυαδικούς αριθμούς με άσσους και μηδενικά!

 

--EDIT: Όχι, τελικά δεν ήταν ο MS-C 6.1, ξέθαψα τα αρχεία βοήθειας του και στην printf που προσφέρει δεν υπάρχει το συγκεκριμένο Format Type, οπότε ειλικρινά δεν θυμάμαι που το είχα δει υλοποιημένο.. :(

 

 

post-41640-0-73415800-1354048993_thumb.png

 

 

--EDIT: Ψάχνοντας λίγο το αρχείο βοήθειας εντόπισα πιθανότατα που είχα σχηματίσει την εντύπωση ότι είχα δει το %b. Για την ιστορία λοιπόν υπάρχει ένα υπόδειγμα χρήσης κάποιων συναρτήσεων μεταξύ των οποίων και της itoa. Η itoa είναι μια non-ANSI συνάρτηση η οποία λαμβάνει μια τιμή και σου επιστρέφει την αναπαράσταση της ως αλφαριθμητικό (char*) με όποια βάση (radix) ορίσεις εσύ. Για να λειτουργήσει χρειάζεται έναν εξωτερικό char buffer (szTempBuf). Αυτή η ρουτίνα λοιπόν της MS-C 6.1, υπάρχει ακόμα και σήμερα στον C++ Builder (stdlib.h) μαρκαρισμένη απλά ως non-ANSI στην τεκμηρίωση (καταβολές από την εποχή της Borland Turbo-C για DOS ;)).

 

Με την βοήθεια της μπορείς να κάνεις άμεσα την μετατροπή ενός integer σε δυαδικό ως εξής:

 

>
char szTempBuf[20];
puts(itoa(123, szTempBuf, 2));

> [b]Έξοδος:[/b]
 1111011

 

Ο κώδικας του υποδείγματος της MS-C 6.1 ήταν ο εξής:

 

>
/* Converts integer to string of 16 binary characters. */
char *binstr( int num, char *buffer )
{
   char tmp[17];
   int  len;

   memset( buffer, '0', 16 );
   len = strlen( itoa( num, tmp, 2 ) );
   strcpy( buffer + 16 - len, tmp );
   return buffer;
}

ΕΞΟΔΟΣ:

0000000001111011 αν num = 123

 

 

 

Οπότε μάλλον κάτι τέτοιο είχα δει τότε και ενδεχομένως κάτι τέτοιο να εννοούσε ο καθηγητής όταν ανέφερε πως υπάρχουν έτοιμες ρουτίνες (έτοιμες ναι, στάνταρτ όχι :-/).

 

* Καθώς εδώ και αρκετά χρόνια προσπαθώ να προτιμώ τις ANSI-C ρουτίνες, αμέλησα εντελώς την ύπαρξη της itoa!!

Επεξ/σία από Directx
Δημοσ.

 

Yeap!! Πάνε πραγματικά πολλά χρόνια και δεν θυμάμαι σε ποίον compiler το είχα συναντήσει, πιθανότατα επρόκειτο για τον MS - C 6.1 για DOS (διαφορετικά πάμε σε C μεταφραστές της AMIGA -αλλά δεν νομίζω..), θυμάμαι εκτύπωνε κανονικά στο STDOUT δυαδικούς αριθμούς με άσσους και μηδενικά!

 

--EDIT: Όχι, τελικά δεν ήταν ο MS-C 6.1, ξέθαψα τα αρχεία βοήθειας του και στην printf που προσφέρει δεν υπάρχει το συγκεκριμένο Format Type, οπότε ειλικρινά δεν θυμάμαι που το είχα δει υλοποιημένο.. :(

Ναι και εγώ δεν θυμάμαι που το είχα δει. Το πρώτο που μου ήρθε στο μυαλό ήταν Turbo / Borland C για DOS αλλά δεν θυμάμαι αν ήταν εκεί. Επίσης είμαι σχεδόν σίγουρος ότι μας το είχαν δείξει σαν ένα από τα πολλά παραδείγματα της printf στη σχολή σε Windows αλλά χρησιμοποιούσαμε Visual Studio και σύμφωνα με το google δεν υποστηρίζεται από το VS. Θυμάμαι ότι εκτός από την printf μπορούσες να δηλώσεις και literals, νομίζω προσθέτοντας b στο τέλος πχ int k = 1010101b (Αυτό το κάνει σαν extension και ο gcc αλλά βάζοντας 0b μπροστά αντί για b πίσω).

 

--EDIT: Ψάχνοντας λίγο το αρχείο βοήθειας εντόπισα πιθανότατα που είχα σχηματίσει την εντύπωση ότι είχα δει το %b. Για την ιστορία λοιπόν υπάρχει ένα υπόδειγμα χρήσης κάποιων συναρτήσεων μεταξύ των οποίων και της itoa. Η itoa είναι μια non-ANSI συνάρτηση η οποία λαμβάνει μια τιμή και σου επιστρέφει την αναπαράσταση της ως αλφαριθμητικό (char*) με όποια βάση (radix) ορίσεις εσύ. Για να λειτουργήσει χρειάζεται έναν εξωτερικό char buffer (szTempBuf). Αυτή η ρουτίνα λοιπόν της MS-C 6.1, υπάρχει ακόμα και σήμερα στον C++ Builder (stdlib.h) μαρκαρισμένη απλά ως non-ANSI στην τεκμηρίωση (καταβολές από την εποχή της Borland Turbo-C για DOS ;)).

 

Οπότε μάλλον κάτι τέτοιο είχα δει τότε και ενδεχομένως κάτι τέτοιο να εννοούσε ο καθηγητής όταν ανέφερε πως υπάρχουν έτοιμες ρουτίνες (έτοιμες ναι, στάνταρτ όχι :-/).

 

* Καθώς εδώ και αρκετά χρόνια προσπαθώ να προτιμώ τις ANSI-C ρουτίνες, αμέλησα εντελώς την ύπαρξη της itoa!!

 

Α όντως η itoa. Δεν πήγε εκεί το μυαλό μου. Όλα τα παραδείγματα σε DOS είχαν και από μια κλήση σε itoa / atoi. Φαίνεται η Turbo C ή δεν είχε sprintf ή θεώρησαν πως ήταν πολύ δύσκολο να σκεφτεί κάποιος νέος να χρησιμοποιήσει sprintf ενώ θα πάει κατευθείαν το μυαλό του σε itoa ως αντίθετη της atoi.

 

Δίκιο έχεις, το πιο πιθανό σενάριο είναι να εννοούσε την itoa και όχι τον %b που είπα μια και η itoa ήταν απείρως πιο γνωστή και την ανέφεραν όλες οι ασκήσεις και όλα τα βιβλία (άσε που είναι και συνάρτηση οπότε ταιριάζει με τα λόγια του καθηγητή).

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

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