Nuova piccola applicazione

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Nuova piccola applicazione

Messaggio da j0kers »

Ok 8)

Avatar utente
Blallo
Packager
Packager
Messaggi: 3302
Iscritto il: ven 12 ott 2007, 11:37
Nome Cognome: Savino Liguori
Slackware: 14.2 / 12.2
Kernel: 4.4.14-smp
Desktop: DWM
Località: Torino / Torremaggiore (FG)
Contatta:

Re: Nuova piccola applicazione

Messaggio da Blallo »

la soluzione che ti ha dato spina è un esempio
semplicemente al posto dei char "statici" puoi dargli in pasto un file di testo, semplicemente

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Nuova piccola applicazione

Messaggio da j0kers »

Certo però si aggiunge comunque altro codice e altre variabili.
comunque ci sono milioni di soluzioni per giungere alla medesima soluzione.
Dipende poi dal programmatore

Avatar utente
Blallo
Packager
Packager
Messaggi: 3302
Iscritto il: ven 12 ott 2007, 11:37
Nome Cognome: Savino Liguori
Slackware: 14.2 / 12.2
Kernel: 4.4.14-smp
Desktop: DWM
Località: Torino / Torremaggiore (FG)
Contatta:

Re: Nuova piccola applicazione

Messaggio da Blallo »

j0kers ha scritto:Certo però si aggiunge comunque altro codice e altre variabili.
comunque ci sono milioni di soluzioni per giungere alla medesima soluzione.
Dipende poi dal programmatore
e allora?
meglio "tanto" codice (che così tanto non è, fidati) e compili una volta sola o modificare e ricompilare ogni volta?
è più una questione di atteggiamento
se ora fai così, se fai robe più grosse, non credo ti converrà tanto modificare e ricompilare ogni volta
oltre a far divenire il programma un "obbrobrio"

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Nuova piccola applicazione

Messaggio da j0kers »

Yep :D

Mario Vanoni
Iper Master
Iper Master
Messaggi: 3174
Iscritto il: lun 3 set 2007, 21:20
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey
Località: Cuasso al Monte (VA)

Re: Nuova piccola applicazione

Messaggio da Mario Vanoni »

j0kers ha scritto:Oppure

Codice: Seleziona tutto

if( (fp=fopen("proc","r"))==NULL)
      exit(fprintf(stderr, "Errore apertura file!\n"));
Giusto ?
Ancora piu` short:

Codice: Seleziona tutto

if(! (fp = fopen("proc","r")))
      exit(fprintf(stderr, "Errore apertura file!\n"));
Come dice giustamente Emanuele,
gli exit code possono servire per individuare il posto del fallimento,
con un programma semplice pero` basta zero o non zero,
soprattutto se il messaggio d'errore e` molto chiaro!

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Nuova piccola applicazione

Messaggio da targzeta »

Mario Vanoni ha scritto:...gli exit code possono servire per individuare il posto del fallimento,
con un programma semplice pero` basta zero o non zero,
soprattutto se il messaggio d'errore e` molto chiaro!
Beh questo non è proprio vero, il codice di errore generalmente non serve all'utente ma ad un comando che deve comportarsi in un modo piuttosto che in un altro a seconda di questo codice. Per l'utente il software potrebbe anche terminare con 'return 0' se prima gli dice che tipo di errore è avvenuto, tanto per lui è chiaro cos'è successo. Però l'stderr può comunque essere ridiretto verso /dev/null e controllare solo il codice di ritorno. Un esempio tra tutti è lo script di avvio della Slackware (rc.S):

Codice: Seleziona tutto

...
  if [ ! -r /etc/fastboot ]; then
    /sbin/fsck $FORCEFSCK -C -a /
    RETVAL=$?
  fi
  if [ $RETVAL -ge 2 ]; then
    if [ $RETVAL -ge 4 ]; then
      echo "*** An error occurred during the root filesystem check. ***"
      ...
    else # With an error code of 2 or 3, reboot the machine automatically:
...
Allo script non interessa minimamente l'output del comando fsck ma gli interessa invece il codice di ritorno per capire se è andato tutto bene o cosa è successo in dettaglio.

Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
gallows
Staff
Staff
Messaggi: 3470
Iscritto il: lun 20 set 2004, 0:00
Slackware: 64-current
Kernel: 5.10.7
Località: ~/
Contatta:

Re: Nuova piccola applicazione

Messaggio da gallows »

Mario Vanoni ha scritto:
j0kers ha scritto:Oppure

Codice: Seleziona tutto

if( (fp=fopen("proc","r"))==NULL)
      exit(fprintf(stderr, "Errore apertura file!\n"));
Giusto ?
Ancora piu` short:

Codice: Seleziona tutto

if(! (fp = fopen("proc","r")))
      exit(fprintf(stderr, "Errore apertura file!\n"));
Programs should be written for people to read, and only incidentally for machines to execute.

Anche se sono programmi giocattolo e - suppongo - i primi che scrivi cerca sempre di mantenere una certa disciplina. Avere l'abitudine di scrivere buon codice è importante. Quando avrai a che fare con programmi (comunque piccoli) da migliaia di righe di codice e devi sistemare qualcosa, leggere questi "trucchetti" risulterà piuttosto irritante!
(Per buon codice indendo anche valori di uscita decenti, se poi è un PoC usa assert()).

ps. dai un'occhiata a errno.h, perror() et similia o alle funzioni bsd in err.h

Avatar utente
masalapianta
Iper Master
Iper Master
Messaggi: 2775
Iscritto il: lun 25 lug 2005, 0:00
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian
Località: Roma
Contatta:

Re: Nuova piccola applicazione

Messaggio da masalapianta »

:fuori: :banghead: :banghead: :banghead: :pottytrain5:
a parte gli orrori che ti han gia fatto notare, in una manciata di righe di codice abbiamo, non uno, ma ben due overflow sullo stack, dipendenti dalla dimensione di argv[1] e di quello che c'è nel file "proc", se hai a che fare con stringhe di cui non conosci a priori la lunghezza valuta la possibilità di allocare dinamicamente con malloc e socie, oppure se vuoi porre a priori un limite assicurati di controllare quanta roba scrivi ed eventualmente gestisci l'eccezione (anzichè troncare la stringa e proseguire come nulla fosse); usi una variabile di appoggio "lettura_file" non si capisce per quale motivo (porcata per porcata a sto punto anzichè fare strncpy dal buffer della fgets a lettura_file e poi strcat da lettura_file a comando a sto punto fai direttamente strncat dal buffer della fgets a comando); evita i commenti con //, non sono ansi/c89; includi stdlib.h senza motivo.
Apro una parentesi sulla programmazione pseudo-sicura: non usate MAI roba come strcat e compagnia cantante se non avete la certezza che sia stato fatto un controllo a monte; per la manipolazione delle stringhe esistono alternative sicure come le strl* bsd, l'approccio bernsteiniano con alloc/stralloc, ecc..
Tornando a te, è evidente che stai cominciando a programmare senza alcun metodo, verosilmilmente hai letto qualche pagina di un tutorial e ti sei buttato a scriver codice senza aver prima acquisito le nozioni che quel codice richiede per essere scritto; con linguaggi ad alto livello (perl, php, ecc..), questo tipo di approccio, seppure porti a risultati mediocri, può essere intrapreso, con il C no; procurati un buon libro (consiglio Deitel&Deitel e K&R, il primo è più didattico ma molto dispersivo, il secondo è meno dispersivo ma meno didattico) e inizia a studiare, scrivi tanto codice, ma scrivilo di pari passo con la teoria studiata.

Riguardo il vanoniano exit, usando come codice d'uscita l'int tornato dalla fprintf, stendo un velo pietoso, per ottimi motivi esistono metodi standard (vedi post di gallows) per la gestione degli errori e per l'uso di particolari exit code in caso di errore.

metrofox
Linux 3.x
Linux 3.x
Messaggi: 760
Iscritto il: gio 7 ago 2008, 12:29
Slackware: slackware64-current
Kernel: 3.4.4-ck3
Desktop: FluxBox-1.3.1
Distribuzione: FreeBSD-8.1(amd64)
Località: London

Re: Nuova piccola applicazione

Messaggio da metrofox »

masalapianta ha scritto::fuori: :banghead: :banghead: :banghead: :pottytrain5:
a parte gli orrori che ti han gia fatto notare, in una manciata di righe di codice abbiamo, non uno, ma ben due overflow sullo stack, dipendenti dalla dimensione di argv[1] e di quello che c'è nel file "proc", se hai a che fare con stringhe di cui non conosci a priori la lunghezza valuta la possibilità di allocare dinamicamente con malloc e socie, oppure se vuoi porre a priori un limite assicurati di controllare quanta roba scrivi ed eventualmente gestisci l'eccezione (anzichè troncare la stringa e proseguire come nulla fosse); usi una variabile di appoggio "lettura_file" non si capisce per quale motivo (porcata per porcata a sto punto anzichè fare strncpy dal buffer della fgets a lettura_file e poi strcat da lettura_file a comando a sto punto fai direttamente strncat dal buffer della fgets a comando); evita i commenti con //, non sono ansi/c89; includi stdlib.h senza motivo.
Apro una parentesi sulla programmazione pseudo-sicura: non usate MAI roba come strcat e compagnia cantante se non avete la certezza che sia stato fatto un controllo a monte; per la manipolazione delle stringhe esistono alternative sicure come le strl* bsd, l'approccio bernsteiniano con alloc/stralloc, ecc..
Tornando a te, è evidente che stai cominciando a programmare senza alcun metodo, verosilmilmente hai letto qualche pagina di un tutorial e ti sei buttato a scriver codice senza aver prima acquisito le nozioni che quel codice richiede per essere scritto; con linguaggi ad alto livello (perl, php, ecc..), questo tipo di approccio, seppure porti a risultati mediocri, può essere intrapreso, con il C no; procurati un buon libro (consiglio Deitel&Deitel e K&R, il primo è più didattico ma molto dispersivo, il secondo è meno dispersivo ma meno didattico) e inizia a studiare, scrivi tanto codice, ma scrivilo di pari passo con la teoria studiata.

Riguardo il vanoniano exit, usando come codice d'uscita l'int tornato dalla fprintf, stendo un velo pietoso, per ottimi motivi esistono metodi standard (vedi post di gallows) per la gestione degli errori e per l'uso di particolari exit code in caso di errore.
stdlib.h gli serve in caso dovesse usare gli exit, come consigliato da vanoni, se non deve usarli allora sarebbe inutile dare una direttiva al preprocessore che non serve a nulla. Comunque dai, siate duri ma non troppo col ragazzo, magari ha veramente cominciato a programmare da poco e senza metodo, gliel'avete fatto notare ma mi sa che nonostante ciò che gli avete detto(e non 1 volta, ma 100) gli stiate facendo anche passare la voglia.

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Nuova piccola applicazione

Messaggio da j0kers »

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    FILE *fp;       
    char *cmd;    
    char *buffer; 
    int buff_size=128;


    if((fp=fopen("proc","r"))==NULL)
        exit(fprintf(stderr, "Open file error!\n"));

    if( (cmd=malloc(buff_size))==NULL || (buffer=malloc(buff_size))==NULL)
        exit(fprintf(stderr,"Error allocate %s or %s into memory!\n",cmd,buffer));

    if(argc==2){
        strcpy(cmd,"/bin/ps ");
        strcat(cmd,argv[1]);
        strcat(cmd," | grep -v");
    }else
        strcpy(cmd,"/bin/ps | grep -v");

    while(fgets(buffer,buff_size,fp)){
        if ((cmd = realloc(cmd, buff_size *= 2)) == NULL)
            exit(fprintf(stderr,"Error allocate %s into memory!\n",cmd));
        strcat(cmd," -e ");
        strncat(cmd,buffer,strlen(buffer)-1);
    }

    system(cmd);

    return 0;
}


metrofox
Linux 3.x
Linux 3.x
Messaggi: 760
Iscritto il: gio 7 ago 2008, 12:29
Slackware: slackware64-current
Kernel: 3.4.4-ck3
Desktop: FluxBox-1.3.1
Distribuzione: FreeBSD-8.1(amd64)
Località: London

Re: Nuova piccola applicazione

Messaggio da metrofox »

Io direi poi di liberare il puntatore.

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Nuova piccola applicazione

Messaggio da j0kers »

Mi sono dimenticato anche di chiudere il file :D Errori di svista purtroppo :(

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Nuova piccola applicazione

Messaggio da targzeta »

  • Codice: Seleziona tutto

    while(fgets(buffer,buff_size,fp)
    potrebbe non leggerti tutta la riga.
  • Codice: Seleziona tutto

    if ((cmd = realloc(cmd, buff_size *= 2)) == NULL)
    in pratica raddoppi la dimensione del buffer senza criterio ad ogni ciclo. Con dieci comandi da ignorare il tuo buffer passa da 2^7 a 2^17 byte, sei un bello sprecone.
  • Codice: Seleziona tutto

    strncat(cmd,buffer,strlen(buffer)-1);
    come ti ho detto il buffer potrebbe non contenere tutta la riga (basta che sia più grande di 128 caratteri. Anche se nel tuo caso può andar bene è comunque un errore, pensa se uno modifica il codice mettendoci una dimensione più piccola del buffer all'inizio, si trova un programma che non funziona e non sa perchè). Inoltre se alla fine non ci metti il terminatore di stringa ('/0') questo programma andrà comunque in segfault prima o poi.
Altri errori li hai già notati da solo, il memory leak va evitato (anche io non ho liberato la memoria) ma comunque quando il processo muore la memoria allocata viene liberata ugualmente.

Io il mio consiglio te l'ho dato ma da quello che ho capito sei uno a cui piace provare e riprovare invece che spendere meglio il suo tempo imparando una volta per tutte. L'approccio secondo me è sbagliato, ma buona fortuna.

Emanuele

P.S. Come ti ho gia detto per questo esercizio basta un solo buffer, non è obbligatorio ma finché ne usi due gli errori di distrazione possono capitare.
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Nuova piccola applicazione

Messaggio da j0kers »

Uno legge e prova.Leggere soltanto senza provare non serve a nulla :D

Rispondi