Forum: PC-Programmierung Hilfe nötig für vereinfachung einer c Funktion


von Martin Teuer (Gast)


Lesenswert?

Hallo,
ich habe eine FUnktion geschirben in c aber ich denke sie ist sehr 
kompliziert? Kann man diese einfacher schreieben??
1
#include <stdio.h>
2
#include <string.h>
3
4
int main()
5
{
6
        char str[] = "69:66:84:1A:0E:E7:E5:51:30:82:60:A7:27:F2:A5:54:56:B9:15:19";
7
        int init_size = strlen(str);
8
        char delim[] = ":";
9
        char test[200];
10
        char test1[200];
11
        char *ptr = strtok(str, delim);
12
        int firstrun = 1;
13
        while(ptr != NULL)
14
        {
15
                if (firstrun == 1) {
16
                        sprintf(test, "0x%s", ptr);
17
                        firstrun = 0;
18
                }
19
                else {
20
                        sprintf(test, ", 0x%s", ptr);
21
                }
22
                strcat(test1, test);
23
                ptr = strtok(NULL, delim);
24
        }
25
        printf("%s", test1);
26
        return 0;
27
}

von A. S. (Gast)


Lesenswert?

Die Funktion ist sinnlos. Sie gibt einen festen Output aus

Wenn Du sagst, was sie machen soll, kann man darüber diskutieren wie.

von Sebastian (Gast)


Lesenswert?

Gib am Anfang "0x" aus, und dann lauf durch str und gib jedes Zeichen 
ausser : aus, und bei : gib ", 0x" aus.

LG, Sebastian

von Helmut -. (dc3yc)


Lesenswert?

Du hast nirgends eine Funktion geschrieben. Alles steht im 
Hauptprogramm.

von Martin L. (tempusertempuser)


Lesenswert?

Es soll aus
69:66:84:1A:0E:E7:E5:51:30:82:60:A7:27:F2:A5:54:56:B9:15:19
Folgendes geformt werden
0x69, 0x66 .....0x19


Ich weiss es ist in der Main Funktion um zu testen.

Danke für die Hilde

von A. S. (Gast)


Lesenswert?

Martin L. schrieb:
> Es soll aus
> 69:66:84:1A:0E:E7:E5:51:30:82:60:A7:27:F2:A5:54:56:B9:15:19
> Folgendes geformt werden

Naja, das tut es. Nicht als Funktion, nicht variable, nicht auf 
irgendwas optimiert, ...

Du kannst z.b. anfangen, doppelten Code zu eliminieren.

Oder ohne strcat, nur sprintf. Das ist aber ohne Ziel oder Wortlaut der 
Aufgabe Kaffeesatzleserei

von Martin L. (tempusertempuser)


Lesenswert?

Ich wäre dankbar wenn jdm erfahrenes einfach Tipps geben kann oder eine 
Optimierung meiner Lösung durchführt?

Programm soll Macher auf einem esp laufen

: Bearbeitet durch User
von wozu (Gast)


Lesenswert?

welchen Sinn macht es denn ":" durch "," zu ersetzen?

Und wenn man weiß, dass es Zahlen sind, dann sieht man auch sofort dass 
es hex-Zahlen sind. Wozu dann noch "Ox" davor?

Oder willst du Zahlen aus dem String extrahieren?

von Martin L. (tempusertempuser)


Lesenswert?

wozu schrieb:
> welchen Sinn macht es denn ":" durch "," zu ersetzen?
>
> Und wenn man weiß, dass es Zahlen sind, dann sieht man auch sofort dass
> es hex-Zahlen sind. Wozu dann noch "Ox" davor?
>
> Oder willst du Zahlen aus dem String extrahieren?


Es ist ein String die stellen müssen extrahiert werden und dann mit 0x 
davor. Am Ende soll wieder ein String rauskommen

von wozu (Gast)


Lesenswert?

strtok-Funktion verändert deinen Originalstring.

von Martin L. (tempusertempuser)


Lesenswert?

Was muss ich dann machen?

von Joachim B. (jar)


Lesenswert?

Martin L. schrieb:
> Am Ende soll wieder ein String rauskommen

wieso wenn es doch 8-Bit Hexwerte sind?
Dann könnte statt ein String auch gleich ein uint8_t Array rauskommen.

Der original "String" belegt Speicher, hinterher brauchst du für 0x 
definitiv pro Byte 2 Byte mehr, also müsstes dafür Speicher 
bereitstellen.
Ich würde ja 2-stufig vorgehen.
1. Byte zählen : +1
2. malloc für Anzahl 4x der gezählten Byte wegen
0
x
Byte
,

etwa auch noch space?

Martin L. schrieb:
> Folgendes geformt werden
> 0x69, 0x66 .....0x19

dann ja
2a. malloc für Anzahl 5x der gezählten Byte wegen

0
x
Byte
,
<SPACE>

von Martin L. (tempusertempuser)


Lesenswert?

Ja uint8_t Array wäre auch super....sorry bin nicht so gut im 
programmieren.....

Könntest du die Funktion in c code schreiben?

von wozu (Gast)


Lesenswert?

Martin L. schrieb:
> Ja uint8_t Array wäre auch super

Mensch, darum habe ich auch gefragt welchen Sinn es macht ":" durch "," 
im String zu verändern.

von Sebastian W. (wangnick)


Lesenswert?

Martin L. schrieb:
> Ich wäre dankbar wenn jdm erfahrenes einfach Tipps geben kann oder eine
> Optimierung meiner Lösung durchführt?

Immer noch? Tipp und Optimierung hab ich doch schon gegeben! Aber gut, 
etwa so:
1
#include <stdio.h>
2
#include <string.h>
3
4
void convert (char* from, char* to) {
5
    memcpy(to,"0x",2); to += 2;
6
    for (; *from; from++) {
7
        if (*from==':') {
8
            memcpy(to,", 0x",4); to += 4;
9
        } else {
10
            *to++ = *from;
11
        }
12
    }
13
    *to = 0;
14
}
15
16
int main() {
17
    char str[] = "69:66:84:1A:0E:E7:E5:51:30:82:60:A7:27:F2:A5:54:56:B9:15:19";
18
    char out[200];
19
    convert(str,out);
20
    printf("%s\n",out);
21
    return 0;
22
}

LG, Sebastian

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

Martin L. schrieb:
> Könntest du die Funktion in c code schreiben?

ja

von wozu (Gast)


Lesenswert?

Zahlen extrahieren:
1
   char str_in[] = "69:66:84:1A:0E:E7:E5:51:30:82:60:"
2
                   "A7:27:F2:A5:54:56:B9:15:19";
3
4
   char* end = str_in;
5
6
   while (1) {
7
      char* start = end;
8
      long hex = strtol (start, &end, 16);
9
10
      printf ("hex: %lx\n", hex);
11
12
      if (!*end) {
13
         break;
14
      }
15
16
      end++;
17
   }

Dann kannst du die Zahlen in einem Array speichern (statt sie 
auszugeben).

von Joachim B. (jar)


Lesenswert?

Sebastian W. schrieb:
> char str[] =
> "69:66:84:1A:0E:E7:E5:51:30:82:60:A7:27:F2:A5:54:56:B9:15:19";
>     char out[200];

gilt doch nur für bekannte Stringlängen und wenn der String mal länger 
wird crashed es

wozu schrieb:
> Dann kannst du die Zahlen in einem Array speichern (statt sie
> auszugeben).

auch dazu müsste man zählen und Speicher reservieren, oder man nimmt den 
Speicher von Input und legt ja gleich dort ohne : und ohne 0x wieder ab, 
dann wäre das kein String sondern nur ein Bytearray.

von wozu (Gast)


Lesenswert?

Aus dem String "FF" wird kein byte-Wert von 255.

von Sebastian W. (wangnick)


Lesenswert?

Joachim B. schrieb:
> gilt doch nur für bekannte Stringlängen und wenn der String mal länger
> wird crashed es

Das ist aber kein Problem der Funktion convert() sondern des Aufrufers 
... :)

Ok, dann also:
1
    char out[strlen(str)*4+3];

https://onlinegdb.com/ziUUevzGY

Dann crashed auch char str[] = "::::" nicht!

LG, Sebastian

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

Martin L. schrieb:
> Ich wäre dankbar wenn jdm erfahrenes einfach Tipps geben kann oder eine
> Optimierung meiner Lösung durchführt?
>
> Programm soll Macher auf einem esp laufen

Deine Frage macht keinen Sinn. Du solltest schreiben, wofür Du das haben 
möchtest. Ist es eine Hausaufgabe, willst Du ein (ganz anderes) Problem 
lösen?

Dein Code funktioniert vermutlich, ist aber sehr fragil. Die Aufgabe ist 
aber nur eine Fingerübung, ähnlich der Folge "asdf jklö" im 
Schreibmaschinenkurs. Da macht es auch keinen Sinn, das "irgendwie 
eleganter" zu schreiben.

von DPA (Gast)


Lesenswert?

Hier mal noch als posix shell script:
1
f(){
2
  ( IFS=:; printf ", 0x%s" $* | tail -c +3; )
3
}
4
f 12:fa:5e

Oder mit sed:
1
echo 12:ab:cd | sed "s/^/0x/;s/:/, 0x/g"

von PittyJ (Gast)


Lesenswert?

Ich verstehe das Problem nicht. Die Funktion besteht aus einer Schleife 
mit einer If-Abfrage. Das ist schon fast das wenigste, was Funktionen so 
im Normalfall machen. Was ist daran jetzt komliziert?

Funktionen mit 100 Zeilen sind die Regel, und auch schon mal 500 Zeilen 
habe ich gesehen.

von Martin Teuer (Gast)


Lesenswert?

ich habe es versucht nun mit
1
uint8_t finalout[20];
2
  for (int i = 0; i <strlen(out); i++) {
3
sscanf(out[i], "%x", finalout[i]);
4
}


in ein uint_8t array zu verandeln aber es klappt nicht.
Was ist daran falsch?

von A. S. (Gast)


Lesenswert?

Martin Teuer schrieb:
> ich habe es versucht nun mit [...]
> in ein uint_8t array zu verandeln

Was denn? Hast Du einen lauffähigen(Compilerbären) Code? Soll das 
irgendwo in dein main reinpassen ? Was kommt rein, was soll rauskommen? 
Hast Du scanf verstanden und Mal in einfacher Form benutzt?

von Jobst Q. (joquis)


Lesenswert?

Martin Teuer schrieb:
> ich habe eine FUnktion geschirben in c aber ich denke sie ist sehr
> kompliziert? Kann man diese einfacher schreieben??

Als Quelltext sieht es noch relativ einfach aus. Für das, was die CPU zu 
tun hat, ist es aber ziemlich kompliziert und aufwendig. Das liegt vor 
allem an den benutzten Funktionen sprintf, strtok und strcat, die sie 
unnötigerweise auszuführen hat.

Wenn man die Aufgabe direkt mit Pointern löst, hat sie schätzungsweise 
nur ein hundertstel davon zu tun. Etwa so:
1
char * convertTo0x(char *t,const char *s,char *lim){
2
3
int firstrun=1;
4
5
lim--;
6
while (*s && t<lim){
7
  if(*s==':' && (t+4)<lim){
8
    s++;
9
    *t++=',';
10
    *t++=' ';
11
    *t++='0';
12
    *t++='x';
13
    }
14
  else if (firstrun && (t+2)<lim){
15
    *t++='0';
16
    *t++='x';
17
    firstrun = 0;
18
    }
19
  else *t++=*s++;
20
  }
21
*t=0;
22
return t;
23
}

Der Aufruf mit deinen Variablen:
convertTo0x(test1,str,test1+sizeof(test1));

Diese Funktion ist zudem durch die Variable lim noch überlaufsicher. In 
deiner Version müsstest du statt sprintf snprintf verwenden und dabei 
die Puffergröße immer wieder neu berechnen.

von stringende (Gast)


Lesenswert?

Jobst Q. schrieb:
> return t;

Das wäre dann die Adresse vom Stringende

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Helmut -. schrieb:
> Du hast nirgends eine Funktion geschrieben. Alles steht im
> Hauptprogramm.

main() ist eine Funktion wie jede andere auch. Der einzige Unterschied 
zu anderen Funktionen besteht darin, dass in den meisten(!) 
Laufzeitumgebungen main() die zuerst aufgerufene Funktion des 
Anwenderprogramms ist. Nicht mehr und nicht weniger.

von Einer (Gast)


Lesenswert?

1
void convert(char * dest, char * src)
2
{
3
  while (*src) {
4
    *dest++ = '0'; *dest++ = 'x';
5
    while (*src && *src != ':')
6
      *dest++ = *src++;
7
    if (*src) {
8
      *dest++ = ','; *dest++ = ' ';
9
      src++
10
    }
11
  }
12
  *dest = 0;
13
}

Wer will kann ja noch beliebige Fehlerabfragen dazubauen.

Ist halt eine Frage davon, was die Spezifikation ist. Wenn garantiert 
ist, dass der Eingangs-String korrekt ist und der Ziel-Buffer groß 
genug, kann man sich das sparen. Wenn nicht, muss halt noch etwas 
Kleinkram dazu.

von Jobst Q. (joquis)


Lesenswert?

stringende schrieb:
> Jobst Q. schrieb:
>> return t;
>
> Das wäre dann die Adresse vom Stringende

Genau. In diesem Fall vielleicht nicht notwendig, aber sehr praktisch, 
wenn man noch etwas anhängen möchte. Der Stringanfang ist ja eh bekannt.

von Einer (Gast)


Lesenswert?

Eigentlich kann man es noch brutaler schreiben, wenn es auf jede 
Mikrosekunden ankommt:
1
void convert(char *dest, char *src) 
2
{
3
    goto start;
4
    do {
5
        *dest++ = ','; *dest++ = ' ';
6
        src++;
7
    start:
8
        *dest++ = '0'; *dest++ = 'x';
9
        *dest++ = *src++; *dest++ = *src++;
10
    } while (*src);
11
    *dest = 0;
12
}

von Einer (Gast)


Lesenswert?

Und wenn man noch eine Zeile Code sparen will...
1
void convert(char *dest, char *src) 
2
{
3
    goto start;
4
    do {
5
        *dest++ = ','; *dest++ = ' ';
6
    start:
7
        *dest++ = '0'; *dest++ = 'x';
8
        *dest++ = *src++; *dest++ = *src++;
9
    } while (*src++);
10
    *dest = 0;
11
}

...lustig, oder?

von A. S. (Gast)


Lesenswert?

Einer schrieb:
> ...lustig, oder?

naja, das letzte ++ im Schleifenkörper muss dann weg.

von A. S. (Gast)


Lesenswert?

Einer schrieb:
> ...lustig, oder?

oder nur
1
void convert(char *d, char *s)
2
{
3
    do {
4
        *d++ = '0'; *d++ = 'x';
5
        *d++ = *s++; *d++ = *s++; 
6
    } while (*d = *s++ && *d++ = ',' && *d++ = ' ');
7
}

von Martin L. (tempusertempuser)


Lesenswert?

Und wie konvertiert man das in ein uint8_t Array?

von boah (Gast)


Lesenswert?

warum muss man DAS (einen weiteren String) jetzt plötzlich nach int 
konvertieren?

warum dieser Umweg?

von A. S. (Gast)


Lesenswert?

Martin L. schrieb:
> Und wie konvertiert man das in ein uint8_t Array?

naja, solange Du nichts zur eigentlichen Aufgabe sagst:
1
void convert(uint8_t *a, char *s)
2
{
3
    while(*s) {
4
        *a=     *s>='A'?*s  -'A':*s  -'0';
5
        *a*= 16;
6
        *a+++=*++s>='A'?*s++-'A':*s++-'0';
7
    } 
8
}

Ich bezweifle nur, dass Du mit den Antworten etwas anfangen kannst. Was 
spricht dagegen, die Aufgabe zu beschreiben?

von boah (Gast)


Lesenswert?

wozu schrieb:
> Zahlen extrahieren:
>    char str_in[] = "69:66:84:1A:0E:E7:E5:51:30:82:60:"
>                    "A7:27:F2:A5:54:56:B9:15:19";
>    char* end = str_in;
>    while (1) {
>       char* start = end;
>       long hex = strtol (start, &end, 16);
>       printf ("hex: %lx\n", hex);
>       if (!*end) {
>          break;
>       }
>       end++;
>    }

da steht es doch schon.

statt printf muss er die Werte halt in einem Array ablegen:
1
arr[i++]=hex;

von Andreas H. (ahz)


Lesenswert?

Martin Teuer schrieb:
> Hallo,
> ich habe eine FUnktion geschirben in c aber ich denke sie ist sehr
> kompliziert? Kann man diese einfacher schreieben??

Ja.
1
#include <stdio.h>
2
int main()
3
{
4
    puts("0x69, 0x66, 0x84, 0x1A, 0x0E, 0xE7, 0xE5, 0x51, 0x30, 0x82, 0x60, 0xA7, 0x27, 0xF2, 0xA5, 0x54, 0x56, 0xB9, 0x15, 0x19");
5
    return(0);
6
}

Erfüllt Deine Anforderung^^

/regards

von Dirk B. (dirkb2)


Lesenswert?

Martin L. schrieb:
> Und wie konvertiert man das in ein uint8_t Array?

Warum muss der ESP denn diese Hexziffern convertieren?

Muss das unbedingt im laufenden Betrieb sein oder reicht das zur compile 
time aus?

von Joachim B. (jar)


Lesenswert?

Martin Teuer schrieb:
> ich habe es versucht nun mit
> uint8_t finalout[20];
>   for (int i = 0

warum wählst du int für i?
kann denn dein i je negativ werden?
Beim Programmieren sollte man doch die Wahl der Variablen überdenken und 
passend wählen.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Machen wir das doch mal richtig. Mit einem richtigen Lexer:
1
%{
2
#include <stdio.h>
3
%}
4
%option noyywrap
5
6
hexnum [0-9a-fA-F][0-9a-fA-F]?
7
delimiter [:]
8
9
%%
10
11
{hexnum}    { printf("0x"); ECHO; }
12
{delimiter} { printf(", "); }
13
14
%%
15
16
int main(int argc, char* argv[]) {
17
  yylex() ;
18
  return 0;
19
}
1
lex -o hex.c hex.l

hex.c ist dann der C code.
1
gcc -o hex hex.c
2
echo 12:34:a7 | ./hex

von Rolf M. (rmagnus)


Lesenswert?

Joachim B. schrieb:
> Martin Teuer schrieb:
>> ich habe es versucht nun mit
>> uint8_t finalout[20];
>>   for (int i = 0
>
> warum wählst du int für i?

Besser wäre size_t, da sizeof auch diesen Typ zurückgibt.

> kann denn dein i je negativ werden?

Gegenfrage: Muss es einen Bereich von mehr als 2 Milliarden abdecken 
können?

von A. S. (Gast)


Lesenswert?

Rolf M. schrieb:
>Gegenfrage: Muss es einen Bereich von mehr als 2 Milliarden abdecken können?

Zumal ab 20 der ganze Code eh broken ist. Als wäre int/uint ein Problem, 
dass der TO schon hätte.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

1
#include <stdio.h>
2
#include <stdint.h>
3
#include <assert.h>
4
5
static inline int hex2num(unsigned char ch){
6
  if(ch >= '0' && ch <= '9')
7
    return ch - '0';
8
  if(ch >= 'A' && ch <= 'Z')
9
    return ch - 'A' + 10;
10
  if(ch >= 'a' && ch <= 'z')
11
    return ch - 'a' + 10;
12
  return -1;
13
}
14
15
int parsehex(size_t n, const char hexstr[n], uint8_t result[(n+3)/3]){
16
  if((n+1)%3)
17
    return -1;
18
  int res = 0;
19
  const char* in  = hexstr;
20
  uint8_t* out = result;
21
  while(1){
22
    int num;
23
    if((res=hex2num(in[0])) == -1)
24
      return -1;
25
    num  = res * 0x10;
26
    if((res=hex2num(in[1])) == -1)
27
      return -1;
28
    num += res;
29
    *out = num;
30
    if(!in[2]) break;
31
    if(in[2] != ':')
32
      return -1;
33
    in  += 3;
34
    out += 1;
35
  }
36
  return 0;
37
}
38
39
int main(){
40
  const char input[] = "69:66:84:1A:0E:E7:E5:51:30:82:60:A7:27:F2:A5:54:56:B9:15:19";
41
  uint8_t output[sizeof(input)/3];
42
  assert(parsehex(sizeof(input)-1, input, output) != -1);
43
  for(size_t i=0; i<sizeof(output); i++){
44
    if(i) printf(", ");
45
    printf("0x%.2X", output[i]);
46
  }
47
  puts("");
48
}

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.