• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Jak używać testów do programów w c++ (.in/.out)

Cloud VPS
+2 głosów
717 wizyt
pytanie zadane 5 stycznia 2022 w C i C++ przez Dobdo Użytkownik (570 p.)
Cześć.

Czasami do programów (najczęściej tych konkursowych) tworzy się dedykowane pliki .in i .out, które zawierają dane wejściowe i poprawne wyjściowe. Posiadam akurat takie testy do pewnego algorytmu, który napisałem w C++. Czy istnieje jakiś łatwy i szybki sposób by te wszystkie dane z pliku .in wstawić do cin'ów w programie, które normalnie te dane biorą przez ręczne wpisanie do konsoli czy raczej trzeba bawić się w wczytywanie danych z pliku .in?

3 odpowiedzi

+3 głosów
odpowiedź 5 stycznia 2022 przez adrian17 Mentor (354,720 p.)
wybrane 6 stycznia 2022 przez Dobdo
 
Najlepsza

`cin` to standardowe wejście - ale to nie musi znaczyć "wpisane ręcznie w konsoli".

Jak w konsoli odpalisz

moj_program < wejscie.in

To zawartość pliku będzie potraktowana, jakby została wpisana na wejście. Zadziała to na każdym systemie.

Podobnie, dodając

> wyjscie.out

Wyjście zostanie zapisane do pliku, a nie wyświetlone na konsolę.

komentarz 5 stycznia 2022 przez Dobdo Użytkownik (570 p.)
Nie wiem czy dobrze rozumiem. W folderze, w którym mam plik exe umieszczam plik z testem np. "test.in" i potem odpalam cmd/poweshella ze ścieżką do foldera z tym i wpisuję w nim: "nazwa_programu.exe < test.in"? Obecnie powoduje to błąd. W którym miejscu powinienem to wpisać?
komentarz 5 stycznia 2022 przez adrian17 Mentor (354,720 p.)

Obecnie powoduje to błąd.

To nic nikomu nigdy nie mówi, musisz zawsze pisać jaki błąd.

komentarz 5 stycznia 2022 przez Dobdo Użytkownik (570 p.)
C:\---------------\Debug> program.exe < test1.in
At line:1 char:11
+ program.exe < test1.in
+           ~
The '<' operator is reserved for future use.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : RedirectionNotSupported

 

komentarz 5 stycznia 2022 przez adrian17 Mentor (354,720 p.)
+1 głos
odpowiedź 5 stycznia 2022 przez Whistleroosh Maniak (57,400 p.)
edycja 5 stycznia 2022 przez Whistleroosh

Ja zawsze piszę sobie skrypt w bashu w którym robie przekierowanie strumienia wejściowego i wyjściowego, a następnie wczytuje wszystkie .in i porównuje wynik programu z odpowiednimi .out Nie wiem czy da się prościej. Tak wygląda ten skrypt:

#!/bin/bash

touch result.txt

for entry in "./in"/*
do
    prefix="./in/"
    sufix=".in"

    name=${entry#"$prefix"}
    name=${name%"$sufix"}
    
    file1="./in/${name}.in"
    file2="./out/${name}.out"

    echo $name
    ./main < $file1 > result.txt
       
    difference=$(diff -Z "result.txt" "$file2")
    if [ "$difference" != "" ]
    then
        echo "BAD"
        break
    else
        echo "GOOD"
    fi
done

Wszystkie pliki .in muszą być w folderze in, a wszystkie pliki .out muszą być w folderze out

 

0 głosów
odpowiedź 5 stycznia 2022 przez toko Dyskutant (8,030 p.)
edycja 5 stycznia 2022 przez toko

Nie znam niczego co by tak robiło, oprócz pisanych ręcznie bibliotek i programów. Ja używam swojego krótkiego programu (nie radzę używać przy dużym outpucie, bo wtedy trochę muli):

#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
bool isWhiteSpace(char c) {
	return (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == '\f');
}
bool isNumber(string str) {
	return !str.empty() && str.find_first_not_of("0123456789") == string::npos;
}
std::string itos(int value, int min_length = 1) {
        std::string result = std::to_string(value);
        reverse(result.begin(), result.end());
        while(result.size() < min_length) {
                result += "0";
        }
        reverse(result.begin(), result.end());
        return result;
}
int main(int argc, char* argv[])
{
	string program;
	string testspath = ".";
	string path = ".";
	int ile = 0;
	bool p = false;
	bool o = false;
	bool e = false;
	for(int i = 1; i < argc; i++) {
		if(string(argv[i]) == "-p")
			p = true;
		else if(string(argv[i]) == "-o")
			o = true;
		else if(string(argv[i]) == "-e")
			e = true;
		else if(string(argv[i]) == "-t" && i+1 < argc)
			testspath = argv[++i];
		else if(string(argv[i]) == "-d" && i+1 < argc)
			path = argv[++i];
		else if(isNumber(argv[i]))
			ile = atoi(argv[i]);
		else
			program = argv[i];
	}
	cout << "tester" << (p?" -p":"") << (e?" -e":"") << (o?" -o":"") << " -t "+testspath << " -d "+path << " " << ile << " "+program << endl;
	for(int i = 1; i <= ile && program.size(); i++) {
		string ii = itos(i /*, itos(ile).size()*/);
		system((program+" < "+testspath+"/in/test"+ii+".in > "+path+"/test"+ii+".out 2> "+path+"/test"+ii+".err").c_str());
		fstream file0(testspath+"/in/test"+ii+".in", ios::in);
		fstream file1(testspath+"/out/test"+ii+".out", ios::in);
		fstream file2(path+"/test"+ii+".out", ios::in);
		fstream file3(path+"/test"+ii+".err", ios::in);
		if(file0.good() && file1.good() && file2.good() && file3.good()) {
			string sp((istreambuf_iterator<char>(file0)), (istreambuf_iterator<char>()));
			string so1((istreambuf_iterator<char>(file1)), (istreambuf_iterator<char>()));
			string so2((istreambuf_iterator<char>(file2)), (istreambuf_iterator<char>()));
			string se((istreambuf_iterator<char>(file3)), (istreambuf_iterator<char>()));
			string po1 = so1;
			string po2 = so2;
			po1.erase(remove_if(po1.begin(), po1.end(), isWhiteSpace), po1.end());
			po2.erase(remove_if(po2.begin(), po2.end(), isWhiteSpace), po2.end());
			if(po1 == po2)
				cout << "\033[32m"+ii+": OK\033[39m\n";
			else
				cout << "\033[31m"+ii+": ZLE\033[39m\n";
			if(p) {
				cout << "Pytanie:\n" << sp << "\n";
			}
			if(o) {
				cout << "Poprawna odpowiedź:\n" << so1 << "\n";
				cout << "Odpowiedź:\n" << so2 << "\n";
			}
			if(e) {
				cout << "Błędy:\n" << se << "\n";
			}
		} else {
			cout << "\033[31m"+ii+": Nie można otworzyć plików!\033[39m\n";
		}
	}
}

argumenty:

  • ścieżka do programu (w takiej formie jak podajesz w konsoli przy uruchamianiu) (w przypadku niepodania program nic nie zrobi) (default "")
  • ilość testów (w przypadku niepodania program nic nie zrobi) (default 0)

opcjonalne argumenty:

  • -p - włącza wypisywanie pliku .in (default false)
  • -o - włącza wypisywanie pliku .out i odpowiedzi programu (default false)
  • -e - włącza wypisywanie błędów (standardowego wyjścia błędów) programu (dafault false)
  • -t "ścieżka do folderu z testami" - testy będą brane z lokalizacji "ścieżka do folderu z testami" (dafault ".")
  • -d "ścieżka do folderu z outputem programu na wszystkich testach" - odpowiedzi programu będą zapisywane w lokalizacji "ścieżka do folderu..." (default ".")

 testy numerowane od 1 do ilości testów, (test1.in, test2.in, test3.in ... test[ilość testów].in)

po odkomentowaniu pierwszej linii w forze, testy powinny wyglądać tak (zawsze numer tej samej długości):

test01.in, test02.in, test03.in, test04.in ... test15.in, test16.in

ułożone są wtedy w dobrej kolejności w przeglądarce plików.

Ponadto pliki wyjścia programu są zapisane w "[ścieżka do folderu z outputem...]/test[numer testu].[in i err]"

Przykładowe użycie: ./tester ./program -p -o -e -t testy -d odpowiedzi 50

PS. Zapomniałem dodać, że pliki .out powinny być w katalogu out a pliki .in w katalogu in.

Podobne pytania

0 głosów
0 odpowiedzi 124 wizyt
pytanie zadane 14 grudnia 2018 w C# przez marcin99b Szeryf (84,470 p.)
0 głosów
0 odpowiedzi 247 wizyt
+4 głosów
0 odpowiedzi 369 wizyt
pytanie zadane 17 lutego 2020 w Nasze projekty przez MysticRPG Nowicjusz (160 p.)

93,488 zapytań

142,421 odpowiedzi

322,772 komentarzy

62,906 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...