• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

Code Schnipsel

supercowpower

Neu angemeldet

Registriert
9 Feb. 2016
Beiträge
25
Hi, ich vermisse ein Code Schnipsel Thread wie damals, in diesem Thread hier geht es um kleine Code Fragen.

---

Dann frage ich mal ^^
Sprache Java
[src=java]
// Harte Kritik am Code bitte
class Test {
public static void main(String[] args) {

String text = "blak f2ololr a su7bstlhelloolri7nheg in9me";
String keyword = "lol";
int keywordLength = 0;
int keywordCounter = 0;


{ // search for keyword
int max = text.length() - keyword.length();
int keywordIndex = 0;
int j = 0;

con:
for (int i = 0 ; i <= max ; ) {
keywordIndex = 0;
if (text.charAt(++i) != keyword.charAt(keywordIndex)) // if first letter of keyword not found, continue to next letter to check
continue con;

keywordLength = keyword.length(); // only for the following while loop parameter
// check the keyword match
while ( -1 < --keywordLength ) { // do the while-loop maximal (keyword.length()-1) times
if (text.charAt(i++) != keyword.charAt(keywordIndex++)) { // check whether the letters matching
continue con;
}
}
keywordCounter++;
}
// print results
System.out.println("Found \"" + keyword + "\" "
+ keywordCounter + " times");
} // end, search for keyword
}
}[/src]
 
Zuletzt bearbeitet:

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
1) Unnötige geschwungene Klammern um lokalen Code zu haben - für das Snippet ist das echt wurscht. Und selbst bei größeren Sachen nimmt man lieber eigene Funktionen also sowas.
2) Für das Continue gehörst du geschlagen.
3) Gescheite Variablenbenennung
4) Zeile 23 und 25 macht keinen Sinn und wäre, mMn. sogar eine Endlosschleife o.O
 

supercowpower

Neu angemeldet

Registriert
9 Feb. 2016
Beiträge
25
  • Thread Starter Thread Starter
  • #4
Wie wäre es wenn Sie ihre Basics erstmal auffrischen? Das Programm kompiliert läuft und finded die gewünschten keywords. ++i und i++ ist nicht das selbe. Mehr Fakten bitte, die geschwungengen Klammern bewirken dass die initialisierten Variablen nur in diesem Code Block sichtbar sind. Was hast du gegen ControlFlow Elemente?
 

Larius

OutOfOrder

Registriert
12 Juli 2013
Beiträge
5.792
Wg. Control Flow Elemente und Geschwunge Klammern zur Abgrenzung von Code Blöcken: Nur weil es eine Sprache unterstützt heisst es nicht, das man es auch verwenden sollte. Ein Code sollte einen gewissen Fluss haben, den man mit Schleifen wunderbar steuern kann. Deshalb sind auch mehrzeilige Schleifen - in zb C, C++, C# und Java - auch mit geschwungenen Klammern versehen das man weiß, welcher Code-Block dazu gehört. Gerade in längeren Codeabschnitten mit vielen solcher Sprunganweisungen kann es durchaus dazu kommen, dass es verdammt schnell unübersichtlich wird. Genauso sollte ein Code selbsterklärend sein so das ich drauf schau, seh "aha, die und die Variable macht das und das" und fertig.

Gerade wenn man lokale Initialisierung benötigt sollte man drüber nachdenken, ob man da nicht eine Subfunktion schreibt die genau diesen Abschnitt ausführt.

Das Argument bzgl. "Es kompiliert und findet die gewünschten Keywords" lass ich nicht gelten. Ich kann auch, wenn ich lustig bin, in C mittels Define meine eigenen Begriffe als Substitution für die bestehenden Schlüsselwörter verwenden. Die Maschine checkt es, aber trotzdem wird mich ein jeder Entwickler, der dann diesen Code zu sehen bekommt, verfluchen.
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
Kompiliert nicht.

Weder mit Clang, noch mit GCC. Ist also kein gültiger C++-Code. … Ernsthaft: was soll man sagen, wenn du nicht mal dranschreibst, welche Sprache das Schnipsel ist.
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
Was ist bitte die Frage, ach so, die steht im Code in Zeile 2 "Harte Kritik"... na dann, ganz hart - aber ich bin keine Java Guru....

1) wie Larius sagt, würde ich dafür, egal in welcher Sprache eine Funktion nehmen, es ist nicht notwedig den Code in eine Klasse zu setzen, du willst letztendlich nur wissen wie oft ein Teilstring in einem String vorkommt, dafür benötigt es nicht zwingend ein Objektinstanz/Klasse

2) Variablen für die Routinen nach oben in die Funktion

3) Wenn du es mit Klassen lösen willst, würde man "text", "keyword" als lokale Attribute der Klasse setzen, das wäre OOP - und diese mit Set/Get Funktionen schreiben. "keywordLength" und "keyWordCounter" könnte man bei vielleicht bei einem Set neu berechnen lassen oder dynamisch bei bedarf und dann überelgen ob man das unbedingt als Attribute setzen will, falls man öfter darauf zugreift

4) Variablen in einer Funktion, leben vermutlich auch nur in selbiger... also brauchst du auch nicht sagen das die Variablen nur innerhalb diese Codeblock leben - die Variablen "max", "keywordIndex" und "j" sollen lokal sein, aber in welchem Scope und warum soll das von Vorteil sein? {} bezeichnet einen Block. okay... aber das kann man dann auch als eigene Funktion der Klasse umsetzen die auf Attribute zurückgreift und die Variablen dort lokal setzen, für die Ausführung dieser Funktion.

5) "j" wird nie benutzt, "String[] args" wird auch nie genutzt....

6) Zeile 18 erzeugt eine Dauerschleife, weil "i" immer 0 ist - egal ob "i" mit "++i" oder "i++" Pre oder Postinkrement verändert wird, die Schleife wird jedesmal neu intitialisiert, nein? Aber der Sprung auf "con" erhällt/behällt doch gar nicht die Variablen bzw. den Counterstand.... dazu müsste der Zähler vor "con" erklärt werden und nicht im Schleifenkopf neu bei Null anfangen.... macht man so aber in der Regel nicht. Außerdem ist es in der Praxis nicht gut einen Schleifenzähler innerhalb der Schleife (verschleiert) hoch oder runter zu zählen. Dann doch lieber gleich eine While Schleife. die prüft ob i > max ist und der String durchlaufen wurde und dann ist klar das "i" innerhalb der Schleife wandert...

7) Zeile 20... nur an Position "text.charAt(i)" testen, ohne Preinkrementierung von "i", nur "continue" für die For-Schleife, aber springe nicht zu "con"... statt "KeywordIndex" gleich nach dem ersten Buchstaben fragen.... keywordIndex ist an dieser Stelle sowieso immer "0" nach Zeile 19...

8) Zeile 23 - "KeywordLength" braucht nur einmal ermittelt werden, das Keyword verändert sich ja nicht innerhalb der Ausführung des Blocks.... der sowieso gleich gestartet wird, wenn die Klasse erstellt wird....

usw....

du solltest auf jeden Fall nochmal den gesamten "con" Teil überdenken, ob du OOP dafür brauchst anstelle einer Helfer Funktion oder wenn du OOP unbedingt dafür nutzen willst.... was keinen Sinn macht, dir aus "con" eine Funktion basteln die alle Blockvariablen beinhaltet.

Fürchterlich. ;)
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
OK … mir war langweilig … und außer Java und C# kommt realistischerweise als Sprache ja wenig infrage.

Unmittelbarer Eindruck: Hier geht’s darum, die Anzahl eines bestimmten Substrings in einem String zu finden. Vieles bleibt aber in dichtem Nebel verborgen.

Annahmen, weil Programmiersprache unklar:

  • Das erste Zeichen in einem String ist Index 0.
  • Preinkrement gibt den Wert nach der Inkrementierung zurück, Post den vorher.
  • Die genauen Rahmenbedingungen sind unklar, da Dokumentation fehlt. Die wichtigsten Fragen sind: Müssen die Substrings durch Weißraum o.ä. abgetrennt sein? Was ist mit sich überlappenden Substrings? So wie der Beispieltext aussieht, gehe ich von einer einfachen Substringsuche ohne Trennzeichen aus.


Für den Zweck zwei geschachtelte Schleifen und ein Goto zu schreiben, ist … komplex. Deutlich komplexer als nötig. Die Wahrscheinlichkeit, dass grobe Fehler im Algorithmus sind, liegt nahe der Gewissheit. Und wenn nicht, garantiere ich miese Wartbarkeit und erwarte Ineffizienz in Sachen Laufzeit.

  • Erstmal alles das, was Larius gesagt hat.
  • Zl. 20: Der erste Buchstabe des Strings wird nie geprüft. i ist im ersten Durchlauf 0, wird in der if-Bedingung auf 1 inkrementiert und damit Index 1 (zweites Zeichen!) des Strings angesprochen.
  • Wenn Die Bedingung in Zl. 20 beim ersten Druchlauf greift, führt das continue zu einer Endlosschleife.
  • Zl. 26 führt die identische Prüfung wie Zl. 20 durch. Warum zweimal prüfen?

An der Stelle hab ich abgebrochen. Für die einfache Aufgabe ist das viel zu komplex, viel zu verworren und hat erwiesenermaßen schwere Fehler.

Schmeiß den Code weg und nutze deine Standard-Library. Die ist dafür gemacht, um dir genau solche Standardaufgaben abzunehmen. In dem Fall wäre das wahlweise die Finde-Substring-in-String-Funktion oder Reguläre Ausdrücke. Dann hast du einen ca. 5-Zeiler bei dem du praktisch auf einen Blick siehst, was er tut und ob das passt.
 

supercowpower

Neu angemeldet

Registriert
9 Feb. 2016
Beiträge
25
  • Thread Starter Thread Starter
  • #9
Sprache: Java. Sorry
Zu: if (text.charAt(++i).....
Zuerst wird i geprüft dann erst erhöht

...

Es funktioniert grob so:
Die äußere for-schleife ist dazu da um den text element für element zu durchsuchen.
Wenn ein element im text gefunden wurde das mit dem ersten element des keywords übereinstimmt dann kommt die innere while-schleife zum einsatz.
Sie checkt ob die nächsten elemente mit dem keyword übereinstimmen. Ist es der Fall, so wird IF kein einziges mal aufgerufen und der counter wird um +1 erhöht
 

Timon3

Team ModMii

Registriert
17 Juli 2013
Beiträge
499
@theSplit: Zumindest ein paar deiner Punkte sind leider nicht richtig so.

1) wie Larius sagt, würde ich dafür, egal in welcher Sprache eine Funktion nehmen, es ist nicht notwedig den Code in eine Klasse zu setzen, du willst letztendlich nur wissen wie oft ein Teilstring in einem String vorkommt, dafür benötigt es nicht zwingend ein Objektinstanz/Klasse

Es geht in Java aber nunmal gar nicht anders. Außerdem ist das hier nur prozeduraler Code, da Java aber als Einstieg immer eine Klasse mit einer Main-Funktion braucht, steht er eben in einer Klasse.

5) "j" wird nie benutzt, "String[] args" wird auch nie genutzt....

Ist eben Teil der Signatur der Einsprungsfunktion.

6) Zeile 18 erzeugt eine Dauerschleife, weil "i" immer 0 ist - egal ob "i" mit "++i" oder "i++" Pre oder Postinkrement verändert wird, die Schleife wird jedesmal neu intitialisiert, nein? Aber der Sprung auf "con" erhällt/behällt doch gar nicht die Variablen bzw. den Counterstand.... dazu müsste der Zähler vor "con" erklärt werden und nicht im Schleifenkopf neu bei Null anfangen.... macht man so aber in der Regel nicht. Außerdem ist es in der Praxis nicht gut einen Schleifenzähler innerhalb der Schleife (verschleiert) hoch oder runter zu zählen. Dann doch lieber gleich eine While Schleife. die prüft ob i > max ist und der String durchlaufen wurde und dann ist klar das "i" innerhalb der Schleife wandert...

In Zeile 20 wird i inkrementiert, gibt also keine Dauerschleife.

Wobei ich dazu sagen muss: Wieso benutzt du ++i, supercowpower? i++ ist wesentlich intuitiver, und es würde keinen großen Unterschied ergeben, i auf 1 zu setzen.
 

drfuture

Zeitreisender
Teammitglied

Registriert
14 Juli 2013
Beiträge
8.750
Ort
in der Zukunft
Eine Klasse / Funktion etc. braucht eine Beschreibung was sie denn tut....
Zum einen im Code, damit man das selber irgendwann noch kapiert - aber viel wichtiger wenn man es in ein Forum schreibt!
Kann ja sein das der Code funktioniert und *etwas* macht - aber woher sollen wir
a) wissen ob der Code das macht was du dir vorstellst
b) wissen ob der Code dafür gut geeignet ist?

Daher... was möchtest du machen und was ist dir dabei wichtig?
Nicht immer lässt sich z.B. kurze Laufzeit, wenig Speicherbedarf und geringe Größe des Executables unter einen Hut bringen.

Und wie du schon so schön gesagt hast geht es hier um Codeschnipsel die man ja normal in etwas größerem Verwendet - somit ist auch bei Java hier die Klasse und das Main() unnütz und gehört schlicht nicht zum *zu kontrollierenden Code*.
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
@theSplit: Es geht in Java aber nunmal gar nicht anders. Außerdem ist das hier nur prozeduraler Code, da Java aber als Einstieg immer eine Klasse mit einer Main-Funktion braucht, steht er eben in einer Klasse.

Man lernt nie aus. Dafür kenne ich Java aber zu wenig (kaum bis gar nicht ;) )

Ist eben Teil der Signatur der Einsprungsfunktion.

String[] args - und das "main" macht dann zumindest Sinn. "j" ist dennoch ungenutzt.


In Zeile 20 wird i inkrementiert, gibt also keine Dauerschleife.

Wobei ich dazu sagen muss: Wieso benutzt du ++i, supercowpower? i++ ist wesentlich intuitiver, und es würde keinen großen Unterschied ergeben, i auf 1 zu setzen.

Ich lese den Code aber so:
Es wird in dem Continue zum "Label" "con" gesprungen, die erste Anweisung die da läuft:
Eine For Schleife bei der ein Counter "i" mit 0 initialisiert wird, warum wird zu einem Sprung außerhalb des Fors der Counter nicht neu intialisiert? - Verstehe ich so nicht.
Entweder ich bleibe in der Schleife normales (continue) - oder ich machs mit "goto" "continue LABEL" um zu einer Zeile im Programm zu springen und starte alle Code danach (neu). So liest sich das für mich ;)
Ich wäre aber über Aufklärung zu meinem Umwissen dankbar und würde gar so weit gehen zu fragen ob das so "sauberer" Stil ist... ? ;)
Weil: Es ist nicht intuitiv... (für mich)
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
Zu: if (text.charAt(++i).....
Zuerst wird i geprüft dann erst erhöht
Was du beschreibst ist Post-Inkrement, nicht Pre.

Ich wäre aber über Aufklärung zu meinem Umwissen dankbar und würde gar so weit gehen zu fragen ob das so "sauberer" Stil ist... ?
Weil: Es ist nicht intuitiv... (für mich)
Es ist weder intuitiv, noch sauber. Zum Vergleich unten ein Beispiel, wie man’s mit Hilfe der Standard Library umsetzen könnte. C++, weil ich mich in Java nicht wohl genug fühle und keine Umgebung zum Testen da hab. Der Algorithmus wäre dort aber exakt derselbe.
[src=cpp]#include <cassert>
#include <iostream>
#include <string>

/**
* Returns the case-sensitive, non-overlapping number
* of `needle`s in the `haystack`.
* Requires: `needle` must not be empty.
*/
std::size_t count_needles(
const std::string& needle, const std::string& haystack)
{
assert(not needle.empty());
std::size_t found_count = 0;
std::size_t startpos = 0;

while (startpos < haystack.size()) {
startpos = haystack.find(needle, startpos);

if (startpos != std::string::npos) { // found
++found_count;
startpos += needle.size();
}
}

return found_count;
}

int main()
{
std::cout
<< count_needles("needle", "There may be needles over needles in a haystack.") // 2
<< " "
<< count_needles("lol", "lololololol") // 3
<< " "
<< count_needles("needle", "There are no pointy things here.") // 0
<< " "
<< count_needles("foo", "") // 0
<< " "
<< count_needles("begin", "beginnnn foo bar baz begi") // 1
<< " "
<< count_needles("end", "en d foo barendbazend") // 2
<< " "
<< count_needles("toolong", "toolo") // 0
<< std::endl;
}
[/src]
 
Zuletzt bearbeitet:

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
@Brother John:

Du hast das was du gequotest hast aber etwas falsch aufgefasst... ich dachte mehr an das "con" welches "außerhalb" des Codes für den For-Schleifen-Kopf liegt. ;)
Weil ich würde spontan davon ausgehen das immer neu initialisiert wird, schließlich liegt - meiner Ansicht nach - das "con" Label außerhalb des Codes der For-Schleife....

Zum zweiten, als Programmieraufgabe ist so etwas doch gar nicht verkehrt... also zum üben. Man sollte auch Probleme ohne (Standard)lib lösen können. ;)
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
Weil ich würde spontan davon ausgehen das immer neu initialisiert wird, schließlich liegt - meiner Ansicht nach - das "con" Label außerhalb des Codes der For-Schleife....
Da hab ich dich wohl wirklich falsch verstanden … In Sachen »con« bin ich jedenfalls ganz bei dir. Genau so sollte es sein. Und ist es auch … hoffe ich … Weil so krass will ich meine Java-Vorurteile gar nicht bestätigt haben. Was mich ein bisschen skeptisch stimmt, ist supercowpowers Aussage, dass der Code funktioniert. Wenn unsere Annahmen passen, läuft nämlich dieser Code mit diesem Input definitiv nicht.

theSplit schrieb:
Zum zweiten, als Programmieraufgabe ist so etwas doch gar nicht verkehrt... also zum üben. Man sollte auch Probleme ohne (Standard)lib lösen können.
Das seh ich ein bisschen anders. Es wird viel zu viel Zeugs manuell und oft fehlerhaft nachimplementiert, was nur einen Funktionsaufruf entfernt ist. Sich wo immer möglich auf die Standardlib zu stützen, halte ich für eine zentrale Fähigkeit eines Softwareentwicklers.

Auch zum Üben findet sich i.d.R. mehr als genug, ohne die Standardlib nachzuimplementieren. Um zum Beispiel zu lernen, wie man Algorithmen sauber implementiert, warum Quicksort hincoden? Ein Baum-Iterator oder Dependency-Resolution in einem Graphen haben einen ähnlichen Schwierigkeitsgrad. Und sie haben einen echten Mehrwert, weil so etwas in den Standardlibs oft nicht drin ist. Wenns dann wirklich mal sein soll, ist mit der Erfahrung Quicksort auch kein Problem.

--- [2016-10-20 22:01 CEST] Automatisch zusammengeführter Beitrag ---

Verdammt! Klarer Fall von erst googeln, dann posten. Das Label ist kein Label wie in C oder C++, sondern es gehört zur For-Schleife. Eine benannte for sozusagen:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
So kann man aus einer untergeordneten Schleife über mehrere Ebenen continue’en oder break’en. »continue con« heißt in unserem Fall also einfach: »Geh in die nächste Iteration der for-Schleife namens con«.

Dass der Code in eine Endlossschleife rennt, zieh ich hiermit zurück. :) Das Ding terminiert schon. Zu meiner Gesamtbeurteilung des Schnipsels steh ich aber.
 
Zuletzt bearbeitet:

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
Verdammt! Klarer Fall von erst googeln, dann posten. Das Label ist kein Label wie in C oder C++, sondern es gehört zur For-Schleife. Eine benannte for sozusagen:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
So kann man aus einer untergeordneten Schleife über mehrere Ebenen continue’en oder break’en. »continue con« heißt in unserem Fall also einfach: »Geh in die nächste Iteration der for-Schleife namens con«.

Dass der Code in eine Endlossschleife rennt, zieh ich hiermit zurück. :) Das Ding terminiert schon. Zu meiner Gesamtbeurteilung des Schnipsels steh ich aber.

Dann sollte man "con" und das "for" in eine Zeile schreiben, ich finds aber trotzdem eklig sowas zu verwenden, wobei ja, mit der While schleife müsste man normal eine bool flag setzten, "brake" anwenden, und dann wenn das flag gestetzt ist, den Counter erhöhen. Bzw. mach ich das "immer so" ;)

Und wenn dann das Flag gesetzt ist, könnte man ein Continue setzen das die For Schleife weiterlaufen lässt.

Ich überlege gerade wie sinnvoll ich sowas finde - wäre in C wohl nur mit Goto - aber mit Schleifenneuinitialisierung zu erledigen bzw. ein Sprung "in die erste Zeile der Schleife", aber mit der Pflicht selbst den Counter zu erhöhen... irgendwie so... :o

Trotzdem, eine Zeile "con: for (int x = 0, int length = elements.length(); x < length; ++x) { Schleifeinhalt.... }" <--- das wäre vielleicht schon wieder logisch(er).
Aber selbst dann sagt mir meine "Intuition" - "die schleife würde neu initialisiert werden", auch wenn sie das nicht wird.... nun ja... :o
 

supercowpower

Neu angemeldet

Registriert
9 Feb. 2016
Beiträge
25
  • Thread Starter Thread Starter
  • #17
Ich sehe mein Code bereitet euch sehr viel Spaß ^^, danke für alle die Rückmeldungen, ich werde darüber nachdenken
 
Oben