Hilfe nötig für vereinfachung einer c Funktion

Gast #6797427
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
}
Gast #6797527
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
Gast #6797549
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?
#6797551
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
#6797568
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>
#6797583
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
Gast #6797590
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).
#6797594
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.
Gast #6797653
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.
Gast #6797723
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.
Gast #6797887
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?
#6797917
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.
(Firma: Schweigstill IT) Persönliche Seite #6797941
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.
Gast #6797953
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.
Gast #6797979
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
}
Gast #6797983
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?
Gast #6798161
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?
Gast #6798180
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;
#6798210
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
Gast #6798265
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
Gast #6798941
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
}

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