Laden...

Natürliche Sortierung implementieren ("img2.jpg" vor "img10.jpg")

Erstellt von herbivore vor 19 Jahren Letzter Beitrag vor 19 Jahren 21.059 Views
Hinweis von herbivore vor 13 Jahren

Abgeteilt von ListView Sortierung (gehört eigentlich zu Sortierung der ListView Items).

Dieser Thread führt beim Durchlesen sehr plastisch vor Augen, viel Aufwand es bedeutet, einen (damaligen) Anfänger selbst bei einer typischen, relativ einfachen Übungsaufgabe bis zu einer fertigen Lösung an die Hand zu nehmen. Sicher kann man das mal ausnahmsweise und exemplarisch machen und ein solche individuelle Tutoriumssitzung kann für den einzelnen Anfänger ein großer Gewinn sein, aber es ist klar zu erkennen, dass dies im Allgemeinen die Zeit und die Hilfsbereitschaft der Helfer deutlich überstrapaziert.

Vielleicht wird dadurch wieder ein bisschen klarer, warum wir von Anfängern - getreu dem Motto "gemeinsam mehr erreichen" - mittlerweile erwarten, dass sie ihren Teil, nämlich das eigenständige Erarbeiten der Grundlagen, selbst übernehmen, bevor sie Fragen im Forum stellen.

Der Algorithmus von natcomapre ist in diesem Beitrag weiter unten beschrieben.
Ein fertiges Code-Snippet, welches Interger-Zahlen inkl. führender Nullen berücksichtigt, in diesem Beitrag weiter unten.

Ein weiteres Snippet findet sich in Natürliche Sortierung (Natural Sorting) für C#.

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren
Natürliche Sortierung implementieren ("img2.jpg" vor "img10.jpg")

Hallo -acid-,

naja, so schwer sollte natsort ja nicht zu implementieren sein. Wenn ich das richtig sehe, geht es ja hauptsächlich darum, dass "10.jpg" hinter "2.jpg" einsortiert wird.

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

tzja sollte... ich habe aber nicht wirklich ahnung wíe ich das umsetzen sollte.

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

das entscheidende der Sortierung ist ja nur der eigentliche Vergleich, nennen wir ihn natcmp, der zwei Strings bekommt. natcmp tut folgendes: Die beiden Strings von vorne zeichenweise zu vergleichen, solange das Zeichen keine Ziffer ist. Wenn das Zeichen eine Ziffer ist, zählt man die Länge der hier beginnenden Zahlen. Ist sind diese Längen gleich setzt man den zeichenweisen Vergleich für alle folgenden Ziffern fort, als wären sie Nicht-Ziffer-Zeichen.

Solange alle Zeichen und Zahlenlängen gleich sind, geht es immer zum nächsten Zeichen. Wenn irgendwann ein Unterschied festgestellt wird, liefert man -1, wenn das Zeichen im ersten String bzw. die Zahlenlänge des ersten Strings kleiner ist, +1 wenn es/sie größer ist. Kommt man zum Ende eines Strings, ohne einen Unterschied festgestellt zu haben, liefert man -1, wenn der erste String kürzer ist, +1 wenn der zweite kürzer ist und 0, wenn beide Strings gleichlang sind.

Das ganze berücksichtigt noch keine führenden Nullen. Das lässt sich dann aber auch später ergänzen. Außerdem geht dieser Algorithmus davon aus, dass alle auftretenden Zahlen als Integer betrachtet werden sollen. Eine Erweiterung auf gebrochene Zahlen wäre denkbar.

HTH

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

Also ich hab das mal so gemacht:

public int Compare(object x, object y)
{
string s1 = ((ListViewItem)x).SubItems[col].Text;
string s2 = ((ListViewItem)y).SubItems[col].Text;
int output = String.Compare(s1, s2);
return output;
}

Ok habe jetzt versucht dir zu folgen und das bisher von der Logik her so verstanden, als wäre result 1 größer und result -1 kleiner. Ich soll also jetzt solange vergleichen bis das Zeichen keine Ziffer ist.

Hm. Ich komme war nicht so ganz hinterher mit deiner Verfahrensweise, aber ich versuche mal das irgendwie hinzubiegen.

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

was ich meine ist, dass du 'String.Compare(s1, s2)' durch 'MyClass.NatCompare (s1, s2)' ersetzen soltest. Die Beschreibung von oben wäre dann die Implementierung von MyClass.NatCompare (s1, s2).

Um es nochmal mit anderen Worten etwas kürzer zu sagen: Einen String kann man vergleichen, indem man seine Zeichen von links nach rechts einzeln vergleicht. Bei NatSort sollen aber eingebettete Zahlen nicht ziffernweise verglichen werden, sondern nach ihrem Wert. Der Wert einer Zahl ist immer größer, wenn sie länger ist als die andere Zahl (von führende Nullen abgesehen). Deshalb wird statt dem Wert der Zahlen erstmal deren Länge verglichen. Erst wenn die Zahlen gleichlang sind, wird ziffernweise verglichen, denn hier bringt der ziffernweise Vergleich dasselbe Ergebnis wie ein Vergleich nach Wert (von den führenden Nullen, wie schon gesagt, abgesehen).

Anders ausgedrückt vergleicht NatSort zeichenweise, betrachtet aber eingebettete Zahlen als ein Zeichen.

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

ok dein prinzip leuchtet mir ein, aber ich glaube nicht, dass ich das technisch umsetzen kann. gibt es nicht irgendwo eine umsetzung?

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

meiner Einschätzung wäre die Umsetzung, zumal nach der schon sehr detailierten Beschrieibung, eine typische Übungsaufgabe, wie sie in Büchern für Einsteiger vorkommen - keinesfalls viel schwerer. Das solltest du eigenlich hinbekommen!

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

Klar sollte ich. Nur ist das Problem einfach, dass ich nicht direkt verstehe, wie ich das umsetzen soll. Wie gesagt ich versuche es...

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

schreib erstmal einen eigenen normalen zeichenweisen Vergleich MyClass.Compare (s1, s2).

Von vorne zeichenweise vergleichen. Wenn Zeichen unterschliedlich -1 bzw. +1 liefern, sonst zum nächsten Zeichen. Kommt man zum Ende eines Strings, ohne einen Unterschied festgestellt zu haben, liefert man -1, wenn der erste String kürzer ist, +1 wenn der zweite kürzer ist und 0, wenn beide Strings gleichlang sind.

Mit dieser Basis solle eine Erweiterung auf NatCompare um einiges leicher sein.

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

bin dabei... 😉

-
885 Beiträge seit 2004
vor 19 Jahren

frage:

wie lasse ich denn am besten meine schleife durlaufen?

gut ich könnte jetzt den größten wert beider strings testen und dann die schleife entsprechend oft durchlaufen lassen, aber geht das nicht auch ähnlich wie ich das hier habe?

for (int i=0; i<s1.Length && s2.Lenght; i++)
herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

mit


for (int i=0; i < s1.Length && i < s2.Lenght; i++)

würde es gehen, ich denke es ist aber praktischer nur 'i < s1.Length' als Schleifenbedingung zu nehmen und i ≥ s2.Lenght als erstes in der Schleife zu fragen.

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren
public int NatCompare(string s1, string s2)
		{
			for (int i=0; i<s1.Length; i++)
			{
				string letter_s1 = s1.Substring(i, 1);
				string letter_s2 = s2.Substring(i, 1);
				
				if (s1.Length == s2.Length)
				{
					return 0;
				}
				else
				{
					if (i >= s2.Length)
					{
						return 1;
					}
					else
					{
						if (letter_s1 != letter_s2)
						{
							return -1;
						}
					}
				}				
			}
			
			return -1;
		}

So ist jetzt so wie ich das verstanden habe...

  • Sind aber noch Fehler drin, weil er nicht richtig sortiert.

(Warum darf ich meine eigenen Beiträge nicht löschen, war ausversehen nen Doppelpost.)

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

vermutlich wirst du beim Testen feststellen, dass es nicht funktioniert. 🙂

Statt "sX.Substring(i, 1)" solltest du besser 'sX _' benutzen und kannst dann auch auf letter_sX verzichten.

Die Längen von s1 und s2 (innerhalb der Schleife zu testen) ist - sorry - Quatsch. Was immer nur interessiert ist ein Vergleich von i mit der jeweiligen Länge.

Und bei dem Vergleich von letter_s1 und letter_s2 (also besser - wie oben gesagt - s1 _ und s2 _) kommt es ja gerade darauf an, welches Zeichen größer bzw. kleiner ist. Entsprechend +1 oder -1 liefern.

Ansonsten geht das schon mal in die richtige Richtung!

HTH

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

richtig das hab ich festgestellt.

ach ok wusste ich nicht das es so auch geht g

aber du hast doch gesagt ich sollte die länge vergleichen...
hm jetzt wo ich deine beiträge das 20. mal lese, verstehe ich etwas mehr. das heisst also wenn zahlen drin vorkommen, dass es trotzdem als ein zeichen betrachtet werden soll.

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

"sX.Substring(i, 1)" lasse i´ch mir immer ein zeichen ausgeben um es zu vergleichen

Das ist mit klar! Ich meine eben nur, dass es besser ist stattdessen 'sX _' zu benutzen. Mit sX.Substring(i, 1) bekommst du einen String, der das eine Zeichen enthält, mit sX _ bekommst du direkt das Zeichen (als char).

du warst es auch, der sagte ich sollte die länge der strings vergleichen.

Was die Längen angeht habe ich geschrieben "Kommt man zum Ende eines Strings ...". Bei deinem Vergleich wird aber sofort beim ersten (und jedem weiteren) Schleifendurchlauf gerprüft, ob die Strings gleich lang sind. Da in diesem Fall 0 zurückgegeben wird, bedeutet das, dass Strings als gleich betrachtet werden, wenn sie gleich lang sind - unabhängig von Inhalt. Das will man offensichtlich nicht.

Aber es wird schon klappen!

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

herbivore: so ich habe mal ne nacht drüber geschlafen und ich denke ich blicke heute mehr durch. ich glaube mein problem war, dass ich zu viele dateien hatte und zuschnell vorrangegangen bin. jetzt gehe ich mal step by step durch.

also erstmal habe ich "1.jpg" und "10.jpg" welches durch...

MessageBox.Show(s1 + " | " + s2);
	 		
for (int i=0; i<s1.Length; i++)
{
  if (i >= s2.Length)
  {
    return 1;
  }
}
return -1;

... wohl richtig sortiert wird. Stimmst du mir bis hier überein? Ich habe dich bisher so verstanden als sollte ich erstmal die eigentliche länge des strings überprüfen. d.h. nen längerer string steht zwangsläufig unten. bis hier hin korrekt?

jetzt habe ich noch zusätzlich die "3.jpg" in das verzeichnis kopiert, diese steht aber jetzt vor der "1.jpg". sprich dafür habe ich noch keinen regelfall. wie soll ich das jetzt überprüfen? ...die zahl auslesen und die kleinere davon dann noch vorne?

also 1 heißt nach hinten und -1 nach hinten - ja?

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

nur noch mal zur Sicherheit, wir sind erstmal dabei einen "normalen" String-Vergleich zu schreiben? Also muss man auch noch nicht unterscheiden, ob die Zeichen in den Strings Buchstaben oder Ziffern (oder was auch immer) sind. Ok soweit? Du solltest zur Klarheit deshalb erstmal Dateinamen ohne Ziffern verwenden. So entstehen weniger Missverständnisse.

Der Code, denn du jetzt geschrieben hast, ist eine gute Basis. Er berücksichtigt die jedoch bisher nur die Länge der Strings Außerdem gibst du bisher nur -1 oder 1 zurück. Die Strings können aber auch gleichlang sein (0).

Natürlich ist auch der reine Längenvergleich nicht ausreichend, denn abc.jpg soll ja vor z.jpg kommen, obwohl der erste String länger ist.

Du musst also noch den Inhalt der Strings zeichenweise (also in der Schleife) vergleichen. Hier kommen s1_ und s2_ ins Spiel.

HTH

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren
for (int i=0; i<s1.Length; i++)
{
  if (i >= s2.Length)
  {
    return 1;
  }
  else
  {
    if (s1[i] > s2[i])
    {
      return 1;
    }
    else
    {
      return -1;
    }
  }
}
return -1;

..liefert:

10.jpg
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg

komischer weise ist plötzlich die 10 als erstes aufm schlauch steht

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

vorne weg: ich habe den Code mal so umgestellt, dass wir weniger Zeilen brauchen, gerade wenn wir noch den "natürlichen" Vergleich einbauen, wird das sonst nicht mehr handelbar.


for (int i=0; i<s1.Length; i++) {
  if (i >= s2.Length)  {
    return 1;
  }
  if (s1[i] > s2[i])  {
    return 1;
  }
  return -1;
}
return -1;

Wenn man return benutzt, kann - und sollte(!) - man sich das else sparen. Jetzt siehst du bestimmt auch klarer, dass deine Schleife maximal einmal durchlaufen wird.

Soweit bist du auf dem richtigen Weg. Es fehlen zwei Fälle:

  1. Die strings sind insgesamt gleich lang.
  2. Die momentan zu vergleichenden Zeichen sind gleich.

herbivore

PS: Wenn es nach mir geht, kommen sogar die returns noch auf die Zeile mit dem if.


for (int i=0; i<s1.Length; i++) {
  if (i >= s2.Length)  { return 1; }
  if (s1[i] > s2[i])  { return 1; }
  return -1;
}
return -1;

-
885 Beiträge seit 2004
vor 19 Jahren

geht sogar noch kürzer, indem man die klammern weglässt g
ok aber ich kann dir eh nix vormachen, wenns nach mir ging hätte ich dich schon längst zum moderator gemacht 🙂

for (int i=0; i<s1.Length; i++)
{
  if (i >= s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
  if (s1[i] == s2[i]) return 1; // macht die sortierung noch besser
  if (s1.Length == s2.Length) return 1; // verwürfelt die sortierung komplett
  return -1;				
}
return -1; 

also habe ich dich wohl bei punkt 2 falsch verstanden oder falsch angewendet.

-
885 Beiträge seit 2004
vor 19 Jahren

sorry... wer lesen kann ist klar im vorteil.

for (int i=0; i<s1.Length; i++)
{
  if (i >= s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
  if (s1[i] == s2[i]) return 1;
  if (s1 == s2) return 1;
  return -1;
}
return -1; 

so ich denke jetzt habe ich das erfüllt was du wolltest.

sortierung sieht aus wie folgt:

1.jpg
10.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

ganz ohne Klammern sparrt ja keine Zeilen mehr, verursacht aber bei späteren Programmänderungen nur (potentielle) Probleme.

Dein Code wird immer kompletter! Trotzdem möchte ich dich bitten, nicht einfach versuchsweise Anweisungen hinzuschreiben und zu probieren, ob richtig sortiert wird (Stichwort "macht die sortierung noch besser", "verwürfelt die sortierung komplett"), sondern mal wirklich versuchen zu überlegen, was dein Code macht (dazu kannst du das Programm im Kopf schnittweise durchspielen).

Dann fällt dir bestimmt auch auf, dass du zu keinem Zeitpunkt 0 zurückgibst, was aber die Rückgabe für komplett gleiche Strings ist. Ich kann dir verraten, dass die letzte (oder zumindest fast die letzte) Anweisung der fertigen Sortierroutine 'return 0;' sein wird, denn das die Strings in jeder Beziehung komplett gleich sind, weiß man eben erst (fast) am Ende, wenn man bis dahin keinen Unterschied gefunden hat.

Desweiteren gibst du einen Wert (und dann auch noch 1) zurück, sobald zwei Zeichen gleich sind. Das haut nicht hin. Wenn zwei Zeichen gleich sind, weiß man nur, dass man eben weitersuchen muss.

Und was die Längengleichheit angeht. Die kannst und solltest du erst feststellen, wenn auch alle Zeichen bis zum Ende eines der Strings gleich sind. Wenn dann auch noch beide Strings gleich sind, dann sind beide Strings insgesamt gleich (return 0) und wenn nicht, ist eben der zweite größer (return -1).

herbivore

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

auch wenn deine Überarbeitung jetzt "richtig" sortiert, gilt quasi noch alles, was ich zu dem beitrag davor geschrieben habe. (Sie sortiert nur zufällig richtig).

Abgesehen davon, ist Sortieren lassen keine gute Methode, eine Vergleichsroutine zu testen. Du solltest stattdessen, die Vergleichsroutine direkt mit Beispielwerten aufrufen und das Ergebnis ausgeben. Probiere dabei mindestes das:

0 = MyClass.NatCompare ("a", "a")
0 = MyClass.NatCompare ("aa", "aa")
-1 = MyClass.NatCompare ("a", "b")
-1 = MyClass.NatCompare ("aa", "ab")
-1 = MyClass.NatCompare ("a", "aa")
1 = MyClass.NatCompare ("b", "a")
1 = MyClass.NatCompare ("ab", "aa")
1 = MyClass.NatCompare ("aa", "a")

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

bin zwar noch nicht komplett drauf gekommen, aber ich glaube mir wird es immer klarer.

for (int i=0; i<s1.Length; i++)
{
  if (i >= s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
 
  if (s1.Length < s2.Length) return -1; // könnte man auch weglassen oder? weil es wird ja eh -1 am ende ausgegeben.
  if (s1.Length > s2.Length) return 1;
  if (s1 == s2) return 0;					
  
  return -1;
}

ich bekomme jetzt:

0 = MyClass.NatCompare ("a", "a") ok
0 = MyClass.NatCompare ("aa", "aa") ok
-1 = MyClass.NatCompare ("a", "b") ok
-1 = MyClass.NatCompare ("aa", "ab") ok
-1 = MyClass.NatCompare ("a", "aa") ok
1 = MyClass.NatCompare ("b", "a") ok
1 = MyClass.NatCompare ("ab", "aa") -1
1 = MyClass.NatCompare ("aa", "a") ok

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

deine Schleife wird immernoch nur max. einmal durchlaufen. Wenn die Zeichen aber gleich sind, muss sie öfter durchlaufen werden. Dafür muss sie nicht nur bei 's1_ > s2_', sondern auch bei 's1_ < s2_' verlassen werden (jetzt mit -1).

Was die String-Längen angeht, musst (und darfst) du diese in der Schleife gar nicht weiter betrachten, denn mit 'i<s1.Length' in der for-Schleifen-Bedingung ist sichergestellt, dass du bei s1 noch nicht am Ende bist und mit 'i ≥ s2.Length' ist sicher gestellt, dass wenn s2 zu Ende ist, die Vergleichsroutine auch korrekt verlassen wird.

Nochmal: Die Stringlänge interessiert erst am Schluss. Erst wenn man am Ende von s1 angekommen ist (und alle Zeichen bis dahin gleich waren) interssiert, ob s2 noch ein Stück länger ist oder nicht.

Das soviele Werte beim Test stimmen, ist übrigens (leider) Zufall.

Aber weit bis zum Ziel ist es trotzdem nicht mehr.

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

achso ok. dachte schon für was dann i≥s1.length da ist.

ok wenn ich dich richtig verstanden habe, sollte das so in die richtige richtung gehen...

for (int i=0; i<s1.Length; i++)
{
  if (i >= s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
  if (s1[i] < s2[i]) return -1;
  return -1;
}
if (s1.Length < s2.Length) return -1;
if (s1.Length > s2.Length) return 1;
if (s1 == s2) return 0;	
return -1; 

sie läuft 1x durch. mh. eigentlich müsste ich doch dann noch s1_ == s2_ nutzen?!

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

die Version ist jetzt schon nahe dran. Deshalb schreib ich mal direkt, was noch zu ändern ist.


for (int i=0; i<s1.Length; i++)
{
  if (i >= s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
  if (s1[i] < s2[i]) return -1;
  // das return -1; muss weg, denn du weißt, an dieser Stelle, dass 
  // die beiden aktuellen Zeichen *gleich* sind. Da der String noch nicht 
  // zu Ende ist (bzw. man das zumindest hier noch nicht weiß), kannst du 
  // eben auch noch nichts zurückgeben, weil du eben noch nicht weiß
  // was noch kommt und welcher String größer oder kleiner ist, oder ob 
  // sie gleich sind. Wenn Du das return -1; wegnimmst, ann auch 
  // endlich deine Schleife mehrmals durchlaufen werden.
}
if (s1.Length < s2.Length) return -1;

// die abfrage 'if (s1.Length > s2.Length) return 1;' ist ok, aber überflüssig, 
// wenn s1 länger als s2 ist, dann wurde die Routine schon oben in der Schleife
// bei 'if (i >= s2.Length) return 1;'verlassen 

// 'if (s1 == s2) return 0;' naja, '==' für Strings benutzen ist gemogelt. Die
// Schleife oben hat schon gezeigt, dass alle Zeichen von s1 mit denen in s2
//  übereinstimmen. Wenn jetzt die Strings auch noch gleich lang sind,
// dann sind sie eben insgesamt völlig gleich, also reicht:
if (s1.Length == s2.Length) { return 0; }

return -1;

Wenn ich jetzt nicht geschudert habe, müsste es das erstmal sein
herbivore

PS: Ich muss jetzt bald mal weg und bin erst zwischen 20 und 21 Uhr wieder da.

-
885 Beiträge seit 2004
vor 19 Jahren

ok chef. bis dahin erstmal nen dickes danke.

bekomme überall "ok" heraus. auch die schleife läuft mehrmals durch.

frage:
wäre "if (s1.Length == s2.Length) return 0;" nicht unnötig, weil es kann meiner meinung nach keine zwei gleichen strings geben?!

so jetzt muss ich also anfangen, auf zahlen im string zu überprüfen, wenn ich dic richtig verstanden habe. habe dazu folgende idee:

  1. char array mit 10 elementen (0-9)
  2. in der schleife mit indexofany überprüfen, ob ein element von array enthalten ist.
  3. mir die zahl die ich entdeckt habe zu merken und mit der anderen vergleichen und die größere gewinnt.

joa soviel zu meiner idee g
(habe nämlich deine erklärung zu anfang nicht ganz verstanden.)

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

zwei identische Strings können durchaus vorkommen. Erstmal schreiben wir ja allgemeine eine Vergleichsfunktion. Das diese Funktion für eine Sortierung von Dateien verwendet werden soll, ist klar, aber nur ein möglicher Verwendungszweck. In meinen Testfällen kommen z.B. identische Strings vor und auch beim Sortieren kann mehrmals der gleiche Strings vor kommen (z.B. Sortieren nach Interpret bei deiner MP3 Sammlung).

Das mit dem IndexOf könnte man machen, passt aber nicht gut zu dem, was wir bisher haben. Stattdessen muss man in der Schleife einfach gucken, ob s1_ und s2_ beides Ziffern sind (char.IsDigit-Methode), denn nur Zahlen, die an der gleichen Stelle in den Strings anfangen interessieren uns ja (und sie interessiern auch nur dann, wenn alle Zeichen vor den Zahlen in beiden Strings gleich sind).

Wenn man nun den Anfang einer Zahl gefunden hat, muss man erstmal die Länge der Zahl ermitten (Teilaufgabe: wie macht man das?). Wenn die Zahlen unterschiedlich lang sind, gibt es wieder ein return 1 bzw return -1. Ansonsten müssen wir die Zahlen zeichenweise vergleichen, als wären es Buchstaben (bzw. irgendwelche anderen Zeichen), also quasi die Schleife normal weiter durchlaufen lassen. Führende Nullen ignorieren wir bei diesem Anzatz erstmal. Die kommen später dazu.

Die Idee, wenn wir auf zwei Zahlen stoßen, die an der selben Stelle anfangen, ist, dass wir dann die Größe der Zahlen vergleichen müssen. Das machen wir in den zwei beschrieben Schritten: 1. Längenvergleich und evtl. 2. zeichenweisen Vergleich.

Beispiel 1. Fall: 1000 ist größer als 256, weil 1000 länger ist als 256
Beispiel 2. Fall: 2581 ist größer als 2567, weil die 8 größer ist als die 6 und die Ziffern davor gleich sind

Dann mal ran!

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

so guckst du:

string s1basket = "";
string s2basket = "";
int oa;
int ob;
	 		
for (int i=0; i<s1.Length; i++)
{
  if (i >= s2.Length) return 1;
  if (Char.IsDigit(s1[i]) && Char.IsDigit(s1[i]))
  {
    oa = 0;
    for (oa=i; oa<s1.Length; oa++)
    {
      if (Char.IsDigit(s1[oa])) s1basket += s1[oa].ToString();
    }

    ob = 0;
    for (ob=i; ob<s2.Length; ob++)
    {
      if (Char.IsDigit(s2[ob])) s2basket += s2[ob].ToString();
    }
  
    if (oa > 0 && ob > 0)
    {
      if (Convert.ToInt64(s1basket) > Convert.ToInt64(s2basket)) return 1;
      return -1;
    }
  }
  if (s1[i] > s2[i]) return 1;	 			
  if (s1[i] < s2[i]) return -1;	
}
if (s1.Length == s2.Length) return 0;
return -1;

also es funktioniert ganz gut. hier und da gibts bestimmt noch fehler. kannst ja mal drüber gucken.

M
20 Beiträge seit 2005
vor 19 Jahren

Hi,

ich kommentier mal ein wenig in deinen Quelltext herein 😉

Original von -acid-
so guckst du:

string s1basket = "";  
string s2basket = "";  
int oa;  
int ob;  
   		  
for (int i=0; i<s1.Length; i++)  
{  
  if (i >= s2.Length) return 1;  
  // Die zweite Überprüfung soll vermutlich auf s2 überprüfen, nicht nochmal auf s1. Ich schätze ist nur nen Tippfehler :)  
  // Ansonsten schonmal der richtige Ansatz  
  if (Char.IsDigit(s1[i]) && Char.IsDigit(s1[i]))  
  {  
    // Der Teil der jetzt kommt passt noch nicht wirklich  
    // Als erstes solltest Du, wie herbi oben schon geschrieben hat, die Länge der Zahl überprüfen, die in Deinem String vorkommt  
    // Sind die Zahlen unterschiedlich lang, brauchst Du die einzelnen Ziffern nicht mehr in der Schleife vergleichen, denn die längere Zahl ist auch die grössere  
    // Es gilt:   "a10a" > "a9a"  
  
  
      
    // Warum benutzt Du hier nicht einfach wieder Deine for Schleife, die die Zeichen einzeln vergleicht, wie Du es auch bei Buchstaben machen würdest?  
    // Asserdem würdest Du hier auf Probleme laufen, wenn deine strings aus mehreren Kombinationen von Buchstaben und Zahlen bestehen, da Du ungeachtet der Zahlenlänge den string bis zu Schluss durchläufst  
    // Es gilt: "a2a" > "a1a9"  
    // Bei Dir würd herauskommen: "a2a" < "a1a9"  
    oa = 0;  
    for (oa=i; oa<s1.Length; oa++)  
    {  
      if (Char.IsDigit(s1[oa])) s1basket += s1[oa].ToString();  
    }  
  
    ob = 0;  
    for (ob=i; ob<s2.Length; ob++)  
    {  
      if (Char.IsDigit(s2[ob])) s2basket += s2[ob].ToString();  
    }  
    
    if (oa > 0 && ob > 0)  
    {  
      if (Convert.ToInt64(s1basket) > Convert.ToInt64(s2basket)) return 1;  
      return -1;  
    }  
  }  
  if (s1[i] > s2[i]) return 1;	 			  
  if (s1[i] < s2[i]) return -1;	  
}  
if (s1.Length == s2.Length) return 0;  
return -1;  

also es funktioniert ganz gut. hier und da gibts bestimmt noch fehler. kannst ja mal drüber gucken.

Ich hoffe ich hab mich nirgendwo schwer vertan g

Greetz
MoD

Ps: Sorry fürs einmischen 😁

Life is a piece of shit, when you look at it!

-
885 Beiträge seit 2004
vor 19 Jahren

if (Char.IsDigit(s1_) && Char.IsDigit(s2_)) is klar. danke.

weißt du das problem ist, dass die schleife aufhört zu laufen, wenn

if (s1_ > s2_) return 1;

kommt. das heißt: aa2.jpg und ab3.jpg hört bei dem dritten zeichen auf, weil 2 ja > 3...

M
20 Beiträge seit 2005
vor 19 Jahren

Original von -acid-
weißt du das problem ist, dass die schleife aufhört zu laufen, wenn

if (s1_ > s2_) return 1;

kommt. das heißt: aa2.jpg und ab3.jpg hört bei dem dritten zeichen auf, weil 2 ja > 3...

Es ist richtig, dass die äussere for Schleife beim zweiten Durchlauf aussteigt, da
if (s1_ < s2_) return -1;
"a" < "b"
true ist.
Dein Posting versteh ich aber grad nicht 🙂

Der nächste Schritt sollte auf jeden Fall erstmal sein, dass Du Dir in dem "if (Char.IsDigit(s1_) && Char.IsDigit(s1_))
" etwas ausdenkst um die Länge der in dem String vorkommenden Zahlen zu vergleichen.
Testfälle:

1 = MyClass.NatCompare ("a10a", "a9a1")
-1 = MyClass.NatCompare ("a9a1", "a10a")

Die Schleifen würde ich erstmal auskommentieren.

Greetz
MoD

Life is a piece of shit, when you look at it!

-
885 Beiträge seit 2004
vor 19 Jahren

ja ok. leuchtet mir ein, dass ich nen fehler bekomme, wenn mehrere zahlen in nem string sind (aa10b11), aber ich steh mal wieder aufm schlauch. meine schleife schreibt halt alles in ne sammelvariable und wertet dann aus...

ich wüsste also nicht, wie ich jetzt das problem lösen sollte...

M
20 Beiträge seit 2005
vor 19 Jahren

Wie gesagt: Eins nach dem anderen 😉

Zuerst rausfinden, wie lang die Zahl ist. Haben wir das Problem gelöst ergibt sich die Lösung für Dein Problem mit der Schleife fast von alleine, indem Du die Abbruchbedingung änderst 👍

Greetz
MoD

Life is a piece of shit, when you look at it!

-
885 Beiträge seit 2004
vor 19 Jahren

ei des hab ich doch. ich setze den zeiger auf die erste zahl oa=i und zähle von da aus...

M
20 Beiträge seit 2005
vor 19 Jahren

Nein zählen tust du nicht. Du durchläufst den string einfach weiter und führst schon Operationen aus. Das führt zu Problemen. Ich schreibe mal umgangssprachlich auf, was zu tun ist:

if (Char.IsDigit(s1_) && Char.IsDigit(s1_))
{
ermittle, wie lang die zahl in s1 ist und merke sie dir
ermittle, wie lang die zahl in s2 ist und merke sie dir
vergleiche die länge von der zahlen in s1 und s2
ist die zahl in s1 länger, dann ist s1 der grössere string
ist die zahl in s2 länger, dann ist s2 der grössere string

sind die zahlen gleich lang, dann müssen wir überprüfen, welche zahl grösser ist
}

Den Fall, dass die Zahlen gleich lang sind machen wir später. Erstmal interessiert uns nur der Fall, dass die Zahlen unterschiedliche Länge haben.

Beispiele:
s1 = "a10a" && s2 = "a9a"
s1 = "a9a3" && s2 = "a10a2"

Ich hoffe jetzt ist klarer geworden, was zu tun ist.

Greetz
MoD

Life is a piece of shit, when you look at it!

-
885 Beiträge seit 2004
vor 19 Jahren

pseudocode 😉

was zu tun ist, ist mir schon klar, aber ich kann doch nur ermitteln wieviel zahlen im string sind indem ich das hier mache:

oa = 0;
    for (oa=i; oa<s1.Length; oa++)
    {
      if (Char.IsDigit(s1[oa])) s1basket += s1[oa].ToString();
    }

in s1basket steht jetzt die zahl (unabhäng mal davon, dass auch mehrere zahlen vorkommen können). anders wüsste ich nicht wie...

M
20 Beiträge seit 2005
vor 19 Jahren

Ja das ist fast eine Möglichkeit. Nicht unbedingt die performanteste aber es funktioniert. Allerdings solltest Du Dir nicht den String merken sondern mitzählen, wie viele Ziffern Du in Folge findest und wenn das aktuelle Zeichen keine Ziffer mehr ist aus der Schleife springen.

Also:


oa = 0;
int count1 = 0;
    for (oa=i; oa<s1.Length; oa++)
    {
      if (Char.IsDigit(s1[oa])) {
        count1++;
      }
      else {
        break;
      }
    }

Wenn man das für beide strings macht weiss man, wie lang die Zahlen sind.
Bestimmt nicht die eleganteste und schnellste Lösung, aber es funktioniert 😉

Greetz
MoD

Ps: Schön wäre vermutlich, wenn man einen RegEx verwendet.

Life is a piece of shit, when you look at it!

-
885 Beiträge seit 2004
vor 19 Jahren

ok aber:

...
sind die zahlen gleich lang, dann müssen wir überprüfen, welche zahl grösser ist...

kann ich nicht, weil ich nirgends den inhalt (zahl) zwischengespeichert habe, also entweder mache ich das oben gleich mit, oder ich mache das jetzt extra?!

M
20 Beiträge seit 2005
vor 19 Jahren

Den Inhalt hast Du doch dadurch, dass Du die Länge hast.
Vergleiche aus Deinen strings genau das Stück, welches die Zahl ist (von Position i bis position i+count1).
Dafür kannst Du dann sogar die wunderbar die String.Compare() Methode verwenden.

Des weiteren würde ich das Vergleichen erst machen, nachdem ich die Längen ermittelt und verglichen hab. Der Grund dafür ist, dass man für das Länge ermitteln eigentlich keine Schleife benutzen möchte.
Man stelle sich vor, man hat einen String der Form "ab"+1MillionZiffern"+"ab"
Dann durchläuft man 2 Millionen mal eine Schleife nur um die Anzahl der Ziffern rauszufinden. Könnte ein bisschen langsam werden das Ganze.

Daher das Vergleichen der beiden Zahlen erst nach dem ermitteln der Längen machen und später das ermitteln der Längen umbauen.
Spontan würde ich auf einen RegEx tippen, der die Zahl ausschneidet und dann nur noch die Length Eigenschaft abgefragt werden muss. Vermutlich immernoch nicht die eleganteste Lösung 😉

Greetz
MoD

Life is a piece of shit, when you look at it!

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo ihr beiden,

@MastaOfDisasta:
Das Einmischen mehr als ok. Das Forum ist ja keine Privatveranstaltung. Ich hatte eher Befrüchtungen, dass -acid- und ich es dazu machen. Bin froh, dass das Thema noch andere interessiert.

Was die die zweimal eine Million Ziffern angeht, denke ich, dass das erstens nicht zu vermeiden ist (jedenfalls nicht, wenn wir hier eine einfach zu programmierende Lösung suchen) und zweitens in der Praxis keine negativen Auswirkungen haben wird. BTW: Auch RexEx können nicht zaubern und müssten den String hier zeichenweise durchsuchen.

@-acid-:
Dein Code von oben ist von der Struktur her schon ziemlich gut. Ich denk, du bist machmal einfach etwas ungeduldig. Wir machen das hier Schritt für Schritt und du wirst sehen, dass am Ende sich schon alles zusammenfügen wird.

Es ist wirklich so: Erstmal brauchen wir nur die Länge der beiden Zahlen, die gerade angefangen haben, mehr nicht!

Wieviele verschiedene Zahlen in dem String wo enthalten sind, ist völlig egal. Nehmen wir nochmal ein Beispiel ohne Zahlen: Wenn man den String aaaa... und aaab... vergleicht, ist für das Ergebnis des Vergleichs doch völlig egal, was nach dem vierten a bzw. dem b kommt. An dieser Stelle unterschieden sich die Strings und der zweite String ist größer als der zweite, fertig. Andererseits interessiert uns die vierte Stelle doch nur deshalb, weil alle Zeichen davor gleich waren.

Das ist der Trick der ganzen Sache: Solange alles gleich ist, machen wir weiter. Wenn es den ersten Unterschied gibt, ist Schluss.

Auf die Zahlen bezogen bedeutet das: Entweder die beiden Zahlen sind gleich (und alles davor natürlich auch), dann interessiert die beiden Zahlen nicht mehr und wir suchen dahinter weiter, oder sie unterscheiden sich, und dann interessiert uns alles dahinter nicht mehr. Was uns interessiert, ist also immer genau das Zeichen oder die Zahl, die wir gerade untersuchen. Alles andere interessiert (gerade) nicht.

Dadurch wird es aber sehr übersichtlich, weil man weder vorausschauen, noch zurückblicken muss (ok, um die Länge der Zahl zu ermitten, muss man natürlich schon vorausschauen, aber das ist auch alles).

Vielleicht hilft das ja schon mal für einen weiteren Versuch.

Als Ergänzung noch folgendes: Wenn du die Länge der beiden Zahlen (sagen wir l1und l2) weißt, gibt es drei Möglichkeiten: Bei l1 <l2 oder l1>l2 machst du gleich ein return, fertig. Und bei l1 == l2 machst du erstmal gar nichts. Dann übernimmt die Hauptschleife das zeichenweise vergleichen der einzelnen Ziffern der Zahlen für dich. Sprich wenn die Zahlen gleich lang sind, werden sie einfach so verglichen, als wären die Ziffern Buchstaben.

Das einzige "Problem" dabei ist, dass, wenn man zur zweiten Ziffer kommt, wieder die Längenermittlung vorgenommen wird. Da sie aber zumgleichen Ergebnis kommt (bzw. kommen muss) funktioniert der Vergleich trotzdem korrekt. Dieses kleine Performanceproblem lösen wir dann im Anschluß.

HTH

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

Hallo Ihr,

sorry mir gings am Donnerstag und Freitag nicht wirklich gut - wie heute leider, aber ich versuchs mal.

Hier mein bisheriges Ergebnis:

	public int NatCompare(string s1, string s2)
		{
	 		int oa;
	 		int ob;
	 		
 			for (int i=0; i<s1.Length; i++)
	 		{
	 			if (i >= s2.Length) return 1;
	 			
	 			if (Char.IsDigit(s1[i]) && Char.IsDigit(s2[i]))
  				{
	 				oa = 0;
					int count1 = 0;
					for (oa=i; oa<s1.Length; oa++)
					{
						if (Char.IsDigit(s1[oa])) count1++;
						else break;
			   		} 
					
					ob = 0;
					int count2 = 0;
					for (ob=i; ob<s2.Length; ob++)
					{
						if (Char.IsDigit(s2[ob])) count2++;
						else break;
			   		}
					
					if (count1 > count2) return 1;
					if (count1 < count2) return 1;
					if (count1 == count2)
					{
					  //hier soll ich ja erstmal nichts machen.	
					}
  				}
	 			
	 			if (s1[i] > s2[i]) return 1;	 			
  				if (s1[i] < s2[i]) return -1;	
 			}
 			
	 		if (s1.Length == s2.Length) return 0;
	 		
			return -1;
		}
herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

Hauptsache es geht dir wieder besser. Und das scheint ja so zu sein, denn dein NatCompare ist wirklich gut. Ich gehe mal davon aus, dass das return 1 statt -1 in 'if (count1 < count2) return 1;' lediglich ein Flüchtigkeitsfehler ist. Ansonsten ist, soweit ich das sehen kann, alles richtig. Du hast damit ein NatCompare, das bis auf führende Nullen korrekt funktioniert.

Im Folgenden habe ich das Ganze nur noch ein bisschen abgekürzt. Dazu benutze ich diese vier "Tricks":

  1. Es kommt uns ja nicht darauf an, wie lang die beiden Zahlen genau sind, sondern nur welche von beiden länger ist. Deshalb verzichte ich auf count1 und count2. BTW: die Variablen 'oa' und 'ob' habe ich in 'o1' und 'o2' umbenannt, weil die Strings ja auch 's1' und 's2' und nicht 'sa' und 'sb' heißen. Und genau diese 'o1' und 'o2', die angeben, wo die Zahlen zu Ende sind, reichen für den Vergleich, welche Zahl länger ist.

  2. Die IsDigit-Bedingung habe ich aus den inneren Schleifen in die Schleifenbedingung gezogen. Das ist nicht nur eleganter, sondern trifft die Sache auch besser, weil es uns ja egal ist, ob die Zahl aufhört, weil der String zu Ende ist oder keine Ziffer mehr kommt. Diese Bedingungen sind gleichwertig und sollten deshalb an gleicher Stelle erscheinen.

  3. Das Feststellen der Länge kann gleich bei i+1 beginnen, denn für i wissen wir ja schon, dass dort Ziffern stehen (und das der String bei i noch nicht zu Ende ist, wissen wir auch).

  4. Die Abfrage o1 == o2 (früher count1 == count2) ist nicht nötig, weil an dieser Stelle o1 automatisch gleich o2 sein muss. Wäre o1 < o2 wären wir durch das eine return ausgestiegen, bei o1 > o2 durch das andere, also kommen wir an die Stelle nur, wenn o1 == o2.

Somit sieht das Ganze jetzt so aus:


public int NatCompare(string s1, string s2)
{
   int o1;
   int o2;

   for (int i=0; i<s1.Length; i++) {
      if (i >= s2.Length) return 1;

      if (Char.IsDigit(s1[i]) && Char.IsDigit(s2[i])) {
         for (o1=i+1; o1<s1.Length && Char.IsDigit(s1[o1]); o1++) { }
         for (o2=i+1; o2<s2.Length && Char.IsDigit(s2[o2]); o2++) { }
         if (o1 > o2) return 1;
         if (o1 < o2) return -1;
         //hier soll ich ja erstmal nichts machen.
      }

      if (s1[i] > s2[i]) return 1;
      if (s1[i] < s2[i]) return -1;
   }

   if (s1.Length == s2.Length) return 0;

   return -1;
}

Jetzt wollen wir noch verhinden, dass die Längen der Zahlen immer wieder ermittelt werden. Dazu reicht eine einfache boolsche Variable, die uns anzeigt, ob wir das schon gemacht haben. Du kannst dich daran gerne selber versuchen. Dann solltest du aber erstmal nicht weiterlesen, weil hier gleich eine mögliche Lösung folgt:


public int NatCompare(string s1, string s2)
{
   int o1;
   int o2;
   bool fInsideNumber = false;

   for (int i=0; i<s1.Length; i++) {
      if (i >= s2.Length) return 1;

      if (fInsideNumber) {
         if (!char.IsDigit (s1 [i])) {
            fInsideNumber = false;
         }
      } else {
         if (Char.IsDigit(s1[i]) && Char.IsDigit(s2[i])) {
            for (o1=i+1; o1<s1.Length && Char.IsDigit(s1[o1]); o1++) { }
            for (o2=i+1; o2<s2.Length && Char.IsDigit(s2[o2]); o2++) { }
            if (o1 > o2) return 1;
            if (o1 < o2) return -1;
            fInsideNumber = true;
         }
      }

      if (s1[i] > s2[i]) return 1;
      if (s1[i] < s2[i]) return -1;
   }

   if (s1.Length == s2.Length) return 0;

   return -1;
}

Du solltest jetzt die Testfälle erweitern, so dass auch Strings mit Zahlen vorkommen. Dann kannst du das NatCompare draufloslassen und schauen, ob unsere Erwartungen erfüllt werden.

Bleiben noch die führenden Nullen. Ich kann schon mal soviel sagen. Die führeden Nullen zu berücksichtigen erfordert mehr Aufwand, als ich ursprünglich dachte. Die Routine wurde bei mir gegenüber der bisher letzten Version (die mit fInsideNumber) um ca. 2/3 länger. Das ist schon eine gewisse Herausforderung.

Aber gehen wir das systematisch an: Zunächst müssen wir vor dem Zahlenlängenermitteln die führenden Nullen überspringen (und uns deren Anzahl merken). Nach dem Zahlenlängenermitteln vergleichen wir wie gehabt die Zahlenlängen. Wenn diese gleich sind, müssen die Zahlen selbst verglichen werden (das macht wieder die Hauptschleife, die jetzt aber berücksichtigen muss, dass wir - ggf. unterschiedlich(!) viele - führende Nullen übersprungen haben). Erst wenn die Zahlen gleich sind, kommen die führenden Nullen wieder ist Spiel. Dann sollte die Zahl größer sein, die mehr führende Nullen besitzt. Leider müssen wir an verschiedenen Stellen berücksichtigen, ob bzw. dass die Zahlen gerade zu Ende sind. Eine Stellle ist natürlich bei 'fInsideNumber = false;'. Die andere Stelle ist aber hinter der Hauptschleife, nämlich wenn die Zahlen am Ende der Strings zu Ende sind.

Vermutlich ist es um einiges einfacher, erstmal eine Version zu erstellen, die führende Nullen nur überspringt/ignoriert und diese Überspringen in der Hauptschleife berücksichtigt.

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

Hm ok. Also das mit den führenden Nullen gehe ich später an. Leider sortiert er nicht richtig.

1.jpg
10.jpg <-- falsch...
11.jpg
12.jpg
13.jpg
14.jpg
15.jpg
16.jpg
17.jpg
18.jpg
19.jpg
2.jpg
20.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
ab1000.jpg <-- falsch...
ab256.jpg
wallpaper.jpg
z.jpg

herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

das liegt aber dann aber wohl nicht nicht an dem NatCompare (oder hast du noch das falsche 'return 1;' statt 'return -1;' drin). Ich habe es bei mir getestet (die Version mit dem fInsideNumber) und da geht es.

herbivore

-
885 Beiträge seit 2004
vor 19 Jahren

*argh*
Ich könnte mich manchmal für meine Fehler selbst schlagen. autsch

So Thema führende Nullen. Ich versuchs dann mal...

-
885 Beiträge seit 2004
vor 19 Jahren

Ok, bevor ich jetzt wieder ewig falsch programmiere, wollte ich erstmal etwas Klarheit schaffen, deswegen teile ich das Ganze mal in noch kleinere Schritte 🙂

  1. Ich prüfe also vor "if ('fInsideNumber)" mit "if (s1_ == '0')" auf eine Null.
  2. Mach ich jetzt einfach ne Variable und erhöhe die +1 oder muss ich da wieder ne for-Schleife nutzen, um die Anzahl der Nullen zu speichern?
  3. Jetzt soll ich soll "überspringen" (Schleife weiterlaufen lassen) - das tue ich mit return -1 ?!
herbivore Themenstarter:in
49.485 Beiträge seit 2005
vor 19 Jahren

Hallo -acid-,

zu 1. Nein, das Testen auf führende Nullen musst du nur einmal am Begin der Zahlen durchführen, also direkt nach 'if (Char.IsDigit(s1_) && Char.IsDigit(s2_)) {'.

zu 2. Du brauchst zwei neue for-Schleifen und zwei neue Varaiblen, um dir die Anzahl der führenden Nullen der beiden Zahlen zu merken.

zu 3. 'return -1' verlässt NatCompare. Das ist so ziemlich das Gegenteil von 'die Schleife weiterlaufen lassen' 🙂 Beim "Überspringen", kommen jetzt die beiden neuen Variablen aus 'zu 2.' in Spiel, d.h. "übersprungen" wird, in dem in s1_ zu i die Anzahl der "übersprungenen" Nullen hinzugefügt wird, bei s2 natürlich entsprechend. Also an allen Stellen, wo i (lesend) benutzt wird, muss man immer die Anzahl der führenden Nullen hinzurechen.

herbivore