Difference between revisions of "Prova pratica 2014.07.17"
Jump to navigation
Jump to search
m (Aggiunte soluzioni da altre pagine, uniformato) |
|||
(6 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | == | + | ==Esercizio 1 == |
+ | <source lang="text"> | ||
+ | Scrivere un programma che per ogni file .c nella directory corrente chiami il compilatore gcc per generare il file oggetto (.o) a | ||
+ | meno che esista gia' nella directory un file oggetto relativo allo stesso sorgente che sia piu' nuovo (ultima modifica) del | ||
+ | sorgente. | ||
+ | Tutti I parametri devono essere passati al compilatore. | ||
+ | Es: | ||
+ | genobj -I . -ggdb | ||
+ | se nella directory corrente esistono I file uno.c e due.c e il file due.o deve richiamare | ||
+ | gcc -I. -ggdb -c uno.c | ||
+ | e, solo se due.o ha ultima modifica precedente a due.c, deve chiamare | ||
+ | gcc -I. -ggdb -c due.c | ||
+ | </source> | ||
+ | |||
+ | ===Soluzione di Davide Quadrelli=== | ||
+ | <source lang="c"> | ||
+ | #include <stdio.h> | ||
+ | #include <unistd.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <dirent.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <string.h> | ||
+ | |||
+ | #define MAX 256 | ||
+ | #define DIM_MAX 1000 | ||
+ | #define dim_last_data 4 | ||
+ | |||
+ | int main (int argc, char *argv[]){ | ||
+ | int i,len,com_size,bol=0; | ||
+ | struct stat o_data,f_data; | ||
+ | struct dirent *cur_file; | ||
+ | char name[MAX]; | ||
+ | char prefix[DIM_MAX]="gcc "; | ||
+ | char *comm; | ||
+ | FILE *o; | ||
+ | FILE *obj=NULL; | ||
+ | DIR *dir=opendir("./"); | ||
+ | /*store in prefix the common part of every command to launch*/ | ||
+ | for (i=1;i<argc;i++){ | ||
+ | strcat(prefix,argv[i]); | ||
+ | strcat(prefix," "); | ||
+ | } | ||
+ | com_size=strlen(prefix); | ||
+ | /*search in the current directory C files*/ | ||
+ | while(cur_file=readdir(dir)){ | ||
+ | if(cur_file->d_type==DT_REG){ | ||
+ | /*it's a file*/ | ||
+ | bol=0; | ||
+ | strcpy(name,cur_file->d_name); | ||
+ | printf("file found: %s ",name); | ||
+ | len=strlen(name); | ||
+ | if(strcmp(&(name[len-2]),".c")==0){ | ||
+ | /*C file found*/ | ||
+ | printf("... source code found ..."); | ||
+ | /*check if the file has already an uptaded object file*/ | ||
+ | name[len-1]='o'; | ||
+ | if ((o=fopen(name,"r"))==NULL){ | ||
+ | /*the corrispondent object file doesn't exists*/ | ||
+ | bol=1; | ||
+ | name[len-1]='c'; | ||
+ | }else{ | ||
+ | fclose(o); | ||
+ | /*get the stat data of the object file*/ | ||
+ | if(stat(name,&o_data)){ | ||
+ | write(STDERR_FILENO,"ERRORE STAT",11); | ||
+ | exit(-1); | ||
+ | } | ||
+ | /*get the stat data of the C file*/ | ||
+ | name[len-1]='c'; | ||
+ | if(stat(name,&f_data)){ | ||
+ | write(STDERR_FILENO,"ERRORE STAT",11); | ||
+ | exit(-1); | ||
+ | } | ||
+ | /*check if the object file must be re-created*/ | ||
+ | if(o_data.st_mtime<f_data.st_mtime){ | ||
+ | bol=1; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if(bol){ | ||
+ | /*prepare and exec the command*/ | ||
+ | comm=(char *)malloc(com_size+len+dim_last_data); | ||
+ | strcpy(comm,prefix); | ||
+ | strcat(comm,"-c "); | ||
+ | strcat(comm,name); | ||
+ | system(comm); | ||
+ | printf("object file created.\n%s",comm); | ||
+ | } | ||
+ | printf("\n\n"); | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Nota del Prof: Nel testo dell'esercizio, in grassetto, c'e' scritto: '''Non usare system o popen o simili!'''. System e' una funzione non sicura. Se si vogliono comporre stringhe c'e' anche la asprintf (al posto di malloc+strcpy+strcat). Se si vuole usare la malloc si puo' usare la snprintf che' piu' comoda di tutte del strcpy/cat [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 16:09, 7 April 2015 (CEST) | ||
+ | |||
+ | ===Soluzione di Stefano Mazza=== | ||
+ | <source lang="c"> | ||
+ | #include <stdio.h> | ||
+ | #include <sys/stat.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <dirent.h> | ||
+ | #include <unistd.h> | ||
+ | #include <string.h> | ||
+ | #include "s2argv/s2argv.h" | ||
+ | |||
+ | /*funzione per sapere l'estensione del file: ritorna vero se quello considerato è un file .x (dove x è il carattere passato come input)*/ | ||
+ | int formato(const char *name, const char x){ | ||
+ | char *point = strrchr(name, '.'); //cerco l'ultima occorrenza del punto della stringa data (nel nome del file) | ||
+ | if (point==NULL || point==name) return 0; | ||
+ | else | ||
+ | { | ||
+ | point++; | ||
+ | if (x==(*point)) return 1; | ||
+ | else return 0; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /*funzione per modificare l'estensione del file di nome name.c*/ | ||
+ | char *modify_format(char *name, const char x){ | ||
+ | char *newname, *ext; | ||
+ | strcpy(newname, name); | ||
+ | ext = strrchr(newname, 'c'); | ||
+ | *ext = x; //cambio il formato con quello passato per parametro (nel nostro caso cambio .c con .o) | ||
+ | return newname; | ||
+ | } | ||
+ | |||
+ | int main(int argc, char *argv[]){ | ||
+ | if (argc!=4) | ||
+ | { | ||
+ | fprintf(stderr, "Usage: %s [-I] [directory] [-ggdb]", argv[0]); | ||
+ | exit(EXIT_FAILURE); | ||
+ | } | ||
+ | char *cmd = NULL; | ||
+ | int n, i; | ||
+ | struct stat info_c, info_o; | ||
+ | struct dirent **entry_list; | ||
+ | if( (n=scandir(argv[2], &entry_list, NULL, alphasort)) <0) | ||
+ | { | ||
+ | perror("Scandir: error while scanning directory\n"); | ||
+ | exit(1); | ||
+ | } | ||
+ | chdir(argv[2]); | ||
+ | for (i=0; i<n; i++) | ||
+ | { | ||
+ | stat(entry_list[i]->d_name, &info_c); | ||
+ | if( S_ISREG(info_c.st_mode) && formato(entry_list[i]->d_name, 'c')) | ||
+ | { //controllo se per ogni file .c esiste il relativo file .o | ||
+ | if ( access( modify_format(entry_list[i]->d_name, 'o'), F_OK) < 0 ) //caso non esiste ==> lo creo | ||
+ | { | ||
+ | printf("Non esiste il .o di %s\n", entry_list[i]->d_name); | ||
+ | asprintf(&cmd, "gcc %s %s %s -c %s", argv[1], argv[2], argv[3], entry_list[i]->d_name); | ||
+ | printf("%s\n", cmd); | ||
+ | system_noshell(cmd); | ||
+ | free(cmd); | ||
+ | cmd = NULL; | ||
+ | } | ||
+ | else //caso esiste | ||
+ | { | ||
+ | stat(modify_format(entry_list[i]->d_name, 'o'), &info_o); | ||
+ | if (info_c.st_mtime > info_o.st_mtime) //non è ancora stato aggiornato | ||
+ | { | ||
+ | printf("Esiste il .o di %s, ma da aggiornare\n", entry_list[i]->d_name); | ||
+ | unlink(modify_format(entry_list[i]->d_name, 'o')); //elimino il file per aggiornarlo(ne creo uno nuovo) | ||
+ | asprintf(&cmd, "gcc %s %s %s -c %s", argv[1], argv[2], argv[3], entry_list[i]->d_name); | ||
+ | printf("%s\n", cmd); | ||
+ | system_noshell(cmd); | ||
+ | free(cmd); | ||
+ | cmd = NULL; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | ==Esercizio 3== | ||
+ | <source lang="text"> | ||
Il comando che dovrete implementare come script shell o programma python e' mytx. | Il comando che dovrete implementare come script shell o programma python e' mytx. | ||
Tale comando elenca tutti i file di una directory. | Tale comando elenca tutti i file di una directory. | ||
Line 10: | Line 191: | ||
12 file1 | 12 file1 | ||
235 file di prova | 235 file di prova | ||
+ | </source> | ||
− | ==Soluzione di Krusty== | + | ===Soluzione di Krusty=== |
+ | <source lang="python"> | ||
import os, sys | import os, sys | ||
from stat import * | from stat import * | ||
Line 18: | Line 201: | ||
for f in os.listdir(sys.argv[1]): #scorre file nella directory | for f in os.listdir(sys.argv[1]): #scorre file nella directory | ||
− | path = os.path.join(sys.argv[1],f) | + | path = os.path.join(sys.argv[1],f) |
s = os.stat(path) | s = os.stat(path) | ||
if S_ISREG(s.st_mode): | if S_ISREG(s.st_mode): | ||
Line 26: | Line 209: | ||
out_file.write("\n") | out_file.write("\n") | ||
out_file.close() | out_file.close() | ||
+ | </source> | ||
+ | ===Soluzione di Stefano Zaniboni=== | ||
+ | <source lang="python"> | ||
+ | #!/bin/usr/env python3 | ||
+ | |||
+ | import sys | ||
+ | import os | ||
+ | |||
+ | def writeOnFile(fileToWrite, fileName): | ||
+ | with open(fileToWrite, "a") as afile: | ||
+ | course = fileName | ||
+ | of = os.path.getsize(fileName) | ||
+ | total = str(of)+' '+str(course) | ||
+ | afile.write(str(total)) | ||
+ | afile.write('\n') | ||
+ | afile.close() | ||
+ | return None | ||
+ | ########################################### | ||
+ | if __name__=="__main__": | ||
+ | myDir=sys.argv[1] | ||
+ | os.system("touch ddd.tx") | ||
+ | |||
+ | for root, dirname, filenames in os.walk(myDir): | ||
+ | for filename in filenames: | ||
+ | writeOnFile("ddd.tx", os.path.join(root,filename)) | ||
+ | if os.path.isfile(os.path.join(root, filename)): | ||
+ | writeOnFile("ddd2.tx", filename) | ||
+ | </source> | ||
+ | |||
+ | ===Soluzione di Davide Quadrelli=== | ||
+ | <source lang="bash"> | ||
+ | #!/bin/bash | ||
+ | #Interpreto la richiesta del testo come segue: | ||
+ | #implementare mytx ddd ddd.tx ove ddd è una directory, ddd.tx è un file | ||
+ | #mytx deve elencare i file della directory ddd scrivere nel file ddd.tx di output una riga per file contenente | ||
+ | #la lunghezza del file, uno spazio e il nome del file. ddd.tx deve terminare con una riga bianca. | ||
+ | |||
+ | if [[ -d $1 ]] ; then | ||
+ | ls $1 | ||
+ | old=`pwd` | ||
+ | cd $1 | ||
+ | files=`ls` | ||
+ | for var in $files ; do | ||
+ | if [[ -f $var ]]; then | ||
+ | wc -c ${var} 1>> ${old}/${2} | ||
+ | fi | ||
+ | done | ||
+ | echo >> ${old}/${2} | ||
+ | |||
+ | else | ||
+ | echo "inserire come primo parametro la directory e come secondo il file da scrivere" | ||
+ | fi | ||
+ | </source> |
Latest revision as of 09:13, 9 May 2017
Esercizio 1
Scrivere un programma che per ogni file .c nella directory corrente chiami il compilatore gcc per generare il file oggetto (.o) a
meno che esista gia' nella directory un file oggetto relativo allo stesso sorgente che sia piu' nuovo (ultima modifica) del
sorgente.
Tutti I parametri devono essere passati al compilatore.
Es:
genobj -I . -ggdb
se nella directory corrente esistono I file uno.c e due.c e il file due.o deve richiamare
gcc -I. -ggdb -c uno.c
e, solo se due.o ha ultima modifica precedente a due.c, deve chiamare
gcc -I. -ggdb -c due.c
Soluzione di Davide Quadrelli
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#define MAX 256
#define DIM_MAX 1000
#define dim_last_data 4
int main (int argc, char *argv[]){
int i,len,com_size,bol=0;
struct stat o_data,f_data;
struct dirent *cur_file;
char name[MAX];
char prefix[DIM_MAX]="gcc ";
char *comm;
FILE *o;
FILE *obj=NULL;
DIR *dir=opendir("./");
/*store in prefix the common part of every command to launch*/
for (i=1;i<argc;i++){
strcat(prefix,argv[i]);
strcat(prefix," ");
}
com_size=strlen(prefix);
/*search in the current directory C files*/
while(cur_file=readdir(dir)){
if(cur_file->d_type==DT_REG){
/*it's a file*/
bol=0;
strcpy(name,cur_file->d_name);
printf("file found: %s ",name);
len=strlen(name);
if(strcmp(&(name[len-2]),".c")==0){
/*C file found*/
printf("... source code found ...");
/*check if the file has already an uptaded object file*/
name[len-1]='o';
if ((o=fopen(name,"r"))==NULL){
/*the corrispondent object file doesn't exists*/
bol=1;
name[len-1]='c';
}else{
fclose(o);
/*get the stat data of the object file*/
if(stat(name,&o_data)){
write(STDERR_FILENO,"ERRORE STAT",11);
exit(-1);
}
/*get the stat data of the C file*/
name[len-1]='c';
if(stat(name,&f_data)){
write(STDERR_FILENO,"ERRORE STAT",11);
exit(-1);
}
/*check if the object file must be re-created*/
if(o_data.st_mtime<f_data.st_mtime){
bol=1;
}
}
}
if(bol){
/*prepare and exec the command*/
comm=(char *)malloc(com_size+len+dim_last_data);
strcpy(comm,prefix);
strcat(comm,"-c ");
strcat(comm,name);
system(comm);
printf("object file created.\n%s",comm);
}
printf("\n\n");
}
}
return 0;
}
Nota del Prof: Nel testo dell'esercizio, in grassetto, c'e' scritto: Non usare system o popen o simili!. System e' una funzione non sicura. Se si vogliono comporre stringhe c'e' anche la asprintf (al posto di malloc+strcpy+strcat). Se si vuole usare la malloc si puo' usare la snprintf che' piu' comoda di tutte del strcpy/cat Renzo (talk) 16:09, 7 April 2015 (CEST)
Soluzione di Stefano Mazza
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include "s2argv/s2argv.h"
/*funzione per sapere l'estensione del file: ritorna vero se quello considerato è un file .x (dove x è il carattere passato come input)*/
int formato(const char *name, const char x){
char *point = strrchr(name, '.'); //cerco l'ultima occorrenza del punto della stringa data (nel nome del file)
if (point==NULL || point==name) return 0;
else
{
point++;
if (x==(*point)) return 1;
else return 0;
}
}
/*funzione per modificare l'estensione del file di nome name.c*/
char *modify_format(char *name, const char x){
char *newname, *ext;
strcpy(newname, name);
ext = strrchr(newname, 'c');
*ext = x; //cambio il formato con quello passato per parametro (nel nostro caso cambio .c con .o)
return newname;
}
int main(int argc, char *argv[]){
if (argc!=4)
{
fprintf(stderr, "Usage: %s [-I] [directory] [-ggdb]", argv[0]);
exit(EXIT_FAILURE);
}
char *cmd = NULL;
int n, i;
struct stat info_c, info_o;
struct dirent **entry_list;
if( (n=scandir(argv[2], &entry_list, NULL, alphasort)) <0)
{
perror("Scandir: error while scanning directory\n");
exit(1);
}
chdir(argv[2]);
for (i=0; i<n; i++)
{
stat(entry_list[i]->d_name, &info_c);
if( S_ISREG(info_c.st_mode) && formato(entry_list[i]->d_name, 'c'))
{ //controllo se per ogni file .c esiste il relativo file .o
if ( access( modify_format(entry_list[i]->d_name, 'o'), F_OK) < 0 ) //caso non esiste ==> lo creo
{
printf("Non esiste il .o di %s\n", entry_list[i]->d_name);
asprintf(&cmd, "gcc %s %s %s -c %s", argv[1], argv[2], argv[3], entry_list[i]->d_name);
printf("%s\n", cmd);
system_noshell(cmd);
free(cmd);
cmd = NULL;
}
else //caso esiste
{
stat(modify_format(entry_list[i]->d_name, 'o'), &info_o);
if (info_c.st_mtime > info_o.st_mtime) //non è ancora stato aggiornato
{
printf("Esiste il .o di %s, ma da aggiornare\n", entry_list[i]->d_name);
unlink(modify_format(entry_list[i]->d_name, 'o')); //elimino il file per aggiornarlo(ne creo uno nuovo)
asprintf(&cmd, "gcc %s %s %s -c %s", argv[1], argv[2], argv[3], entry_list[i]->d_name);
printf("%s\n", cmd);
system_noshell(cmd);
free(cmd);
cmd = NULL;
}
}
}
}
return 0;
}
Esercizio 3
Il comando che dovrete implementare come script shell o programma python e' mytx.
Tale comando elenca tutti i file di una directory.
mytx ddd ddd.tx
Ogni riga del file di output (secondo parametro) deve contenere la lunghezza, uno spazio e il nume del file. Dopo l'ultima riga
deve inserire una riga bianca.
ddd.t2 deve contenere l'elenco dei file regolari. Il primo campo e' un numero intero seguito da uno spazio, tutto cio' che segue
fino alla fine riga e' il nome del file.
es.
12 file1
235 file di prova
Soluzione di Krusty
import os, sys
from stat import *
out_file = open(sys.argv[2],"w")
for f in os.listdir(sys.argv[1]): #scorre file nella directory
path = os.path.join(sys.argv[1],f)
s = os.stat(path)
if S_ISREG(s.st_mode):
info = str(os.path.getsize(path)) + ' ' + f #scrive dimensione e nome file in info
out_file.write(info + "\n")
out_file.write("\n")
out_file.close()
Soluzione di Stefano Zaniboni
#!/bin/usr/env python3
import sys
import os
def writeOnFile(fileToWrite, fileName):
with open(fileToWrite, "a") as afile:
course = fileName
of = os.path.getsize(fileName)
total = str(of)+' '+str(course)
afile.write(str(total))
afile.write('\n')
afile.close()
return None
###########################################
if __name__=="__main__":
myDir=sys.argv[1]
os.system("touch ddd.tx")
for root, dirname, filenames in os.walk(myDir):
for filename in filenames:
writeOnFile("ddd.tx", os.path.join(root,filename))
if os.path.isfile(os.path.join(root, filename)):
writeOnFile("ddd2.tx", filename)
Soluzione di Davide Quadrelli
#!/bin/bash
#Interpreto la richiesta del testo come segue:
#implementare mytx ddd ddd.tx ove ddd è una directory, ddd.tx è un file
#mytx deve elencare i file della directory ddd scrivere nel file ddd.tx di output una riga per file contenente
#la lunghezza del file, uno spazio e il nome del file. ddd.tx deve terminare con una riga bianca.
if [[ -d $1 ]] ; then
ls $1
old=`pwd`
cd $1
files=`ls`
for var in $files ; do
if [[ -f $var ]]; then
wc -c ${var} 1>> ${old}/${2}
fi
done
echo >> ${old}/${2}
else
echo "inserire come primo parametro la directory e come secondo il file da scrivere"
fi