Salve a tutti,
Non mi sono mai preoccupato di riprodurre in locale la stessa situazione delle OII. Ho sempre fatto due file di codice, uno contenente la funzione da mandare e l’altro che si occupa dell’input/output che non fa altro che includere il file con la funzione.
Vero, tuttavia fate conto che agli stage di allenamento (dopo le OII) ci si aspetta che gli studenti selezionati sappiano utilizzare i grader autonomamente (quindi non è detto che vengano forniti script/progetti/makefile).Non c'è nulla da esercitare dato che alle OII sarà già tutto preparatoLawliet
Supponendo che tu utilizzi C o C++, l'idea è che devi lavorare con due file anziché uno, e uno di questo due (il grader) non lo devi (o meglio "non lo dovresti") modificare.chi mi spiega bene come si eseguono in locale grader e funzione creata per fare i test? come si richiama quest'ultima?gianpiero96
int somma(int, int);
int main() {
// lettura da file di a, b
// chiamata di somma(a, b) e scrittura del risultato su file
return 0;
}
int somma(int x, int y) {
return x + y;
}
Per capire come si fa a compilare "insieme" due file che si riferiscono a vicenda (come in questo caso) devi sapere che il processo che spesso viene semplicemente chiamato "compilazione" in realtà è suddiviso in due fasi distinte che avvengono una dopo l'altra: (1) compilazione, (2) linking.
Assumiamo che per compilare un file utilizziamo questo comando (che produce di default, se tutto va a buon fine, un eseguibile a.out)
gcc nome_file.c
Questo comando in realtà prima compila nome_file.c in un file oggetto con estensione .o, e infine linka questo file oggetto creando un eseguibile.
Chiaramente, se provi a compilare con quel comando uno solo dei due file di cui abbiamo parlato prima, riceverai un errore nella fase di linking:
- linkando il file oggetto ottenuto dalla compilazione di grader.c, ci sarà un errore che dice che il riferimento a "somma" non è definito.
- linkando il file oggetto ottenuto dalla compilazione di tuasoluzione.c, ci sarà un errore che dice che manca il riferimento alla main().
Un modo per "risolvere" il problema è quello di compilare entrambi i file, per poi eseguire la fase di linking su entrambi i file oggetto (con estensione .o) che sono stati creati. Ovvero:
gcc nome_file1.c nome_file2.c
In questo modo la fase di linking andrà a buon fine (dato che tutti i riferimenti ci sono) e verrà prodotto l'eseguibile a.out (per specificargli un altro nome, si può usare come sempre il flag -o di gcc).
tl;dr
Un modo è questo:
1) Crea per ogni problema una cartella apposita, in ogni cartella crea uno script bash chiamato "compila.sh" con dentro:
#!/bin/bash
gcc -o tuoeseguibile grader.c tuasoluzione.c
2) Fai tasto destro sul file, vai sulle proprietà e impostalo come eseguibile (assumo che si stia usando Ubuntu).
3) Configura il tuo IDE in modo da mappare una combinazione di tasti a "esegui compila.sh".
4) Configura il tuo IDE in modo da mappare un'altra combinazione di tasti a "esegui tuoeseguibile".
O più semplicemente si puó modificare la riga di compilazione dell’IDE aggiungendo “grader.cpp” alla riga usata dall’IDE, molto rapido con software come geany per esempio.
C'è un modo di "automatizzare" tutto questo in codeblocks, magari usando i progetti?Supponendo che tu utilizzi C o C++, l'idea è che devi lavorare con due file anziché uno, e uno di questo due (il grader) non lo devi (o meglio "non lo dovresti") modificare.chi mi spiega bene come si eseguono in locale grader e funzione creata per fare i test? come si richiama quest'ultima?gianpiero96
Per esempio, se un problema ti chiede di implementare una funzione "somma", avrai una situazione di questo tipo:grader.c (ha la funzione main e dichiara un prototipo della funzione che devi implementare)int somma(int, int);
int main() {
// lettura da file di a, b
// chiamata di somma(a, b) e scrittura del risultato su file
return 0;
}tuasoluzione.c (contiene un'implementazione compatibile col prototipo dichiarato nel grader)int somma(int x, int y) {
return x + y;
}Per capire come si fa a compilare "insieme" due file che si riferiscono a vicenda (come in questo caso) devi sapere che il processo che spesso viene semplicemente chiamato "compilazione" in realtà è suddiviso in due fasi distinte che avvengono una dopo l'altra: (1) compilazione, (2) linking.
Assumiamo che per compilare un file utilizziamo questo comando (che produce di default, se tutto va a buon fine, un eseguibile a.out)
gcc nome_file.cQuesto comando in realtà prima compila nome_file.c in un file oggetto con estensione .o, e infine linka questo file oggetto creando un eseguibile.
Chiaramente, se provi a compilare con quel comando uno solo dei due file di cui abbiamo parlato prima, riceverai un errore nella fase di linking:
- linkando il file oggetto ottenuto dalla compilazione di grader.c, ci sarà un errore che dice che il riferimento a "somma" non è definito.
- linkando il file oggetto ottenuto dalla compilazione di tuasoluzione.c, ci sarà un errore che dice che manca il riferimento alla main().
Un modo per "risolvere" il problema è quello di compilare entrambi i file, per poi eseguire la fase di linking su entrambi i file oggetto (con estensione .o) che sono stati creati. Ovvero:
gcc nome_file1.c nome_file2.cIn questo modo la fase di linking andrà a buon fine (dato che tutti i riferimenti ci sono) e verrà prodotto l'eseguibile a.out (per specificargli un altro nome, si può usare come sempre il flag -o di gcc).
tl;dr
Un modo è questo:
1) Crea per ogni problema una cartella apposita, in ogni cartella crea uno script bash chiamato "compila.sh" con dentro:
#!/bin/bash
gcc -o tuoeseguibile grader.c tuasoluzione.c2) Fai tasto destro sul file, vai sulle proprietà e impostalo come eseguibile (assumo che si stia usando Ubuntu).
3) Configura il tuo IDE in modo da mappare una combinazione di tasti a "esegui compila.sh".
4) Configura il tuo IDE in modo da mappare un'altra combinazione di tasti a "esegui tuoeseguibile".
wil93
C'è un modo di "automatizzare" tutto questo in codeblocks, magari usando i progetti?Sì, basta creare un progetto ed aggiungerci entrambi i file :)mark03
Alle ultime OII infatti i contestant avevano nelle proprie home (o forse nelle scrivanie?) una cartella per ogni task, e dentro ognuna di queste c'erano altre cartelle: "codeblocks" (con un progetto), "geany" (con un Makefile, credo), "altro" (con un compila.sh).
-wil93
Grazie per le spiegazioni. Comunque da quel che ho capito al correttore va inviato soltanto il mio_file.cpp/.c contenente la funzione risolutiva, giusto? Quindi, anche per motivi di tempo, non converrebbe modificare il grader magari includendo il file con la mia funzione come se fosse una libreria?
Es. #include<C:…\mio_file.cpp>
non converrebbe modificare il grader magari includendo il file con la mia funzione come se fosse una libreria?gianpiero96
#include "percorso/miofile.cpp"
(con "" invece di <>, per i file locali).
Beh, questo è un altro modo, tuttavia secondo me non dà molti vantaggi dato che ogni volta devi compilare ed eseguire il grader (mentre modifichi un altro file) quindi dovresti comunque perdere tempo a configurare l'IDE (o chi per lui) in modo da fare la cosa giusta.#ifndef EVAL
#include "grader.cpp"
#endif
questa mi sembra l'alternativa più "trasparente", ovvero lavori (compilazione, esecuzione) su un solo file come al solito. Però dipende dal correttore: se un giorno si decide che il correttore non definisce più EVAL? in tal caso ti ritroveresti a dover cambiare l'ifndef in un ifdef e a dover definire EVAL (o TEST_LOCALE, o quel che vuoi) andando a cambiare la riga di comando che usi per compilare.
Ho provato a risolvere qualche problema con grader degli ultimi inseriti per provarne il funzionamento ma in tutti i casi questo non funziona. pare che il programma di blocchi al momento dell’input ossia all’ultima riga del seguente stralcio:
int main(){
FILE *fin, *fout;
int i,j;
#ifdef EVAL
assert(fin = fopen(“input.txt”, “r”));
assert(fout = fopen(“output.txt”, “w”));
#else
fin = stdin;
fout = stdout;
#endif
fscanf(fin, “%d”, &N);
è un problema di librerie o sbaglio qualche cosa io?
Si blocca perché aspetta di leggere i dati da tastiera (quando viene sottoposto invece lavora su file).
int main(){
FILE *fin, *fout;
int i,j;
assert(fin = fopen(“input.txt”, “r”));
assert(fout = fopen(“output.txt”, “w”));
fscanf(fin, “%d”, &N);
P.S. ho modificato i grader allegati che avevano #ifdef EVAL (petali e sponsor), ora dovrebbero leggere di default da file.
Perfetto, effettivamente queste erano funzioni che non conoscevo, non mi ero accorto dell’input da tastiera, Grazie!