Hallo,
ich bin immer bestrebt mein Programmcode so verständlich wie möglich und
somit so wartbar wie möglich zu schreiben. Ich möchte es anderen
Personen so einfach wie möglich machen den Code zu verstehen.
Dementsprechend füge ich auch viele Kommentare ein (habe ich in den
unten gezeigten Beispielen jetzt ausnahmsweise nicht gemacht).
Letzte Woche habe ich ein Stück Code geschrieben, in dem untersucht
werden sollte, ob in einem Array aus Zeichenketten eine bestimmte
Zeichenkette enthalten ist. Dabei kamen die drei unten aufgeführten
Beispiele heraus, bei denen ich nicht weiß welche Lösung die "bessere"
ist. Damit die Beispiele unabhängig von der verwendeten
Programmiersprache sind habe ich sie in (m)einem Pseudo-Code
geschrieben. Ich denke jeder der schon einmal programmiert hat wird den
Code verstehen.
Irgendwo am Anfang des Programms wird ein Array mit den Zeichenketten
definiert bzw. vom Anwender angegeben. Das Array besteht aus maximal 30
Elementen. Die Reihenfolge der Elemente ist nicht sortiert.
1
List[1] := 'Text1'
2
List[2] := 'Text2'
3
List[3] := 'Text3'
4
List[4] := 'Text4'
5
...
Im Weiteren Verlauf des Programms soll untersucht werden, ob die
folgende Zeichenkette in dem o.g. Array enthalten ist.
1
SearchString := 'Text3'
Da das Array sehr klein ist habe ich zunächst über alle Elemente
gesucht.
1
Index := 1
2
while Index <= length(List)
3
if SearchString == List(Index)
4
Found := 'true'
5
end
6
Index := Index + 1
7
end
Allerdings ist mir nicht ganz klar, ob es üblich bzw. guter Stil ist
weiterzusuchen, obwohl der Text bereits gefunden wurde. Ich habe die
Schleife daher wie folgt erweitert.
1
Index := 1
2
while Index <= length(List)
3
if SearchString == List(Index)
4
Found := 'true'
5
Index := length(List)
6
end
7
Index := Index + 1
8
end
An der oben aufgeführten Schleife hat mir jedoch nicht gefallen, dass
die Funktion "length(List)" zweimal aufgerufen werden muss. Daher dachte
ich mir es ist doch möglich dies zu umgehen, wenn die Liste rückwärts
durchsucht wird.
1
Index := length(List)
2
while Index > 0
3
if SearchString == List(Index)
4
Found := 'true'
5
Index := 0
6
end
7
Index := Index - 1
8
end
Jetzt bin ich mir allerdings nicht mehr sicher, ob dieser Code für
andere (auch Anfänger) noch einfach ist. Immerhin sind wir in unserem
Kulturkreis gewohnt Listen von oben nach unten zu lesen. Welche der drei
Vorgehensweisen würdet Ihr bevorzugen?
Mit freundlichen Grüßen
Guido
Die Suche nach dem Finden des Strings abzubrechen
halte ich für OK.
Die Frage heißt ja ob der gesuchte String enthalten ist
und nicht wie Oft enhalten. Bei wie oft muß natürlich
das gesamte Array abgesucht werden.
Ich würde also die Zeile mit dem while um "&& found == false"
ergänzen. Kann Laufzeit sparen.
Für die Suchrichtung würde ich mal schauen was der
Compiler draus macht und wie lange der Ziel-µC benötigt.
Dann würde ich das bessere nehmen.
Hallo,
vielen danke für die Rückmeldungen.
Carsten Wille schrieb:> Ich würde die erste Variante bevorzugen, plus ein "Break", welches die> Suche beim Erreichen der ersten Fundstelle abbricht.
Stimmt ein "break" ist sicher die eleganteste Lösung. Leider ist dieser
Befehl nicht in jeder Programmierumgebung vorhanden. So auch nicht in
"imc Famos" für das ich gerade eine Auswerteroutinen für meine Messdaten
schreibe.
Alter Hase schrieb:> Die Frage heißt ja ob der gesuchte String enthalten ist> und nicht wie Oft enhalten.
Es muss nur untersucht werden, ob der String "überhaupt" vorhanden ist.
Alter Hase schrieb:> Ich würde also die Zeile mit dem while um "&& found == false"> ergänzen. Kann Laufzeit sparen.
Laufzeit ist zwar nicht so das Problem, die Idee ist dennoch gut.
Mit freundlichen Grüßen
Guido
Kommt drauf an, wie 'pedantisch' man einige Regeln auslegt.
Eine Regel besagt: Eine Funktion sollte einen Einstieg und einen
Ausstieg haben. Dagegen ist auch grundsätzlich nichts zu sagen, wenn man
allerdings akzeptiert, dass es auch Ausnahmen geben kann. zb
Fehlerabfragen am Anfang einer Funktion mit vorzeitigem Return.
Aber auch: kurze Funktionen, die überschaubar sind und dadurch, dass man
diese Regel strikt einhaltet nichts gewinnen
int Search( .... )
{
for( i = 0; i < ArrayGrenze; i++ ) {
if( List[i] == SearchString )
return i;
}
return -1;
}
Ich bevorzuge hier die for-Schleife (egal ob man das syntaxmässig so
schreibt oder in einer anderen Sprache anders), weil
* das grundsätzlich eine Zählschleife ist
* ich vorher weiß wie oft sie maximal durchlaufen werden muss
* ich so die 3 Elemente einer Zählschleife beisammen habe
+ bei welcher Zahl gehts los
+ bei welcher Zahl ist Schluss
+ was passiert mit dem zählenden Element von einem Durchlauf
zum nächsten
Dadurch, dass ich hier einen return mitten aus der Schleife heraus
zulasse, verschleiere ich die Funktion noch nicht. Aber: ich brauche
keine zusätzlichen Variablen, die in die Analyse der Funktion eingehen
müssen.
Hallo,
ich sehe schon, Ihr seid alle zu sehr mit C verseucht. "LOL"
Leider kennt imc Famos weder eine For-Schleife noch ein Befehl zum
beenden einer (While-)Schleife. Vielleicht war mein Ansatz mit dem
Pseudo-Code nicht so gut. Ich dachte mir jedoch, wenn ich von FAMOS
schreibe liest es sowieso keiner, da dieses Programm unter den µC.net
Benutzern nicht sehr weit verbreitet zu sein scheint. FAMOS-Foren sind
leider alle wie ausgestorben.
Vermutlich wäre es dann so am besten, oder?
Meiner Meinung nach sollte man Breaks und erst recht Returns mitten im
Code vermeiden, allerdings nur dann, wenn deren Vermeidung nicht durch
irgendwelche Verrenkungen erkauft wird.
In diesem Fall geht es ohne Verrenkungen, indem man das Ergebnis des
Stringvergleichs einfach mit zur Abbruchbedingung hinzufügt. In C sieht
das folgendermaßen aus:
Manch einer wird jetzt anmerken, dass in die Zeile mit dem "for" zu viel
Code hineingepackt wurde. Ich finde, die Zeile ist mit 57 Zeichen (ohne
die Einrückung) für einen geübteren C-Programmierer noch gut mit einem
Blick erfassbar, aber da gehen die Geschmäcker eben etwas auseinander :)
Guido C. schrieb:> Hallo,>> ich sehe schon, Ihr seid alle zu sehr mit C verseucht. "LOL">> Leider kennt imc Famos weder eine For-Schleife noch ein Befehl zum> beenden einer (While-)Schleife.
Nunja, du kämpfst wohl mit demselbem Mist, wie ich damals mit Simplorer
unt Matlab gekämpft habe: Programme, bei denen man sich fragt, wie sich
solche ergonomischen Katastrophen so lange halten können...
> Vermutlich wäre es dann so am besten, oder?> [...]
Das ist sehr schwierig zu beurteilen.
Wenn ich mal ganz dreist annehme, dass der Skript-Interpreter (also das,
was dein Programm ausführt) gewohnt mies konstruiert ist, dann solltest
du möglichst wenig Programmtext bei jeder Iteration ausführen.
Das bedeutet vorallem, dass du die Schleifenbedingung kurz halten musst.
Beschränke dich da auf 'Index > 0' oder 'Index < N', wobei du 'N' vorher
als Variable eingeführt hast. Das vermeidet, dass die
'length()'-Funktion bei jeder Runde gerufen wird.
Als Abbruch würde ich dann, wie du ja auch schon vorgeschlagen hast, den
Index in der Schleife so versetzen, dass die Schleife abbricht. Sofern
du die Fundstelle brauchst, merk dir den Index nochmal in einer
separaten Variablen:
1
I := 0
2
Index := -1
3
N := length(List)
4
5
while I < N
6
if SearchString == List(I)
7
Index := I
8
I := N
9
end
10
I := I + 1
11
end
So würde ich das in diesem Fall formulieren. Wohl gemerkt: Unter der
(leider recht wahrscheinlich zutreffenden) Voraussetzung, dass der
Interpreter Schrott ist.
Die Iteration beschränkt sich dann auf drei kurze Zeilen (Vergleich im
Schleifenkopf, Vergleich auf Suchstring und Inkrement von I). Ob du die
drei dann noch zusammenziehst, wie Yalu zuvor es vorschlägt, spielt dann
keine Rolle mehr.
Hallo,
Yalu X. schrieb:> Wei wär's so:> Index := length(List)> while (Index > 0) and SearchString <> List(Index)> Index := Index - 1> end
Das gefällt mit sehr gut. Kurz und knackig :-)
Sven P. schrieb:> Nunja, du kämpfst wohl mit demselbem Mist, wie ich damals mit Simplorer> unt Matlab gekämpft habe: Programme, bei denen man sich fragt, wie sich> solche ergonomischen Katastrophen so lange halten können...
Ich hoffe immer, dass mit der nächsten Version alles besser wird.
Sven P. schrieb:> Das bedeutet vorallem, dass du die Schleifenbedingung kurz halten musst.
Da hast Du sicher recht. In Matlab versuche ich immer auf Schleifen
komplett zu verzichten. In FAMOS gelingt dies leider nicht. Hierfür
fehlen dort einfach ein paar Syntaxelemente.
Danke nochmals an ALLE für die Unterstützung. Ich werde mir den Inhalt
des ganzen Thread noch einmal in Ruhe durch den Kopf gehen lassen. Wobei
ich denke der Ansatz von Yalu ist schon optimal.
Mit freundlichen Grüßen
Guido
> while (Index > 0) and SearchString <> List(Index)
3
> Index := Index - 1
4
> end
5
>
Auch schön.
Ich bin allerdings kein Freund von Schleifen die runterzählen, ichmag
hochzählende Schleifen lieber. Das eröffnet dann noch eine Variante,
wenn es erlaubt ist temporär an die Liste/das Array noch ein Element
anzuhängen
Sven P. schrieb:>> Leider kennt imc Famos weder eine For-Schleife noch ein Befehl zum>> beenden einer (While-)Schleife.> Nunja, du kämpfst wohl mit demselbem Mist, wie ich damals mit Simplorer> unt Matlab gekämpft habe
Matlab kennt doch sowohl for-Schleifen (die zugegebenermaßen den Ablauf
oft ziemlich ausbremsen) als auch "break" zum Abbruch von
While-Schleifen. Oder meinst Du was anderes?
Guido C. schrieb:> In Matlab versuche ich immer auf Schleifen> komplett zu verzichten.
Das ist ja gerade eine der Spezialitäten von Matlab, dass man meistens
ohne die relativ langsamen for-Schleifen auskommen kann.
Hallo,
J.-u. G. schrieb:> Matlab kennt doch sowohl for-Schleifen (die zugegebenermaßen den Ablauf> oft ziemlich ausbremsen) als auch "break" zum Abbruch von> While-Schleifen. Oder meinst Du was anderes?
Ich arbeite derzeit mit Matlab und Famos.
Matlab => "For"-Schleifen und "break"
Famos => Keine "For"-Schleifen und Kein "break"
Sorry falls ich hier für Verwirrung gesorgt habe. Die Frage in diesem
Thread bezog sich auf FAMOS. In Matlab hätte ich das Problem wohl ohne
Schleife gelöst.
Mit freundlichen Grüßen
Guido
> indem man das Ergebnis des Stringvergleichs einfach mit zur> Abbruchbedingung hinzufügt.
...was wiederum ein Stil ist, den ich nicht so mag, weil man zwei nicht
zusammenhängende Bedingungen in eine Zeile bringt. Das eine ist der rein
formale Teil, weil man einfach nicht mehr Elemente als LSIZE untersuchen
kann, das andere ist der Vergleich auf irgendwas, was man finden will.
Gerade wenn man für den zweiten Teil noch komplexere Bedingungen
überprüfen will, wirds unübersichtlich und mit Pech noch so, dass der
Index-Check aus Versehen deaktiviert wird (OR an der falschen Stelle,
Klammerung verpennt, ...).