# Telegrammdaten auslesen / String-Verarbeitung



## Semo (18 Juni 2009)

Mahlzeit,

ich bin atm dabei, mal wieder n bisserl mit C++ zu spielen. Eine andere Bezeichnung, meines Umgangs mit dem momentan Programm, wäre wohl nicht zutreffend 

Ich ärger mich dabei grad mit dem Auslesen der über Socket empfangenen Telegramme in die einzelnen Daten. Momentan greife ich dabei auf Left(), Mid() und Right() zurück, was bei knapp 30 Teilstrings schon ein wenig ausartet...

Ihr kennt nicht zufällig ne elegantere Möglichkeit und würdet mir diese verraten?

Die Telegrammaufteilung sieht etwa wie folgt aus: 
"AABBCCDDDD-EFFF-GGGG-HHHHIIJJJJ-KKKKL-MMMMN-OOOOP-QQQQR-usw"

Wobei es sich bei den Teildaten hauptsächlich um 2-4stellige Strings, aber auch um 2-4 stellige Ganzzahlen und einzelne ASCII Zeichen handelt.
Trennungszeichen wie die teilweise als Filler vorhandenen '-' stehen halt nicht komplett zur Verfügung. 

Ich habe schon überlegt ob es irgendwie möglich ist den ganzen Buffer in nen vorbereitetes Struct zu schmeißen, hatte damit allerdings bisher keinen Erfolg. Was auch daran liegen mag, dass ich keine Ahnung habe, wie ich den "<<" Operator richtig überladen muss...

Hilfe wird dankend angenommen


----------



## Human (18 Juni 2009)

Ich kann dir das in Pascal kurz runterschreiben:


```
var
  Tele: String; // dein Telegramm
  Res: Array of String; // dynamisches Array in das deine Teile eingefügt werden
const
  tz: Char = '-';
begin
  SetLength(Res,1); // Array auf 1 setzen
  for i := 1 to length(Tele) do // for-Schleife vom 1. Zeichen bis zum letzten Zeichen
  begin
    if Tele[i] = tz then // Prüfen, ob aktuelles Zeichen ein Trennzeichen ist
    begin
      SetLength(Res,length(Res)+1); // Array um eine Stelle erhöhen
    end
    else
    begin
      Res[high(Res)] := Res[high(Res)] + Tele[i]; // aktuelles Zeichen an das Ende des letzten Ergebnis-Strings hängen
    end;
  end;
end;
```
 
Ich kann nicht garantieren, dass das so geht, hab das nur schnell aus dem Kopf runtergeschrieben. Das musst du jetzt nurnoch in C++ übersetzen!


----------



## Semo (19 Juni 2009)

Semo schrieb:


> Mahlzeit,
> ...
> Die Telegrammaufteilung sieht etwa wie folgt aus:
> "AABBCCDDDD-EFFF-GGGG-HHHHIIJJJJ-KKKKL-MMMMN-OOOOP-QQQQR-usw"
> ...



Wie schon geschrieben, die Teilstrings sind nicht alle durch Trennzeichen getrennt, es sind keine sichtbahren Übergänge vorhanden.

Gemeint war, dass z.B. "AA", genau wie 'E' und "FFF" einzelne Teilstrings, bzw. Ganzzahlen/Chars sind 

Aber Danke Human


----------



## Human (19 Juni 2009)

Wenn die Zahlen fest drinstehen dann ist das ja kein Problem:

(ich schreibs wieder in Pascal)

```
Res[0] := '';
for i := 1 to 4 do
begin
  Res[0] := Res[0] + Tele[i];
end;
 
Res[1] := '';
for i := 5 to 6 do
begin
  Res[1] := Res[1] + Tele[i];
end;
 
...
```
 
Aber wenn die variabler Länge sind, dann würde ich den Programmierer des anderen Systems zusammenscheißen, dass er doch bitte überall die Trennzeichen reinmachen soll (würde ich dann auch bei statischer Länge machen)!


----------



## Semo (19 Juni 2009)

Ich möcht nicht undankbar klingen, bin ich zumindest net!
Aber... so ähnlich mach ichs momentan:


```
string sTele = cBuffer;
string sCast = sTele.substr(0, 2);
...
...
sCast = sTele.substr(2, 2);
...
...
sCast = sTele.substr(4, 2);
...
...
sCast = sTele.substr(6, 4);
...
usw.
```
Finde das ganze aber nicht alzu elegant gelöst...

am liebsten hätt ich halt so was in der Art:
[Wunschdenken]
struct tTele {
  char abc[2];  // Name Typ Wertebereich
  char def[2];  // Name Typ Wertebereich
  char ghi[4];  // Name Typ Wertebereich
  char jkl[2];  // Name Typ Wertebereich
  char mno[6];  // Name Typ Wertebereich
  char pqr;  // Name Typ Wertebereich
  char stu[3];  // Name Typ Wertebereich
  ...
};
tTele telegramm;
telegramm << cBuffer;
[/Wunschdenken]

Mein Gedanke ist halt, das ich bei Änderungen an der Telegrammdefinition nicht dass Programm ändern muss sondern nur Zentral nen Dokuimentierten Aufbau...
Und das ganze soll auch nicht darauf hinauslaufen:

```
string sTele = cBuffer;
string sCast = sTele.substr(iStartXY, iLaengeXY);
...
...
sCast = sTele.substr(iStartYZ, iLaengeYZ);
...
usw.
```
Sagen wir einfach, ich hab etwas das funktioniert... aber, meiner Vermutung nach in jeder Hinsicht optimiert werden könnte.

Könnt sein, dass ich heute nicht mehr rein schaue, weil kaputt 
Schönen Abend!


----------



## Thomas_v2.1 (19 Juni 2009)

So richtig verstanden habe ich dein Telegramm zwar nicht, aber wenn du das so habe willst kannst du doch den << Operator überladen.

Vom Prinzip:

```
class Tele {
    public:
        char abc[2];
        char def[2];

        Tele operator<<(const std::string tele)
        {
            if (tele.length() < 5) throw "Telegramm zu kurz";
            memcpy(abc, tele.substr(0, 2).c_str(), sizeof(abc));
            memcpy(def, tele.substr(3, 2).c_str(), sizeof(def));
        }                        
};
```
Dann kannst du das so aufrufen wie du das geschrieben hast:

```
Tele t;
std::string buff = "abcdefgh";
try {
    t << buff;
} catch (const char *str) {
    std::cout << "Fehler :" << str << std::endl;
}
std::cout << " t.abc[0],[1] =  " << t.abc[0] << t.abc[1] << std::endl;
std::cout << " t.def[0],[1] =  " << t.def[0] << t.def[1] << std::endl;
```


----------



## Semo (19 Juni 2009)

Werd das ganze morgen mal probieren, klingt auf jedenfall ganz nach dem was ich suche 

DANKE!


----------



## Thomas_v2.1 (20 Juni 2009)

Um im C++ Style zu bleiben sollte man anstatt memcpy die copy Methode der String Klasse verwenden:

```
Tele operator<<(const std::string tele)
{
    if (tele.length() < 5) throw "Telegramm zu kurz";
    tele.copy(abc, sizeof(abc), 0);
    tele.copy(def, sizeof(def), 3);
}
```
Diese prüft zudem auch, dass nicht mehr Zeichen aus dem String kopiert werden als er lang ist.


----------



## pvbrowser (21 Juni 2009)

> "AABBCCDDDD-EFFF-GGGG-HHHHIIJJJJ-KKKKL-MMMMN-OOOOP-QQQQR-usw"

sscanf(telegram,"%02d%02d%02d%04d-%1d%03d-%04d", 
                        &aa, &bb, &cc,  &dd,   &ee,&ff,   &gg);

usw.


----------

