Ausgabe in C
-
Okay und kannst du mich darüber aufklären, wie das mit der Rekursion genau gemeint ist?
-
Ja, klar ist das möglich.
Normalerweise wandelt man gleich in einen String (also '0' und '1') um, weil man mit einem Zahlenarray dass die Binärform repräsentiert eh man wenig anfangen kann.
Da gibt es verschiedene Ansätze. Der einfachste ist wahrscheinlich die neue Zahl einfach immer vorne anzuhängen und den Rest nach hinten zu schieben.
Am performantesten dürfte es sein, ein (char) Array einfach von hinten zu beschreiben und das dann erst ab dem gültigen Index auszugeben oder gleich mit nullen zu füllen.@Rekursion: oO Dann zeig mal her.
-
Okay das klingt verständlich. Und auch für mich lösbar.
Aber eine weitere Frage habe ich dazu noch, wie kann ich es machen, dass wenn ich die Binärzahl ausgeb nach jeweils 4 Stellen ein Freizeichen ist?
-
Also wenn ich das jetzt richtig verstanden habe, was du sagtest, dann sieht mein Programm so aus:
#include<stdio.h> int main(void) { int speicher[32], dezimalzahl ,i; printf("Bitte geben sie eine Dezimalzahl ein:"); printf("\n\n"); scanf("%d",&dezimalzahl); for ( i=0; dezimalzahl > 0; i++) { speicher[i]=dezimalzahl%2; dezimalzahl=dezimalzahl/2; } for (; i > 0; i--) { printf("%d",speicher[i-1]); } return 0; }
-
Toastaa schrieb:
Also wenn ich das jetzt richtig verstanden habe, was du sagtest, dann sieht mein Programm so aus:
Und wie sieht dein Programm aus, wenn du ihn nicht richtig verstanden hast? :xmas2:
-
Dann würde es genauso aussehen, nur das ich es anders gelöst hätte als er es sagte.
-
Toastaa schrieb:
Aber eine weitere Frage habe ich dazu noch, wie kann ich es machen, dass wenn ich die Binärzahl ausgeb nach jeweils 4 Stellen ein Freizeichen ist?
Entweder mit einer Schleife und putchar() (und if (i % 4 == 0)), oder mit solchen Konstrukten:
void print_bin(const char *s) { while (*s && printf("%.4s ", s) == 5) s += 4; }
Da gibt es jetzt unzählige Formatierungsmöglichkeiten.
Und nein, du hast mich nicht richtig verstanden.
-
Ja das habe ich auch grade gemerkt als ich mir nochmal einen bericht zur Rekursion durchgelesen habe :).
Aber da werde ich mich morgen nochmal genauer informieren.
Aber ich danke dennoch schonmal für die Hilfe.
-
Das mit der Rekursion war nicht meine Idee. (Und offen gesagt finde ich die Idee auch doof.)
void print_bin(const char *s) { while (*s && printf("%.4s ", s) == 5) s += 4; } char *make_bin(unsigned num, char *buf, unsigned buf_size) { char *p = buf + buf_size - 1; if (buf_size == 0) return buf; // Oder gleich assert(), oder einfach ignorieren, buf_size = 0 macht keinen Sinn. *p = '\0'; while (p-- != buf) { *p = num % 2 + '0'; num /= 2; //if (num == 0) // Falls du nicht mit Nullen füllen möchtest. // return p; } return p + 1; } int main() { unsigned number = 34754643; char buffer[sizeof(unsigned) * CHAR_BIT + 1]; print_bin(make_bin(number, buffer, sizeof(buffer))); getchar(); }
-
cooky451 schrieb:
Das mit der Rekursion war nicht meine Idee. (Und offen gesagt finde ich die Idee auch doof.)
Vergleich mal dein Code mit meinem und sage mir nochmal ins Gesicht, dass das ne doofe Idee war.
#include <stdio.h> void toBinary(int n) { if (n != 0) { toBinary(n/2); printf("%d", n%2); } } int main() { toBinary(9); printf("\n"); return 0; }
Liebe Grüße
Steffo
-
Na ja, ich schreibe ja auch in einen String. Wenn du einfach nur die Ausgabe haben möchtest, dann doch bitte gleich so:
void printBinary(int n, unsigned j) { if (j != 0) { printBinary(n/2, j - 1); if (j % 4) printf("%d", n%2); else printf("%d ", n%2); } } int main() { printBinary(34754643, sizeof(int) * CHAR_BIT); return 0; }
-
Auf solche Details kommt es auch nicht mehr drauf an und selbst wenn du in einem String schreiben willst, bist du mit Rekursion besser dran.
L. G.
Steffo
-
Doch es macht einen Unterschied, du bekommst da kleine Probleme mit der Nullterminierung. :xmas1:
-
Wo soll da das Problem sein?
/*...*/ if (j == sizeof(unsigned) * CHAR_BIT) { buf[sizeof(unsigned) * CHAR_BIT] = '\0'; /* Oder so ähnlich... */ } /*...*/
-
Da siehst du die Puffergröße jetzt aber als gegeben an, das zählt nicht. Wenn es so einfach ist, schreibe doch eine äquvalente Funktion, die 7 Zeilen wirst du wohl überleben.
-
#include <stdio.h> #include <stdlib.h> static void writeBinary(int n, int *c) { if (n != 0) { ungetc(n % 2 + '0', stdin); writeBinary(n / 2, c); (*c)++; } } void toBinary(int n, char **s) { int c = 0; ungetc(' ', stdin); writeBinary(n, &c); *s = (char*) malloc(sizeof(char) * c + 1); scanf("%s", *s); } int main() { char *s = NULL; toBinary(8, &s); printf("%s\n",s); free(s); return 0; }
-
Was haltet Ihr denn von dieser Herangehensweise?
#include <stdio.h> #include <stdlib.h> #include <assert.h> void print_binary(unsigned int number) { unsigned int flag = 1 << ((sizeof(unsigned int) * CHAR_BIT) - 1); /* directly print 0 if number is 0 */ if (!number) { putchar(number + '0'); return; } /* cut off leading zeros */ while (!(number & flag)) flag >>= 1; /* print the result */ while (flag) { putchar(number & flag ? '1' : '0'); flag >>= 1; } } typedef struct binary_string { /* guaranteed to be big enough to hold all bits of an unsigned int plus the terminating null character */ char buffer[(sizeof(unsigned int) * CHAR_BIT) + 1]; } binstr_t; void to_binary(unsigned int number, binstr_t * output) { unsigned int n = (sizeof(unsigned int) * CHAR_BIT) - 1; char * p = NULL; assert(output != NULL); p = output->buffer; /* almost the same like above */ if (!number) { output->buffer[0] = '0'; output->buffer[1] = '\0'; return; } while (!(number & (1 << n))) --n; do { *p++ = (number & (1 << n)) ? '1' : '0'; } while(n--); *p = '\0'; } int main(void) { unsigned int n = 0; binstr_t str; for (; n < 16; ++n) { printf("print_binary: "); print_binary(n); putchar('\n'); to_binary(n, &str); printf("to binary: %s\n", str.buffer); } return 0; }
-
Steffo schrieb:
#include <stdio.h> #include <stdlib.h> static void writeBinary(int n, int *c) { if (n != 0) { ungetc(n % 2 + '0', stdin); writeBinary(n / 2, c); (*c)++; } } void toBinary(int n, char **s) { int c = 0; ungetc(' ', stdin); writeBinary(n, &c); *s = (char*) malloc(sizeof(char) * c + 1); scanf("%s", *s); }
Diese Art des Missbrauchs von ungetc ist durch den Standard nicht gedeckt:
ISO/IEC 9899:1999 7.19.7.11 (3) schrieb:
One character of pushback is guaranteed. If the ungetc function is called too many times on the same stream without an intervening read or file positioning operation on that stream, the operation may fail.
Ich sehe auch nicht, was man hier groß mit Rekursion wollen sollte. Geht auch, aber die Gruppierung wird auf die Weise ziemlich umständlich, und Performancevorteile darf man sich in diesem Fall von einem rekursiven Vorgehen sicher nicht versprechen.
Eine einfache Möglichkeit, die ganze Problematik mit der Suche nach der Länge des Ergebnisstrings zu umgehen, ist, von hinten zu schreiben und einen Zeiger mitten in den Buffer als String zu benutzen. Ich stelle mir das etwa so vor:
#include <limits.h> #include <stddef.h> #include <stdio.h> #include <string.h> char *binary_representation(char *buffer, size_t buflen, unsigned x) { char *p = buffer + buflen - 1; size_t used = 0; int group = 0; do { ++used; if(used >= buflen) return NULL; --p; if(group == 4) { group = 0; *p = ' '; } else { ++group; *p = (x & 1) + '0'; x >>= 1; } } while(x != 0); buffer[buflen - 1] = '\0'; return p; /* * Wenn man die Daten unbedingt am Anfang des Eingabebuffers haben will, * kann man hier statt der letzten zwei Zeilen * * memmove(buffer, p, used); * buffer[used] = '\0'; * return buffer; * * schreiben. Frisst natürlich etwas mehr Laufzeit, aber für Linksjustierung * braucht man halt ein Zwischenergebnis. */ } int main(void) { char buffer[100]; char *bin; bin = binary_representation(buffer, sizeof(buffer), 1234); if(bin) { puts(bin); } return 0; }
-
seldon schrieb:
Diese Art des Missbrauchs von ungetc ist durch den Standard nicht gedeckt:
ISO/IEC 9899:1999 7.19.7.11 (3) schrieb:
One character of pushback is guaranteed. If the ungetc function is called too many times on the same stream without an intervening read or file positioning operation on that stream, the operation may fail.
Dann nimmt man halt einen Stack oder so etwas ähnliches. Jedenfalls ist Rekursion hier m. A. n. eleganter. Und das Performance-Argument zählt nicht. Weshalb?
Nehmen wir mal an, man will 1000 000 000 in binär umwandeln. Wieviel rekursive Aufrufe sind das? Das sind aufgerundet genau log2(1000 000 000) = 30 Aurufe --> Sich hier Performancegedanken zu machen, ist fehl am Platz.Schau dir mal meine Schnittstelle an (Parameter: beliebige Zahl, mit NULL initialisierter Pointer) und deine Schnittstelle (Parameter: buffer, mit der fixen Größe 100, Größe des Buffers und beliebige Zahl). Bei meiner Methode hat der Endanwender weniger Arbeit und muss sich weniger Gedanken machen.
L. G.
Steffo
-
Ich sehe irgendwie dein Argument nicht. Es geht wunderbar als Schleife. Rekursion ist hier technisch gar nicht nötig, es ist bloß eine andere Art, die Schleife zu schreiben.