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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von ;-) (Gast)


Bewertung
0 lesenswert
nicht 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)


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

von ;-) (Gast)


Bewertung
0 lesenswert
nicht lesenswert

unsigned int i,x, pack=0, packetsz=3;
unsigned char packet[8] = "abcdefgh";

for (i=0; i<(sizeof(packet));i++) {

   for (x=pack; x<packetsz+pack;x++){
     
       printf("%c",packet[x]);

  //rumpf zweite for schleife
  }

if (pack < (sizeof(packet))){
    pack += packetsz;
    printf("\r\n")        // jeder blocksize sein \r\n
 }
 else
 break;                   // alle pakete da.

//rumpf erste for schleife
}



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

von ;-) (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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.
#include <stdio.h>
#include <inttypes.h>

// als C-erfahrener wissen wir, dass solche Daten üblicherweise als Adresse + Laenge uebergeben werden.
void print_subpacket(uint8_t* p, size_t len)
{
// TODO
}

// 
int main(void)
{
    uint8_t einzeln[] = {1,2, 3};
    size_t laenge_einzeln = sizeof(einzeln) / sizeof(einzeln[0]); 
    print_subpacket(einzeln, laenge_einzeln);
    return 0;
}
Compiliert, tut aber noch nichts sinnvolles. Das gilt es zu beheben.


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

Lösung 1.
#include <stdio.h>
#include <inttypes.h>

// parameter sinnvoller benannt
void print_subpacket(uint8_t* subpacket, size_t subpacket_length)
{
    printf("Einzelpaket: ");
    size_t i;
    for(i=0; i < subpacket_length; ++i)
        printf("%4d", subpacket[i]);
    printf("\n");
}

int main(void)
{
    uint8_t einzeln[] = {1,2, 3};
    size_t laenge_einzeln = sizeof(einzeln) / sizeof(einzeln[0]); 
    print_subpacket(einzeln, laenge_einzeln);

    //mehr tests nachgetragen, nachdem der erste ging:
    print_subpacket(einzeln, 1);
    print_subpacket(einzeln, 2);

    //sonderfall:
    print_subpacket(einzeln, 0);

    print_subpacket(einzeln, 4); //kracht oder macht murks.
    //dieser test mach keinen sinn, das koennen wir in
    //print_subpacket nicht abfangen. Es ist C hier.

    return 0;
}
Passt. Erste Aufgabe gelöst.

von Musterlösungsservice Nord (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Nächste Aufgabe: Auffüllen auf eine bestimmte Länge.

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

Test 2:
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
{
    printf("Einzelpaket: ");
    size_t i;
    for(i=0; i < subpacket_length; ++i)
        printf("%4d", subpacket[i]);
    printf("\n");
    //TODO: auffuellen
}


int main(void)
{
    uint8_t einzeln[] = {1,2, 3};
    size_t laenge_einzeln = sizeof(einzeln) / sizeof(einzeln[0]); 
    size_t laenge_nominal = 5;
    // jetzt  ohne und mit auffuellen auf eine andere laenge:
    print_subpacket(einzeln, laenge_einzeln, laenge_nominal, false); //geht noch
    print_subpacket(einzeln, laenge_einzeln, laenge_nominal, true); // geht noch nicht

    return 0;
}
Compiliert, aber füllt noch nicht auf.


#########################################
Lösung 2:
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
{
    printf("Einzelpaket: ");
    size_t i;
    for(i=0; i < subpacket_length; ++i)
        printf("%4d", subpacket[i]);
    //wir wollen insgesamt nominal_length-mal ausgeben, also einfach weiterloopen und
    // Fuellzeichen schreiben, bis nominal_length erreicht ist:
    if(fill_to_length)     
        for( ; i < nominal_length; ++i)
            printf("    #");
    // Die Schleifenvariable i von oben zu recyclen und damit weiterzuloopen ist hässlich 
    // und fehleranfällig, aber bei einer Funktion mit ein paar zeilen zu rechtfertigen.
    // Klarer wäre es, die Differenz delta zwischen geschriebenen und zu schreibenden Werten
    // zu berechnen und delta mal Füllzeichen zu schreiben.
    printf("\n");
}

int main(void)
{
    uint8_t einzeln[] = {1,2, 3};
    size_t laenge_einzeln = sizeof(einzeln) / sizeof(einzeln[0]); 
    size_t laenge_nominal = 5;
    // jetzt mit und ohne auffuellen auf eine andere laenge:
    print_subpacket(einzeln, laenge_einzeln, laenge_nominal, false); 
    print_subpacket(einzeln, laenge_einzeln, laenge_nominal, true); //geht jetzt auch.
    return 0;
}

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)


Bewertung
0 lesenswert
nicht lesenswert
Nächste Aufgabe: Das große Paket zerlegen.

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

Test 3:
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
{
    printf("Einzelpaket: ");
    size_t i;
    for(i=0; i < subpacket_length; ++i)
        printf("%4d", subpacket[i]);
    if(fill_to_length)     
        for( ; i < nominal_length; ++i)
            printf("    #");
    printf("\n");
}

// die sache mit Zeiger+Länge hatten wir oben schon.
void print_packet(uint8_t* packet, size_t packet_length, size_t subpacket_length)
{
//TODO irgendwie zerlegen und print_subpacket aufrufen
}

int main(void)
{
    //testfall:
    uint8_t bigpacket[] = {1,2,3,4,5,6,7,8,9,0};
    size_t bigpacket_length = sizeof(bigpacket) / sizeof(bigpacket[0]); 
    size_t subpacket_length = 3;
    print_packet(bigpacket, bigpacket_length, subpacket_length); //geht noch nicht
    return 0;
}
Compiliert, aber tut noch nichts.


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

Zwischenschritt 3:
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
{
    printf("Einzelpaket: ");
    size_t i;
    for(i=0; i < subpacket_length; ++i)
        printf("%4d", subpacket[i]);
    if(fill_to_length)     
        for( ; i < nominal_length; ++i)
            printf("    #");
    printf("\n");
}


void print_packet(uint8_t* packet, size_t packet_length, size_t subpacket_length)
{
    // siehe unten, gefunden durch den letzten test.
    // ohne die abfrage gibt es eine endlosschleife.
    if (subpacket_length == 0)
        return; 
        
    // zum zerlegen springen wir an die stellen im packet, an denen das neue
    // subpacket beginnt
    size_t idx;
    for(idx = 0; idx < packet_length; idx += subpacket_length)
    {
        uint8_t* subpacket = packet + idx;
        // erstmal die erste stelle im subpacket ausgeben und sehen, ob wir
        // an den richtigen stellen landen.
        printf("%d\n", *subpacket);
    }
}

int main(void)
{
    uint8_t bigpacket[] = {1,2,3,4,5,6,7,8,9,0};
    size_t bigpacket_length = sizeof(bigpacket) / sizeof(bigpacket[0]); 
    printf("in 3er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 3);

    //mehr testfälle nachgetragen:
    printf("in 5er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 5);
    printf("in 1er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 1);

    //jetzt wird es interessant:
    printf("in 13er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 13);
    //geht.

    //jetzt wird es noch interessanter
    printf("in 0er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 0);
    // endlosschleife, behoben durch erste abfrage in print_packet()
    
    printf("mal sehen\n");
    print_packet(bigpacket, 0, 42);
  
    return 0;
}
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.
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>


size_t min(size_t a, size_t b)
{
    return a < b ? a : b;
}

void print_subpacket(uint8_t* subpacket, size_t subpacket_length, size_t nominal_length, bool fill_to_length)
{
    printf("Einzelpaket: ");
    size_t i;
    for(i=0; i < subpacket_length; ++i)
        printf("%4d", subpacket[i]);
    if(fill_to_length)     
        for( ; i < nominal_length; ++i)
            printf("    #");
    printf("\n");
}

void print_packet(uint8_t* packet, size_t packet_length, size_t subpacket_length)
{
    if (subpacket_length == 0)
        return; 
    size_t idx;
    for(idx = 0; idx < packet_length; idx += subpacket_length)
    {
        uint8_t* subpacket = packet + idx;
        // wie lang ist das subpacket?
        //entweder subpacket_length oder (am ende) soviel wie noch uebrigbleibt, falls das weniger ist.
        size_t total_bytes_left =  packet_length - idx;
        size_t actual_subpacket_length = min(subpacket_length, total_bytes_left);
        print_subpacket(subpacket, actual_subpacket_length, subpacket_length, true);
    }
}

int main(void)
{
    uint8_t bigpacket[] = {1,2,3,4,5,6,7,8,9,0};
    size_t bigpacket_length = sizeof(bigpacket) / sizeof(bigpacket[0]); 

    printf("in 3er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 3);

    printf("in 5er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 5);

    printf("in 1er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 1);

    printf("in 13er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 13);


    printf("in 0er zerlegen\n");
    print_packet(bigpacket, bigpacket_length, 0);
    
    printf("mal sehen\n");
    print_packet(bigpacket, 0, 42);
  
    return 0;
}
Passt. Die nächste Anforderung der Auswertung des Tags spare ich mir 
jetzt.

von Robert L. (lrlr)


Bewertung
0 lesenswert
nicht lesenswert
lol, SO programmierst du ??

von :-) (Gast)


Bewertung
0 lesenswert
nicht 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' ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.