strcat, umgekehrte Reihenfolge

Gast #3873465
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
}
Gast #3873485
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
}
Moderator Persönliche Seite #3873607
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));
}
Moderator Persönliche Seite #3874047
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...
Moderator Persönliche Seite #3874068
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.
Moderator Persönliche Seite #3874166
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.
Gast #3874845
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...
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren