Forum: PC-Programmierung Beschnittene Zeichenabfolge in string gesucht


von Christian S. (chris72160)


Lesenswert?

Hallo,

wenn ich einen string habe, in den ich kontinuierlich reinschreibe, wie 
kann ich eine gewünschte Zeichenabfolge auch dann finden, wenn sie sich 
in den Randbereichen des strings befindet.

Beispiel:

Stringgröße: 10
Aktueller Inhalt: d e r 0 0 0 0 K i n
Gesuchte Zeichenabfolge: Kinder

Gruß Chris

von Peter II (Gast)


Lesenswert?

Christian Stielz schrieb:
> wenn sie sich
> in den Randbereichen des strings befindet.

einfach umrechnen

if s[x] = 'K' &&
   s[(x+1) % maxlen] = 'i'
   s[(x+2) % maxlen] = 'n'
   s[(x+3) % maxlen] = 'd'
   s[(x+4) % maxlen] = 'e'
....


das was du unter string verstehst ist ein ringpuffer.

von Christian S. (chris72160)


Lesenswert?

Ah- ok.

"maxlen" kannte ich noch nicht.

Werd mal googlen. ;)

Gruß Chris

von Peter II (Gast)


Lesenswert?

Christian Stielz schrieb:
> "maxlen" kannte ich noch nicht.

das gibt es auch nicht. Dort sollte der größe des Ringpuffers 
eingetragen weden. Entweder mit einem DEFINE oder mit sizeof()

von Christian S. (chris72160)


Lesenswert?

Würde es für mein oben angegebenes Beispiel reichen, anstatt maxlen eine 
10 einzutragen?

Gruß Chris

von amateur (Gast)


Lesenswert?

Bei einem Ringpuffer musst Du die gleiche Strategie zum Lesen benutzen, 
wie die Schreibroutine.

U.U. kann es nämlich sein, das sich, trotz anderer "Ansicht" die 
Zeichenkette: "Kinder" gar nicht im Puffer befindet.

Zugegeben das Beispiel ist wohl an den Haaren herbei gezogen, aber es 
könnten auch das Ende von Wun"der" und der Anfang von "Kin"haken sein.

Eine Interpretation ist ohne genaue Kenntnis von Anfang und Ende nicht 
möglich.

von Peter II (Gast)


Lesenswert?

Christian Stielz schrieb:
> Würde es für mein oben angegebenes Beispiel reichen, anstatt maxlen eine
> 10 einzutragen?

ja aber schön ist es halt nicht.

von Christian S. (chris72160)


Lesenswert?

Argh- bekomme es nicht hin. :(

if ((commandbuffer[i] = 'L') &&
   (c[(commandbuffer+1) % 7] = 'i')
   (c[(commandbuffer+2) % 7] = 'b')
   (c[(commandbuffer+3) % 7] = 'e')
   (c[(commandbuffer+4) % 7] = 'l')
   (c[(commandbuffer+4) % 7] = 'l')
   (c[(commandbuffer+4) % 7] = 'e'))
   {
     Serial.println("Libelle gefunden");
     i = 0;
     memset(commandbuffer,0,sizeof(commandbuffer));
   }

von jmp (Gast)


Lesenswert?

Probiers mal so:

if ((commandbuffer[i] == 'L') &&
   (commandbuffer[(i+1) % 7] == 'i') &&
   (commandbuffer[(i+2) % 7] == 'b') &&
   (commandbuffer[(i+3) % 7] == 'e') &&
   (commandbuffer[(i+4) % 7] == 'l') &&
   (commandbuffer[(i+5) % 7] == 'l') &&
   (commandbuffer[(i+6) % 7] == 'e'))
   {
     Serial.println("Libelle gefunden");
     i = 0;
     memset(commandbuffer,0,sizeof(commandbuffer));
   }

= ist eine Zuweisung,
== ein Vergleich

--jmp

von Christian S. (chris72160)


Lesenswert?

Hey, danke.

Scheint aber noch immer nicht zu funktionieren, obwohl keine 
Fehlermeldung auftaucht.

Hier mal der komplette Code:

char commandbuffer[7];
char c;
int i=0;

void setup()
{
  Serial.begin(9600);
  Serial3.begin(19200);
  Serial3.setTimeout(0);
}

void loop()
{

//  <- An dieser Stelle steht mein kompletter restlicher Code, der auch 
noch verarbeitet werden muss.

  if (Serial3.available())
  {
    c=Serial3.read();
    commandbuffer[i] = c;
    i++;
  }
/*  if (strcmp(commandbuffer,"Libelle")==0)
  {
    Serial.println("Libelle gefunden");
    i = 0;
    memset(commandbuffer,0,sizeof(commandbuffer));
  }*/
  if ((commandbuffer[i] == 'L') &&
   (commandbuffer[(i+1) % 7] == 'i') &&
   (commandbuffer[(i+2) % 7] == 'b') &&
   (commandbuffer[(i+3) % 7] == 'e') &&
   (commandbuffer[(i+4) % 7] == 'l') &&
   (commandbuffer[(i+5) % 7] == 'l') &&
   (commandbuffer[(i+6) % 7] == 'e'))
   {
     Serial.println("Libelle gefunden");
     i = 0;
     memset(commandbuffer,0,sizeof(commandbuffer));
   }
}

von jmp (Gast)


Lesenswert?

Initialisiere mal oben commandbuffer direkt:

char commandbuffer[7] = {"Libelle"};

und kommentiere das Einlesen des Zeichens vorübergehend aus.

Was passiert dann?

von Mik (Gast)


Lesenswert?

Christian Stielz schrieb:

//Schreib hier am Anfang mal
#define MAXLEN 7

 // damit machst du es Dir einfacher die Pufferlänge zu verändern.
>
> char commandbuffer[MAXLEN];
dann hier MAXLEN

>
> void loop()
> {
>
> //  <- An dieser Stelle steht mein kompletter restlicher Code, der auch
> noch verarbeitet werden muss.
>
>   if (Serial3.available())
>   {
>     c=Serial3.read();
>     commandbuffer[i] = c;

>     i++;
 Hier muß
  i = (i+1) % MAXLEN;
  sonst hast d upuggerüberlauf


>   }
> /*  if (strcmp(commandbuffer,"Libelle")==0)
>   {
>     Serial.println("Libelle gefunden");
>     i = 0;
>     memset(commandbuffer,0,sizeof(commandbuffer));
>   }*/


>   if ((commandbuffer[i] == 'L') &&
>    (commandbuffer[(i+1) % 7] == 'i') &&
>    (commandbuffer[(i+2) % 7] == 'b') &&
>    (commandbuffer[(i+3) % 7] == 'e') &&
>    (commandbuffer[(i+4) % 7] == 'l') &&
>    (commandbuffer[(i+5) % 7] == 'l') &&
>    (commandbuffer[(i+6) % 7] == 'e'))
    die 7 immer durch MAXLEN ersetzten

>    (commandbuffer[(i+1) % MAXLEN] == 'i') &&

 Du mußt eine eigenes i nehmen, also z.B. j
 da du ab i abragst ist maximal der erste Buchstabe da, der Rest ist 
noch gar nicht angekommen, oder rückwärtsabfragen, sprich bei i ist das 
'e', bei i-1 das 'l' usw

von Mik (Gast)


Lesenswert?

>d upuggerüberlauf
=du Pufferüberlauf,

 sry kan nnicht esitieren

von amateur (Gast)


Lesenswert?

@Christian

Um himmels Wilhelm!

Wann beschäftigst Du Dich endlich mal mit der Funktion des Ringpuffers?

Wie ich oben, in meinem Post bereits angedeutet habe, wird das so, wie 
Ihr euch das Denkt, nichts.

Was Ihr braucht: Anfang, Ende und Länge des Puffers, alles andere ist 
Zeitverschwendung.
Werf' doch wenigstens eine halbe Pupille auf meinen Post.
Natürlich musst Du nicht, irgendwann gereift vielleicht auch die 
Geht-So-Besser-Methode. Ob Du damit aber die mögliche(n) 
Doppeldeutigkeit(en) ausklammerst ist fraglich.

von Christian S. (chris72160)


Lesenswert?

amateur schrieb:
> Wann beschäftigst Du Dich endlich mal mit der Funktion des Ringpuffers?

Sobald ich ein Tutorial gefunden habe, in dem dieser einleuchtend 
erklärt ist und nicht nur das suchen eines einzelnen Zeichens, sondern 
ganzer Zeichenketten innerhalb des Ringbuffers behandelt.

Bisher bin ich leider nicht fündig geworden.

Gruß Chris

von amateur (Gast)


Lesenswert?

Selbst hier in mikrocontroller.net sind mehrere Ansätze zu finden, 
insbesondere rund um die gepufferte serielle Schnittstelle.
Die Wikipedia weiß es mit Sicherheit.

Das Grundprinzip ist recht einfach:
Es gibt zwei Zeiger.
Der eine zeigt auf den Anfang - hier wird gelesen.
Der andere zeigt auf das Ende - hierhin wird geschrieben.

Sind beide gleich, so ist der Puffer leer.
Wird gelesen, so wird der erste Zeiger erhöht.
Wird geschrieben, so wird der zweite Zeiger erhöht.
Erreicht einer der beiden Zeiger das Ende (max.), so wird er auf den 
Pufferanfang gesetzt.
Liest Du mehr als drinnen ist (ohne Abfrage), so hast Du ein Problem - 
wie bei jedem leeren Puffer.
Schreibst Du, trotzdem das Teil voll ist, so hast Du ebenfalls ein 
Problem - auch wie bei jedem vollen Puffer.
Es gehören also ein paar Hilfsfunktionen (Voll/Leer) dazu – auch normal.

Du hast jetzt zwei Möglichkeiten:
1. Du simulierst das Lesen nach den obigen Regeln ohne die
   eingebauten Zeiger zu verändern
oder
2. Du liest brav alle vorhandenen Zeichen in einen eigenen Puffer und
   such dort.

von Reinhard Kern (Gast)


Lesenswert?

Christian Stielz schrieb:
> nicht nur das suchen eines einzelnen Zeichens, sondern
> ganzer Zeichenketten innerhalb des Ringbuffers behandelt.

Das ist schon missverstanden - der Ringbuffer ist nur im Speicher als 
Ring angeordnet, logisch ist er jedoch linear. Dazu braucht man eben 
einen Pointer auf den gerade gültigen Anfang, der logisch lineare String 
geht von da einmal um den Ring bis zum Zeichen vor dem Anfang.

Da dir das Verständnis so extrem schwer fällt, machst du es wirklich am 
besten so, dass du den Inhalt ab dem Anfang in einen String üblicher 
Anordnung kopierst, auch wenn das zusätzlichen Speicherplatz kostet, 
dann kannst du vorhandene Vergleichsfunktionen verwenden oder abtippen.

Gruss Reinhard

von Mmm (Gast)


Lesenswert?

Reinhard Kern schrieb:
> Das ist schon missverstanden

Stichwort: circumcised fonts

von Rush (Gast)


Lesenswert?

strncmp benutzen. An die Funktion den Pointer vom aktuellen 
Schreibzeiger
übergeben. Die Länge ist die Differenz aus Schreibzeiger und aktuellen 
Lesezeiger.
Oder Du vergleichst erst einmal ob das gerade geschriebene Zeichen
dem Anfangszeichen des Suchstrings entspricht. Dann setzt Du dir ein 
Flag und
rufst zyklisch strncmp auf.

Arbeite Dich mal in Pointerarithmetik ein. Mit den []-Klammern wird das 
nix auf Dauer.

von Christian S. (chris72160)


Lesenswert?

amateur schrieb:
> Das Grundprinzip ist recht einfach:
> Es gibt zwei Zeiger.
> Der eine zeigt auf den Anfang - hier wird gelesen.
> Der andere zeigt auf das Ende - hierhin wird geschrieben.

Ok- Anfang= Position 0, Ende z.B. Position 8

amateur schrieb:
> Sind beide gleich, so ist der Puffer leer.

=?

amateur schrieb:
> Wird gelesen, so wird der erste Zeiger erhöht.

Er geht also auf Position 1. Hm- da steht ja noch nix, weil nix 
reingeschrieben wurde= ?

amateur schrieb:
> Wird geschrieben, so wird der zweite Zeiger erhöht.

Höher als 8 geht nicht, also springt er auf 0, oder?

amateur schrieb:
> Erreicht einer der beiden Zeiger das Ende (max.), so wird er auf den
> Pufferanfang gesetzt.

Das war doch eben der Fall=?

amateur schrieb:
> Liest Du mehr als drinnen ist (ohne Abfrage), so hast Du ein Problem -
> wie bei jedem leeren Puffer.

Das leuchtet mir ein.

amateur schrieb:
> Schreibst Du, trotzdem das Teil voll ist, so hast Du ebenfalls ein
> Problem - auch wie bei jedem vollen Puffer.

Auch klar.

Bin noch immer auf der Suche nach einem gut erklärten 
Beispielringbuffer.

Gruß Chris

von tare (Gast)


Lesenswert?

amateur schrieb:
> Selbst hier in mikrocontroller.net sind mehrere Ansätze zu finden,
> insbesondere rund um die gepufferte serielle Schnittstelle.
http://www.mikrocontroller.net/articles/FIFO#Standard-Ringpuffer

von Christian S. (chris72160)


Lesenswert?

Wow- super!

1000 Dank!

Gruß Chris

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.