Frage

Während normalerweise gut es ist, immer die richtige Sprache für den Job zu wählen, kann es manchmal aufschlussreich sein, etwas in einer Sprache zu versuchen und zu tun, das wild ungeeignet ist.

  1. Es können Sie das Problem besser verstehen helfen. Vielleicht haben Sie nicht Haben es die Art und Weise zu lösen, die Sie dachten, Sie getan haben.
  2. Es können Sie die Sprache besser verstehen helfen. Vielleicht unterstützt es mehr Funktionen, als Sie realisiert.

Und drückt diese Idee es unlogisch Abschluss ... wie würden Sie quicksort in einer Batch-Datei implementieren? Ist es überhaupt möglich?

War es hilfreich?

Lösung

Es stellte sich heraus, es ist nicht so schwer wie Sie vielleicht denken. Die Syntax ist hässlich wie die Hölle, aber die Batch-Syntax ist tatsächlich in der Lage einige überraschende Dinge, einschließlich Rekursion, lokale Variablen und etwas überraschend anspruchsvolle Parsing von Strings. Verstehen Sie mich nicht falsch, es ist eine schreckliche Sprache, aber zu meiner Überraschung ist es nicht völlig gelähmt. Ich glaube nicht, dass ich etwas über quicksort gelernt, aber ich viel über Batch-Dateien gelernt!

In jedem Fall ist hier quicksort in einer Batch-Datei - und ich hoffe, Sie haben so viel Spaß versuchen, die bizarre Syntax zu verstehen, während es zu lesen, wie ich beim Schreiben tat. : -)

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

call :qSort %*
for %%i in (%return%) do set results=!results! %%i
echo Sorted result: %results%
ENDLOCAL
goto :eof

:qSort
SETLOCAL
    set list=%*
    set size=0
    set less=
    set greater=
    for %%i in (%*) do set /a size=size+1
    if %size% LEQ 1 ENDLOCAL & set return=%list% & goto :eof
    for /f "tokens=2* delims== " %%i in ('set list') do set p=%%i & set body=%%j
    for %%x in (%body%) do (if %%x LEQ %p% (set less=%%x !less!) else (set greater=%%x !greater!))
    call :qSort %less%
    set sorted=%return%
    call :qSort %greater%
    set sorted=%sorted% %p% %return%
ENDLOCAL & set return=%sorted%
goto :eof

Nennen Sie es, indem es eine Reihe von Zahlen geben auf der Kommandozeile zu sortieren, die durch Leerzeichen getrennt. Beispiel:

C:\dev\sorting>qsort.bat 1 3 5 1 12 3 47 3
Sorted result:  1 1 3 3 3 5 12 47

Der Code ist ein bisschen wie ein Schmerz zu verstehen. Es ist im Grunde Standard quicksort. Key-Bits sind, dass wir Zahlen in einem String sind speichern - armer Mann Array. Die zweite for-Schleife ist ziemlich unklar, es ist im Grunde Aufspalten das Array in einem Kopf (das erste Element) und einem Schwanz (alle anderen Elemente). Haskell tut es mit der Notation x: xs, aber Batch-Dateien tun es mit einer für mit dem Schalter / f genannt Schleife. Warum? Warum nicht?

Die SETLOCAL und ENDLOCAL Anrufe lassen Sie uns lokale Variablen tun - Art. SETLOCAL gibt uns eine vollständige Kopie der ursprünglichen Variablen, aber alle Änderungen vollständig ausgelöscht werden, wenn wir ENDLOCAL nennen, was bedeutet, dass Sie nicht einmal mit der anrufenden Funktion Globals kommunizieren können. Dies erklärt die hässliche Syntax „ENDLOCAL & set return =%% sortiert“, die tatsächlich funktioniert trotz allem, was Logik anzeigen würde. Wenn die Zeile der sortierte Variablen ausgeführt wird nicht gewischt worden, weil die Leitung noch nicht ausgeführt wurde - dann anschließend das Return-Variable wird nicht gewischt, weil die Leitung bereits ausgeführt worden ist. Logisch!

Auch amüsante, können Sie grundsätzlich keine Variablen innerhalb einer Verwendung für Schleife, weil sie nicht ändern können - die für die Schleife eine der mit den meisten der Punkt entfernt. Die Abhilfe ist ENABLEDELAYEDEXPANSION zu setzen, die funktionieren, aber macht die Syntax noch hässlicher als normal. Beachten wir nun eine Mischung aus Variablen referenziert nur durch ihren Namen haben, indem sie mit einem einzigen% prefixing, indem man sich mit zwei% prefixing, indem man sich in% Einwickeln oder von ihnen in Einwickeln!. Und diese unterschiedlichen Arten von Variablen Referenzierung sind fast vollständig NICHT austauschbar!

Anders als das, sollte es relativ einfach zu verstehen!

Andere Tipps

Hier ist eine lesbare Version, die ich vor einer Weile geschrieben:

@echo off

echo Sorting:  %*

set sorted=

:sort
:: If we've only got one left, we're done.
if "%2"=="" (
  set sorted=%sorted% %1
  :: We have to do this so that sorted gets actually set before we print it.
  goto :finalset
)
:: Check if it's in order.
if %1 LEQ %2 (
  :: Add the first value to sorted.
  set sorted=%sorted% %1
  shift /1
  goto :sort
)
:: Out of order.
:: Reverse them and recursively resort.
set redo=%sorted% %2 %1
set sorted=
shift /1
shift /1
:loop
if "%1"=="" goto :endloop
set redo=%redo% %1
shift /1
goto :loop
:endloop
call :sort %redo%
:: When we get here, we'll have already echod our result.
goto :eof

:finalset
echo Final Sort:  %sorted%
goto :eof

Beispiel:

C:\Path> sort 19 zebra blah 1 interesting 21 bleh 14 think 2 ninety figure it out

erzeugt:

Sorting:  19 zebra blah 1 interesting 21 bleh 14 think 2 ninety figure it out
Final Sort:   1 2 14 19 21 blah bleh figure interesting it ninety out think zebra
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top