In letzter Zeit ist wettbewerbsfähiges Programmieren bei studentischen Programmierern und aktiven Programmierern populär geworden (Erfahrung). Ich nehme nicht an Wettbewerben teil, aber ich löse häufig Probleme mit Wettbewerben als Testaufnahme, wenn ich eine neue Sprache lerne. Es ist ziemlich interessant.
Das Problem ist normalerweise, dass ** eine Beispieleingabe bereitgestellt wird, aber ist es nicht mühsam **, sie als Standard einzugeben? Ich möchte es wenn möglich automatisieren. ** Wenn Sie es automatisieren, können Sie effizienteres Ausprobieren und eine höhere Punktzahl erwarten **! Es gibt viele Möglichkeiten, dies zu automatisieren. In diesem Artikel wird jedoch gezeigt, wie Sie den Befehl make verwenden. Makefile ist für C ++, Java, Python als Beispiel. Wenn Sie Beispiele für Kompilierungssprachen, Java-basierte Sprachen und Skriptsprachen bereitstellen, schreibt der Benutzer diese entsprechend der Sprache neu. Da ist eine Seele.
Das Makefile und die Verzeichnisstruktur dieses Artikels wurden auf github hochgeladen. Bitte verwenden, wenn es gut ist. https://github.com/aoi-stoic/AtcorderTemplate
OS
$ cat /etc/os-release | head -n 2
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
Ich benutze Ubuntu. Andere Betriebssysteme und Distributionen werden weggelassen. Bitte lesen Sie sie entsprechend.
C++
gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)
Java
$ echo `javac -version` `java -version`
javac 1.8.0_265
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-8u265-b01-0ubuntu2~20.04-b01)
OpenJDK 64-Bit Server VM (build 25.265-b01, mixed mode)
Java ist geeignet, weil ich es kaum geschrieben habe. Wenn Sie den Wettbewerb mit Java herausfordern, wählen Sie bitte die Version, die zum Wettbewerb passt.
Python3
$ python3 --version
Python 3.8.2
Dinge, die nicht verwendet werden, wie z. B. die virtuelle Umgebung
Pseudowettbewerb ABCXXX Ein Problem "Vier Standardeingaben empfangen und die Summe als Standard ausgeben" wird als Thema verwendet, um eine Arbeitsverzeichniskonstruktion darzustellen und ein Beispiel für die Befehlsausführung zu erstellen. Löse in C ++.
Ein Problem-Eingabebeispiel und ein Ausgabebeispiel sind wie folgt ** Eingabebeispiel 1 ** 1 1 1 1 ** Ausgabebeispiel 1 ** 4
** Eingabebeispiel 2 ** 1 2 3 4 ** Ausgabebeispiel 2 ** 10
** Eingabebeispiel 3 ** 1000 100 10 1 ** Ausgabebeispiel 3 ** 1111
Befehl make installieren
sudo apt isntall make
Arbeitsverzeichnis erstellen
#Arbeitsverzeichnis erstellen und verschieben
mkdir ABCXXX && cd ABCXXX
#Klon des Vorlagenverzeichnisses (--depth=Klon mit 1 für minimale Historie)
git clone --depth=1 https://github.com/aoi-stoic/AtcorderTemplate.git
#Atcorder-Vorlage für ein Problem/Kopiervorlage Cpp&Bewegung
cp AtcorderTemplate/TemplateCpp/ problemA -r && cd problemA
Zu diesem Zeitpunkt sieht der Inhalt des problemmA-Verzeichnisses folgendermaßen aus Wenn Sie diese Konfiguration reproduzieren möchten, können Sie sie manuell erstellen, ohne von git zu klonen, und nur Makefile aus diesem Artikel kopieren.
$ tree
.
├── main.cpp #Quelldatei zur Antwort
├── Makefile # C++Für Makefile
└── Testfiles #Dateiverzeichnis testen
├── test1.test #Testdatei des Eingabebeispiels 1
├── test2.test
├── test3.test
└── test4.test
Kopieren Sie das Eingabebeispiel in jede Testdatei. Das Ergebnis ist: Da es nur 1 bis 3 Eingabebeispiele für das ABCXXX A-Problem gibt, ist test4.test eine leere Datei.
$ cat Testfiles/test1.test
1 1
1 1
$ cat Testfiles/test2.test
1 2
3 4
$ cat Testfiles/test3.test
1000 100
10 1
$ cat Testfiles/test4.test
Wie üblich habe ich den Antwortcode in main.cpp geschrieben.
// main.cpp
#include <iostream>
int main(){
int a, b, c, d;
std::cin >> a >> b >> c >> d;
std::cout << a + b + c + d << std::endl;
}
Wenn Sie den Befehl make im Verzeichnis problemA ausführen, Nach dem Kompilieren wird es automatisch für jedes Eingabebeispiel ausgeführt. Da test4.test leer ist, wird Eingabebeispiel 4 nicht ausgeführt.
$ make
g++ -std=c++11 -Wall main.cpp -o main.out
----------------------
exec Testfiles/test1.test
input:
1 1
1 1
output:
4
----------------------
exec Testfiles/test2.test
input:
1 2
3 4
output:
10
----------------------
exec Testfiles/test3.test
input:
1000 100
10 1
output:
1111
Stellen Sie sicher, dass die Entsprechung zwischen den Eingabe- und Ausgabebeispielen korrekt ist, und senden Sie sie, wenn Sie sicher sind, dass der Code korrekt ist. Wenn Sie mit dem nächsten B-Problem fortfahren möchten, kopieren Sie das TemplateCpp-Verzeichnis, um problemB zu erstellen, und arbeiten Sie auch in diesem Verzeichnis.
Die folgenden Ziele sind für das diesmal veröffentlichte Makefile vorbereitet. Da Python keine Kompilierungsarbeit hat, hat es keine Ziele wie Build und Clean.
Ziel | Befehl | Überblick |
---|---|---|
(Keiner) | make | Führen Sie make test aus |
build | make build | Nur kompilieren |
run | make run | Kompilieren und nach Bedarf ausführen. Die Standardeingabe erfolgt manuell. |
test | make test | Kompilieren und nach Bedarf ausführen. Geben Sie standardmäßig den Inhalt der Testdatei ein. |
clean | make clean | Löschen Sie das kompilierte Produkt. |
clean_test | make clean_test | Leeren Sie den Inhalt der Testdatei. Es wird verwendet, wenn das Verzeichnis von Frage A kopiert und für die Antwort auf Frage B wiederverwendet wird. |
Makefile
COMP = g++ -std=c++11 -Wall
SRC = main.cpp
BIN = main.out
TESTDIR = Testfiles
#Deaktivieren Sie implizite Regeln,Deaktivieren Sie die Ausgabe beim Verschieben von Verzeichnissen
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory
#Zieltest ohne Argumentausführung (Zielausführung)
all: test
$(BIN): $(SRC)
$(COMP) $(SRC) -o $(BIN)
#make run ist eine manuelle Ausführung der Standardeingabe
.phony:run
run: $(BIN)
./$(BIN)
# make test
#Ausführen, um den Inhalt der Testdatei standardmäßig in TESTDIR einzugeben (leere Dateien ignorieren)
.phony:test
test: $(BIN)
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
if [ -s $$testfile ]; then \
echo ---------------------- ;\
echo "exec $$testfile " ;\
echo "input: "; \
cat $$testfile ; \
echo "" ;\
echo "output: " ;\
cat $$testfile | ./$(BIN) ;\
fi \
done
.phony:clean
clean:
-rm $(BIN)
#Leeren Sie alle Testdateien
.phony:clean_test
clean_test:
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
: > $$testfile ;\
done
Ich habe kaum Java geschrieben.
COMP = javac
EXEC = java
SRC = Main.java
CLASS = Main.class
# Main.class -> Main
APP = $(basename $(CLASS) .class)
TESTDIR = Testfiles
#Deaktivieren Sie implizite Regeln,Deaktivieren Sie die Ausgabe beim Verschieben von Verzeichnissen
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory
#
#Zieltest ohne Argumentausführung (Zielausführung)
all: test
$(CLASS): $(SRC)
$(COMP) $(SRC)
#make run ist eine manuelle Ausführung der Standardeingabe
run: $(CLASS)
$(EXEC) $(APP)
# make test
#Ausführen, um den Inhalt der Testdatei standardmäßig in TESTDIR einzugeben (leere Dateien ignorieren)
test: $(CLASS)
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
if [ -s $$testfile ]; \
then \
echo ---------------------- ;\
echo "exec $$testfile" ;\
echo "input: " ; \
cat $$testfile ; \
echo "" ;\
echo "output: " ;\
cat $$testfile | $(EXEC) $(APP) ;\
fi \
done \
.phony:clean
clean:
-rm $(CLASS)
#Leeren Sie alle Testdateien
.phony:clean_test
clean_test:
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
: > $$testfile ;\
done
In Bezug auf Makefile erscheint die Skriptsprache Makefile seltsam.
SRC = main.py
EXEC = python3
TESTDIR = Testfiles
#Deaktivieren Sie implizite Regeln,Deaktivieren Sie die Ausgabe beim Verschieben von Verzeichnissen
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory
#Zieltest ohne Argumentausführung (Zielausführung)
all: test
#make run ist eine manuelle Ausführung der Standardeingabe
.phony:run
run:
$(EXEC) $(SRC)
# make test
#Ausführen, um den Inhalt der Testdatei standardmäßig in TESTDIR einzugeben (leere Dateien ignorieren)
.phony:test
test:
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
if [ -s $$testfile ]; then \
echo ---------------------- ;\
echo "exec $$testfile " ;\
echo "input: "; \
cat $$testfile ; \
echo "" ;\
echo "output: " ;\
cat $$testfile | $(EXEC) $(SRC) ;\
fi \
done
#Leeren Sie alle Testdateien
.phony:clean_test
clean_test:
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
: > $$testfile ;\
done
Mit der Pipeline (|) können Sie die Ausgabe eines Befehls mit der Eingabe des nächsten Befehls verbinden.
$ cat Testfiles/test1.test
1 1
1 1
$ cat Testfiles/test1.test | ./main.out #Geben Sie den Befehl cat aus./main.out input
4
Sie können damit die Standardeingabe einer ausführbaren Datei skripten.
make test
Nutzt diese Funktion.
Beim Erstellen einer neuen leeren Datei
touch empty_file
Das reicht, aber diese Methode funktioniert nicht für vorhandene Dateien. Die unten gezeigte Methode "Löschen und Berühren" ist nicht mein Hobby
rm empty_file & touch empty_file #Das passt nicht zu meinem Geschmack
Ich benutze oft die folgenden zwei Typen.
#Befehl, nichts zu tun(:)Leiten Sie das Ergebnis von um
: > empty_file
# /dev/cp null
cp /dev/null empty_file
Es scheint verschiedene andere Methoden zu geben.
genau. Wenn Sie jedoch Verknüpfungen für Ausführungsbefehle im Editor festlegen, ist es meiner Meinung nach besser, Verknüpfungen für den vielseitigeren Befehl make festzulegen, als Shell-Skripte auszuführen.
genau. Bitte entsprechend der Umgebung färben.
Einige Ubuntu-Distributionen verwenden Bindestrich anstelle von Bash, um Shell-Skripte auszuführen.
Es gibt einige Unterschiede im Verhalten einiger Befehle zwischen Bash und Dash.
In Bash können Sie beispielsweise einen Escape-Code verwenden, um die Ausgabe des Echos mit `echo -e" \ 033 [31m GRÜN \ 033 [m "`
zu färben, aber in Bindestrich benötigen Sie die Option -e nicht. Analysiert die Optionen nicht.
Ich habe die Echoausgabe dieses Mal nicht eingefärbt, da erwartet wurde, dass dieser Unterschied beim Veröffentlichen dieses Mal ein Problem darstellt.
Recommended Posts