Forum: Mikrocontroller und Digitale Elektronik strcat, umgekehrte Reihenfolge


von Herman Uh. (Gast)


Lesenswert?

Hallo,

ich möchte gerne einige Zahlen in bestimmte Zahlenformate (bin, dec, 
hex) umwandeln und über uart rüberschicken.

Wie kann ich am besten dass so machen, dass ich "0b" voranstelle.
Das "Problem" ist, dass wenn ich mache,
1
strncat(prefix, buffer_int_conv, MAX-strlen(buffer_int_conv)+1);
wird der string prefix unnötig lang. Geplant ist alles in 
buffer_int_conv auszulagern. Dieses habe ich entsprechend groß angelegt, 
dann +prefix binäre Zahlen vom Typ int16_t reinpassen.

1
#define MAX  20
2
char buffer_int_conv[MAX];
3
4
void put_bin(int16_t value)
5
{
6
  const char prefix[] = "0b";
7
  itoa(value, buffer_int_conv, 2);
8
  strncat(buffer_int_conv, prefix, MAX-strlen(buffer_int_conv)+1);
9
  puts(buffer_int_conv);
10
}

von Unbekannt U. (Gast)


Lesenswert?

1
void put_bin(int16_t value)
2
{
3
  char buffer[20];
4
  strcpy(buffer, "0b");
5
  itoa(value, buffer + strlen(buffer), 2);
6
  puts(buffer);
7
}

Oder:

1
void put_bin(int16_t value)
2
{
3
  char buffer[18];
4
  itoa(value, buffer, 2);
5
  putchar('0');
6
  putchar('b');
7
  puts(buffer);
8
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Oder:
1
void put_bin(int16_t value)
2
{
3
  char buffer[18];
4
  itoa(value, buffer, 2);
5
  puts("0b");
6
  puts(buffer);
7
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rufus Τ. Firefly schrieb:
> Oder:
>
1
> void put_bin(int16_t value)
2
> {
3
>   char buffer[18];
4
>   itoa(value, buffer, 2);
5
>   puts("0b");
6
>   puts(buffer);
7
> }
8
>

2x puts hintereinander geht nicht, da puts den String mit einem 
zusätzlichen '\n' ausgibt. Dann hättest Du nach dem "0b" zusätzlich ein 
'\n'.

Wie wärs damit:

void put_bin(int16_t value)
{
  char buffer[18];
  putchar('0');
  putchar('b');
  puts(itoa(value, buffer, 2));
}

von Eric B. (beric)


Lesenswert?

> 2x puts hintereinander geht nicht, da puts den String mit einem
> zusätzlichen '\n' ausgibt.
1
void put_bin(int16_t value)
2
{
3
  char buffer[18];
4
  itoa(value, buffer, 2);
5
  fputs("0b", stdout);
6
  puts(buffer);
7
}
 ;-)

von Helmut L. (helmi1)


Lesenswert?

Oder ganz einfach ein printf / sprintf verwenden.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank M. schrieb:
> 2x puts hintereinander geht nicht, da puts den String mit einem
> zusätzlichen '\n' ausgibt.

Ach, Mist, das hatte ich übersehen.

Alternative (so die Laufzeitumgebung das hergibt)

fputs.

Das nämlich macht's nicht.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Helmut Lenzen schrieb:
> Oder ganz einfach ein printf / sprintf verwenden.

Tja, wenn das verflixte printf auch die Ausgabe einer Zahl im 
Bionärformat erlauben würde. Tut es aber nicht. ;-)

Okay, das ginge:

void put_bin(int16_t value)
{
  char buffer[18];
  printf("0b%s\n", itoa(value, buffer, 2));
}

Ist bisher die kürzeste Version. Aber bestimmt nicht die eleganteste. Da 
kommt es auf die Zielplattform an. Wird printf() unterstützt? Gibt es 
ein stdout für fputs()? Fragen über Fragen...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Und hier die schnellste, die ohne itoa(), printf() und fputs() - und vor 
allem ohne Buffer auskommt:
1
void put_bin(uint16_t value)
2
{
3
    uint16_t i = 0x8000;
4
5
    putchar('0');
6
    putchar('b');
7
8
    while (i)
9
    {
10
        if (value & i)
11
        {
12
            putchar ('1');
13
        }
14
        else
15
        {
16
            putchar ('0');
17
        }
18
        value &= ~i;
19
        i >>= 1;
20
    }
21
    putchar ('\n');
22
}

Ich habe den Parameter übrigens von int16_t auf uint16_t geändert. 
Negative Binärzahlen finde ich nicht wirklich sinnvoll.

Nachteil der obigen Funktion: Es werden alle führenden Nullen gedruckt. 
Die könnte man noch mit einem Flag unterdrücken.... wenn man es denn 
will.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Und weil es soviel Spaß macht, hier noch die obligatorische rekursive 
Methode:
1
static void put_bin2(uint16_t value)
2
{
3
    if (! value)
4
    {
5
        return;
6
    }
7
    put_bin2 (value >> 1);
8
    putchar ('0' + (value & 1));
9
}
10
11
void put_bin(uint16_t value)
12
{
13
    putchar ('0');
14
    putchar ('b');
15
16
    if (! value)
17
    {
18
        putchar ('0');
19
    }
20
    else
21
    {
22
        put_bin2(value);
23
    }
24
    putchar ('\n');
25
}

Diese kommt auch ohne Buffer aus, benutzt lediglich putchar() und 
unterdrückt sogar führende Nullen. Leider muss das ganze wegen des 
abschließenden '\n' in 2 Funktionen realisiert werden. Ohne 
Zeilenabschluss hätte eine Funktion als Konvertierungsfunktion gereicht. 
Das führende '0b' hätte man noch in die Abbruchbedingung der Rekursion 
mit reinnehmen können.

von Peter D. (peda)


Lesenswert?

Frank M. schrieb:
> Und weil es soviel Spaß macht, hier noch die obligatorische rekursive
> Methode:

Auf dem AVR gulpt das ebenmal satte 64 Byte Stack.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Auf dem AVR gulpt das ebenmal satte 64 Byte Stack.

Ja, irgendwo muss der nicht mehr notwendige Buffer ja versteckt werden 
;-)

Das Ding würde ich auch niemals einsetzen. Das war ein rein 
theoretischer Ansatz mit der Rekursion als pures Spielzeug.

von Norbert (Gast)


Lesenswert?

Na gut, von mir auch noch eine...
1
void put_bin(uint16_t value) {
2
    uint16_t i = 0x8000;
3
4
    putchar('0');
5
    putchar('b');
6
    do {
7
        putchar( value & i ? '1' : '0' );
8
    } while(i >>= 1);
9
}

von Unbekannt U. (Gast)


Angehängte Dateien:

Lesenswert?

Also, wenn schon rekursiv, dann aber richtig:

1
extern void putchar(uint8_t);
2
3
static void put_bit(uint16_t value, uint8_t bitnum)
4
{
5
  if (!bitnum) {
6
    putchar('\n');
7
    return;
8
  }
9
10
  putchar( value & 0x8000 ? '1' : '0' );
11
12
  return put_bit(value << 1, bitnum - 1);
13
}
14
15
static void skip_bit(uint16_t value, uint8_t bitnum)
16
{
17
  if (!bitnum) {
18
    putchar('0');
19
    putchar('\n');
20
    return;
21
  }
22
23
  if (value & 0x8000)
24
    return put_bit(value, bitnum);
25
  else
26
    return skip_bit(value << 1, bitnum - 1);
27
}
28
29
void put_bin(uint16_t value)
30
{
31
  putchar('0');
32
  putchar('b');
33
  return skip_bit(value, 16);
34
}

Mit ''avr-gcc -O2'' Version 4.82, Stack-Usage 4 Bytes, siehe Anhang...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.