Verwenden Sie make, um die Standardeingabe des veröffentlichten Makefile-Beispiel-Makefiles von Competition Pro (AtCorder) C ++ / Java / Python zu vereinfachen

Einführung

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

Angenommener Leser

Unerwartete Leser

Überprüfungsumgebung

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

Wie benutzt man

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

0. Vorbereitung

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

1. Kopieren Sie das Eingabebeispiel und fügen Sie es ein

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

2. Codierung

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;
}

3. Führen Sie den Befehl make aus

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

4. Einreichung oder Korrektur

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.

Ziel machen

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

Makefile für C ++

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

Makefile für Java

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

Makefile für Python

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

Beiseite

Pipeline

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.

So leeren Sie den Inhalt einer vorhandenen Datei

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.

Reicht ein Shell-Skript für diese Skala nicht aus?

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.

Ist es nicht einfacher zu sehen, ob Sie die Ausgabe des Echos färben?

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

Verwenden Sie make, um die Standardeingabe des veröffentlichten Makefile-Beispiel-Makefiles von Competition Pro (AtCorder) C ++ / Java / Python zu vereinfachen
[Java] Geben Sie in stdin of Process ein
Geschichte von paiza.jp [Java Standard Input Solution]
[Java] [Maven3] Zusammenfassung der Verwendung von Maven3