Forum: PC-Programmierung Delphi / c code string/byte packetweise verarbeiten


von ;-) (Gast)


Lesenswert?

hi
manchmal sieht man vor lauter wald den baum nicht mehr,
das passiert die tage eben bei mir daher ganz von unten herauf gefragt:
ich habe:
ein gesamtpaket 50 byte
eine paketmaxsize von 16 byte
einen tag ( 0 oder 1 ) der mir sagt, ob ich ausfüllen soll oder nicht

jetzt will ich paketweise printen
und zum schluss das paket mit den 2 byte
wenn der tag 1 ist, dann wie es ist, also nur 2 byte
wenn der tah 0 ist, dann mit 14 \0 ausfüllen.


es würde mir helfen den ansatz in pasacl / delphi zu haben
wer es mir per c code erklären kann, wäre auch super.
im moment habe ich eine festgefahrene schleife im kopf,
ich bin seit tagen an der schleife dran, bekomm die aber nicht hin
ein ansatz wie dieser ist ein freitagslacher:

unsigned integer gesamtpaket,paketmaxsize=16,tag=1,i;

for (i=0; i< paketmaxsize ; i++ ) {

 sprint("%c ", gesamtpaket[i]);    // ok bis hier hin die ersten 16 
bytes

}


wenn ich jetzt anfange die bytes abzuzählen und dann entsprechende 
weitere schleifen einbaue, dann hab ich bei einem 10000er gesamtpaket 
ellenlangen code, wie schreibe ich da eine weitere bedinung ein? eine 
weitere variable dir mir die (vollen) durchläufe sagt, und den letzten 
dann mit einer

else
und die restlichen 2 bytes je nach tag dann mit oder ohne nullen 
aufgefüllt printed..

ist das wochenende nóch zu retten?

:)

von Musterlösungsservice Nord (Gast)


Lesenswert?

http://ideone.com/JkF6Vb
Falls das eine Hausaufgabe war, bitte 5€ an eine wohltätige Einrichtung 
spenden.

von ;-) (Gast)


Lesenswert?

1
unsigned int i,x, pack=0, packetsz=3;
2
unsigned char packet[8] = "abcdefgh";
3
4
for (i=0; i<(sizeof(packet));i++) {
5
6
   for (x=pack; x<packetsz+pack;x++){
7
     
8
       printf("%c",packet[x]);
9
10
  //rumpf zweite for schleife
11
  }
12
13
if (pack < (sizeof(packet))){
14
    pack += packetsz;
15
    printf("\r\n")        // jeder blocksize sein \r\n
16
 }
17
 else
18
 break;                   // alle pakete da.
19
20
//rumpf erste for schleife
21
}


ok hab es jetzt doch noch gebracht, geht das auch einfacher?
vieleicht versteht man mich jetzt besser ;-)

von ;-) (Gast)


Lesenswert?

Musterlösungsservice Nord schrieb:
> http://ideone.com/JkF6Vb
> Falls das eine Hausaufgabe war, bitte 5€ an eine wohltätige Einrichtung
> spenden.

oh danke danke für deine mühen!!
, das hab ich jetzt zu spät gesehen.
nein das war keine hausaufgabe ;-)
ich drück mich schon lange vor c und solchen übungen.
aber habs letztes jahr mit dem esp dann doch anfangen müssen
weil ich den so ins herz geschlossen habe ;-)
manche sachen fallen leichter, wenn ich einen ansatz habe.
jetzt muss ich nur noch den tag einbringen.
danke dir!!!
;-)

von Hans-Georg L. (h-g-l)


Lesenswert?

Wenn Tag = 1, ist es draussen hell
und bei Tag = 0 nennt man es nennt Nacht ;)

Wenn du das Problem mal richtig formulieren kannst, dann hast du auch 
die Lösung.

von ;-) (Gast)


Lesenswert?

werde aber trotzdem 5eur jemanden zukommen lassen.
so fair bin ich dann schon. danke!
der ansatz mit dem ausfüllen ( tag ) gefällt mir.

danke dir nochmals für deine mühen!
;-)

von ;-) (Gast)


Lesenswert?

Hans-Georg Lehnard schrieb:
> und bei Tag = 0 nennt man es nennt Nacht ;)

das ist aber doppelt formuliert ;-)

>
> Wenn du das Problem mal richtig formulieren kannst, dann hast du auch
> die Lösung.

du hast das gleiche problem wie ich ? ;-)
dann bin ich ja nicht allein ;-)
ich weiss, manchmal liegt in der formulierung schon der lösungsansatz,
es ist nicht leicht, zu formulieren, was man eigentlich will, wenn nicht 
weiss, was man will bzw wohin man eigentlich will..siehst, gehts schon 
wieder los ;-)
ich schleich mich .. ;-)
danke!!

von Musterlösungsservice Nord (Gast)


Lesenswert?

Im folgenden mal der Entwicklungsprozess mittels 
printf-test-driven-development. Immer schrittweise in Test und Lösung 
aufgeteilt.

##############################################################

Test 1
Bottom up. Wir fangen mit den Einzelpaketen an.

Aufgabe: ganz simpel, erstmal nur ein Subpaket einer gewissen Länge 
ausgeben.
1
#include <stdio.h>
2
#include <inttypes.h>
3
4
// als C-erfahrener wissen wir, dass solche Daten üblicherweise als Adresse + Laenge uebergeben werden.
5
void print_subpacket(uint8_t* p, size_t len)
6
{
7
// TODO
8
}
9
10
// 
11
int main(void)
12
{
13
    uint8_t einzeln[] = {1,2, 3};
14
    size_t laenge_einzeln = sizeof(einzeln) / sizeof(einzeln[0]); 
15
    print_subpacket(einzeln, laenge_einzeln);
16
    return 0;
17
}
Compiliert, tut aber noch nichts sinnvolles. Das gilt es zu beheben.


##############################################################

Lösung 1.
1
#include <stdio.h>
2
#include <inttypes.h>
3
4
// parameter sinnvoller benannt
5
void print_subpacket(uint8_t* subpacket, size_t subpacket_length)
6
{
7
    printf("Einzelpaket: ");
8
    size_t i;
9
    for(i=0; i < subpacket_length; ++i)
10
        printf("%4d", subpacket[i]);
11
    printf("\n");
12
}
13
14
int main(void)
15
{
16
    uint8_t einzeln[] = {1,2, 3};
17
    size_t laenge_einzeln = sizeof(einzeln) / sizeof(einzeln[0]); 
18
    print_subpacket(einzeln, laenge_einzeln);
19
20
    //mehr tests nachgetragen, nachdem der erste ging:
21
    print_subpacket(einzeln, 1);
22
    print_subpacket(einzeln, 2);
23
24
    //sonderfall:
25
    print_subpacket(einzeln, 0);
26
27
    print_subpacket(einzeln, 4); //kracht oder macht murks.
28
    //dieser test mach keinen sinn, das koennen wir in
29
    //print_subpacket nicht abfangen. Es ist C hier.
30
31
    return 0;
32
}
Passt. Erste Aufgabe gelöst.

von Musterlösungsservice Nord (Gast)


Lesenswert?

Nächste Aufgabe: Auffüllen auf eine bestimmte Länge.

########################################

Test 2:
1
#include <stdio.h>
2
#include <inttypes.h>
3
#include <stdbool.h>
4
5
void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
6
{
7
    printf("Einzelpaket: ");
8
    size_t i;
9
    for(i=0; i < subpacket_length; ++i)
10
        printf("%4d", subpacket[i]);
11
    printf("\n");
12
    //TODO: auffuellen
13
}
14
15
16
int main(void)
17
{
18
    uint8_t einzeln[] = {1,2, 3};
19
    size_t laenge_einzeln = sizeof(einzeln) / sizeof(einzeln[0]); 
20
    size_t laenge_nominal = 5;
21
    // jetzt  ohne und mit auffuellen auf eine andere laenge:
22
    print_subpacket(einzeln, laenge_einzeln, laenge_nominal, false); //geht noch
23
    print_subpacket(einzeln, laenge_einzeln, laenge_nominal, true); // geht noch nicht
24
25
    return 0;
26
}
Compiliert, aber füllt noch nicht auf.


#########################################
Lösung 2:
1
#include <stdio.h>
2
#include <inttypes.h>
3
#include <stdbool.h>
4
5
void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
6
{
7
    printf("Einzelpaket: ");
8
    size_t i;
9
    for(i=0; i < subpacket_length; ++i)
10
        printf("%4d", subpacket[i]);
11
    //wir wollen insgesamt nominal_length-mal ausgeben, also einfach weiterloopen und
12
    // Fuellzeichen schreiben, bis nominal_length erreicht ist:
13
    if(fill_to_length)     
14
        for( ; i < nominal_length; ++i)
15
            printf("    #");
16
    // Die Schleifenvariable i von oben zu recyclen und damit weiterzuloopen ist hässlich 
17
    // und fehleranfällig, aber bei einer Funktion mit ein paar zeilen zu rechtfertigen.
18
    // Klarer wäre es, die Differenz delta zwischen geschriebenen und zu schreibenden Werten
19
    // zu berechnen und delta mal Füllzeichen zu schreiben.
20
    printf("\n");
21
}
22
23
int main(void)
24
{
25
    uint8_t einzeln[] = {1,2, 3};
26
    size_t laenge_einzeln = sizeof(einzeln) / sizeof(einzeln[0]); 
27
    size_t laenge_nominal = 5;
28
    // jetzt mit und ohne auffuellen auf eine andere laenge:
29
    print_subpacket(einzeln, laenge_einzeln, laenge_nominal, false); 
30
    print_subpacket(einzeln, laenge_einzeln, laenge_nominal, true); //geht jetzt auch.
31
    return 0;
32
}

Jetzt sollte man sich Gedanken machen, was passiert, wenn jemand 
print_subpacket() mit falschen Werten aufruft und  packet_length größer 
als nominal_length ist. Bei printf ist das egal; wenn man in einen 
anderen buffer o.ä. schreibt, der nur nominal_length groß ist, oder die 
bytes in ein externes Schieberegister schiebt,  evtl. etwas schlimmes. 
Ich ignoriere das Problem erstmal.

print_subpacket() ist jetzt fertig, getestet und wird nicht mehr 
angefasst, solange keine anderen Anforderungen dazukommen.

von Musterlösungsservice Nord (Gast)


Lesenswert?

Nächste Aufgabe: Das große Paket zerlegen.

#########################################

Test 3:
1
#include <stdio.h>
2
#include <inttypes.h>
3
#include <stdbool.h>
4
5
void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
6
{
7
    printf("Einzelpaket: ");
8
    size_t i;
9
    for(i=0; i < subpacket_length; ++i)
10
        printf("%4d", subpacket[i]);
11
    if(fill_to_length)     
12
        for( ; i < nominal_length; ++i)
13
            printf("    #");
14
    printf("\n");
15
}
16
17
// die sache mit Zeiger+Länge hatten wir oben schon.
18
void print_packet(uint8_t* packet, size_t packet_length, size_t subpacket_length)
19
{
20
//TODO irgendwie zerlegen und print_subpacket aufrufen
21
}
22
23
int main(void)
24
{
25
    //testfall:
26
    uint8_t bigpacket[] = {1,2,3,4,5,6,7,8,9,0};
27
    size_t bigpacket_length = sizeof(bigpacket) / sizeof(bigpacket[0]); 
28
    size_t subpacket_length = 3;
29
    print_packet(bigpacket, bigpacket_length, subpacket_length); //geht noch nicht
30
    return 0;
31
}
Compiliert, aber tut noch nichts.


###################################

Zwischenschritt 3:
1
#include <stdio.h>
2
#include <inttypes.h>
3
#include <stdbool.h>
4
5
void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
6
{
7
    printf("Einzelpaket: ");
8
    size_t i;
9
    for(i=0; i < subpacket_length; ++i)
10
        printf("%4d", subpacket[i]);
11
    if(fill_to_length)     
12
        for( ; i < nominal_length; ++i)
13
            printf("    #");
14
    printf("\n");
15
}
16
17
18
void print_packet(uint8_t* packet, size_t packet_length, size_t subpacket_length)
19
{
20
    // siehe unten, gefunden durch den letzten test.
21
    // ohne die abfrage gibt es eine endlosschleife.
22
    if (subpacket_length == 0)
23
        return; 
24
        
25
    // zum zerlegen springen wir an die stellen im packet, an denen das neue
26
    // subpacket beginnt
27
    size_t idx;
28
    for(idx = 0; idx < packet_length; idx += subpacket_length)
29
    {
30
        uint8_t* subpacket = packet + idx;
31
        // erstmal die erste stelle im subpacket ausgeben und sehen, ob wir
32
        // an den richtigen stellen landen.
33
        printf("%d\n", *subpacket);
34
    }
35
}
36
37
int main(void)
38
{
39
    uint8_t bigpacket[] = {1,2,3,4,5,6,7,8,9,0};
40
    size_t bigpacket_length = sizeof(bigpacket) / sizeof(bigpacket[0]); 
41
    printf("in 3er zerlegen\n");
42
    print_packet(bigpacket, bigpacket_length, 3);
43
44
    //mehr testfälle nachgetragen:
45
    printf("in 5er zerlegen\n");
46
    print_packet(bigpacket, bigpacket_length, 5);
47
    printf("in 1er zerlegen\n");
48
    print_packet(bigpacket, bigpacket_length, 1);
49
50
    //jetzt wird es interessant:
51
    printf("in 13er zerlegen\n");
52
    print_packet(bigpacket, bigpacket_length, 13);
53
    //geht.
54
55
    //jetzt wird es noch interessanter
56
    printf("in 0er zerlegen\n");
57
    print_packet(bigpacket, bigpacket_length, 0);
58
    // endlosschleife, behoben durch erste abfrage in print_packet()
59
    
60
    printf("mal sehen\n");
61
    print_packet(bigpacket, 0, 42);
62
  
63
    return 0;
64
}
Der erste Ansatz zum zerlegen sieht schonmal gut aus.

##########################################################

Lösung 3

Weiter geht's. Nächster Schritt: Die Länge der Subpackets ermitteln und
print_subpacket aufrufen.
1
#include <stdio.h>
2
#include <inttypes.h>
3
#include <stdbool.h>
4
5
6
size_t min(size_t a, size_t b)
7
{
8
    return a < b ? a : b;
9
}
10
11
void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
12
{
13
    printf("Einzelpaket: ");
14
    size_t i;
15
    for(i=0; i < subpacket_length; ++i)
16
        printf("%4d", subpacket[i]);
17
    if(fill_to_length)     
18
        for( ; i < nominal_length; ++i)
19
            printf("    #");
20
    printf("\n");
21
}
22
23
void print_packet(uint8_t* packet, size_t packet_length, size_t subpacket_length)
24
{
25
    if (subpacket_length == 0)
26
        return; 
27
    size_t idx;
28
    for(idx = 0; idx < packet_length; idx += subpacket_length)
29
    {
30
        uint8_t* subpacket = packet + idx;
31
        // wie lang ist das subpacket?
32
        //entweder subpacket_length oder (am ende) soviel wie noch uebrigbleibt, falls das weniger ist.
33
        size_t total_bytes_left =  packet_length - idx;
34
        size_t actual_subpacket_length = min(subpacket_length, total_bytes_left);
35
        print_subpacket(subpacket, actual_subpacket_length, subpacket_length, true);
36
    }
37
}
38
39
int main(void)
40
{
41
    uint8_t bigpacket[] = {1,2,3,4,5,6,7,8,9,0};
42
    size_t bigpacket_length = sizeof(bigpacket) / sizeof(bigpacket[0]); 
43
44
    printf("in 3er zerlegen\n");
45
    print_packet(bigpacket, bigpacket_length, 3);
46
47
    printf("in 5er zerlegen\n");
48
    print_packet(bigpacket, bigpacket_length, 5);
49
50
    printf("in 1er zerlegen\n");
51
    print_packet(bigpacket, bigpacket_length, 1);
52
53
    printf("in 13er zerlegen\n");
54
    print_packet(bigpacket, bigpacket_length, 13);
55
56
57
    printf("in 0er zerlegen\n");
58
    print_packet(bigpacket, bigpacket_length, 0);
59
    
60
    printf("mal sehen\n");
61
    print_packet(bigpacket, 0, 42);
62
  
63
    return 0;
64
}
Passt. Die nächste Anforderung der Auswertung des Tags spare ich mir 
jetzt.

von Robert L. (lrlr)


Lesenswert?

lol, SO programmierst du ??

von :-) (Gast)


Lesenswert?

Robert L. schrieb:
> lol, SO programmierst du ??

jetzt würde es mich aber arg interessieren wie du das angehst.
immerhin ist das ja nicht gerade eine unbekannte sache sondern eine 
altägliche beispiele wären:

uart buffer
ring buffer
fifo
usw
also?
wie machst du es?

;-)

bin gespannt auf deinen vierzeiler, mehr darfst nicht schreiben mit so 
einer 'grossen klappe' ;-)

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.