Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Usare o no lo stderr?

5 views
Skip to first unread message

guido84

unread,
Jun 10, 2017, 4:57:34 AM6/10/17
to
Usando la funzione strdup() con questo codice:

----------------------------------------
// char *strdup(char *vettore_origine) -- Fuori standard ANSI
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
char *dest;
..............

A questo punto, per evitare un'immissione che provocherebbe
un sigfault, ho trovato due modi, potreste dirmi qual e' il
migliore? (funzionano entrambi benissimo)

--------------- PRIMO MODO -----------------
if (argc == 1) // Se argv[1]=0 va in sigfault
{
printf("Usage: Duplica il vettore-stringa $1 in stdout \n");
}

else
{
dest = strdup(argv[1]);
printf("%s\n", dest);
}
return 0;
}
-----------

================ SECONDO MODO ================
#include <stdlib.h>

if (argc == 1) // carica l'errore in stderror?
{
fprintf(stderr, "Usage: Duplica il vettore-stringa $1 in stdout \n");
exit(1); // evita il sigfault?
}

dest = strdup(argv[1]);
printf("%s\n", dest);
return 0;
}
==========

--
Saluti,
Guido

Giovanni

unread,
Jun 10, 2017, 6:19:00 AM6/10/17
to
In genere 'stderr' si usa per i messaggi di errore per evitare che
vengano mescolati all'output del programma.

Molto spesso l'output di un programma è usato come input ad un altro ed
i messaggi di errore non sarebbero visibili o produrrebbero causare
errori anche nel programma che analizza l'output del primo.


PS: Mi spieghi che significa "$1" nella stringa che *dovrebbe* spiegare
l'uso del programma>

Ciao
Giovanni
--
A computer is like an air conditioner,
it stops working when you open Windows.
< http://giovanni.homelinux.net/ >

guido84

unread,
Jun 10, 2017, 6:33:15 AM6/10/17
to
Il 10/6/2017 12:18:59 Giovanni scrisse:
Dunque in conclusione e' meglio il primo modo: senza l'exit(1) ?
Usa anche una libreria in meno.

>PS: Mi spieghi che significa "$1" nella stringa che *dovrebbe* spiegare
>l'uso del programma>

E' il $1 della bash, l'alternativa e' argv[1], mi sembrava piu'
chiaro e veloce con $1, con argv[1] si puo' far casino rileggendo
dopo un po' e ricordando male con la storia che comincia da 0.

--
Saluti,
Guido

Giuseppe Della Bianca

unread,
Jun 10, 2017, 7:54:45 AM6/10/17
to
guido84 wrote:

]zac[
> A questo punto, per evitare un'immissione che provocherebbe
> un sigfault, ho trovato due modi, potreste dirmi qual e' il
]zac[

Questi problemi li hanno avuti tutti quelli che hanno cominciato a
programmare in C .

Dovresti leggerti qualche documentazione/libro magari per principianti.


Come spunto, ' strncpy ' e ' snprintf '.

Presta attenzione, che come molte cose nel C, sono funzioni poco amichevoli
e introducono un effetto collaterale, che puo' trasformare un scrittura
fuori dalla memoria (probabile) a una lettura fuori dalla memoria (piu'
probabile).

Come spunto, attenzione al ' \0 ' terminatore della stringa che potrebbe
essere omesso.


Senza offesa, ribadisco che affrontare il C a tentativi e senza documentarsi
prima e' poco sensato.

guido84

unread,
Jun 10, 2017, 9:45:15 AM6/10/17
to
Il 10/6/2017 13:54:09 Giuseppe Della Bianca scrisse:
>guido84 wrote:

>]zac[
>> A questo punto, per evitare un'immissione che provocherebbe
>> un sigfault, ho trovato due modi, potreste dirmi qual e' il
>]zac[

>Questi problemi li hanno avuti tutti quelli che hanno cominciato a
>programmare in C .
>Dovresti leggerti qualche documentazione/libro magari per principianti.

Si', ma son convinto che la lettura e' almeno 200x100 volte piu'
efficace quando /per pratica gia' fatta/ so-seguo-capisco di cosa
stanno parlando.

Insomma, e' come aprire una polemica sull'insegnamento: secondo
me i prof dovrebbero spiegare dopo aver prima assegnato un
capitolo da studiare sul libro a casa e per conto proprio.

>Come spunto, ' strncpy ' e ' snprintf '.
>Presta attenzione, che come molte cose nel C, sono funzioni poco amichevoli
>e introducono un effetto collaterale, che puo' trasformare in scrittura
>fuori dalla memoria (probabile) a una lettura fuori dalla memoria (piu'
>probabile).
>Come spunto, attenzione al ' \0 ' terminatore della stringa che potrebbe
>essere omesso.

Proprio la strncpy l'avevo gia' fatta, ed e' appunto per essa che
qui ho chiesto per quale scegliere tra le condizionali, perche'
ho visto che tanto ci sara' da applicarle in continuazione.

Il terminatore \0 assicurano che strncpy lo mette lei /sempre/,
forse dici quando invece d'usare strncpy mi faccio io un ciclo
for per copiare una [parte di] stringa?

Ecco lo strncpy, ero stato attento in particolare a malloc().
Ho spezzato il codice nei casi 2 e 3, ma sembra inutile e penso
proprio perche' evidentemente ci mette lo \0.

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

// char *strcpy(char *dest, char *orig, size_t n)

int main(int argc, char** argv)
{
int lunghezza, n;

if (argc==1)
{
printf("Usage: Duplica i primi n caratteri di $1 \n");
}
else // else_1
{
lunghezza = strlen(argv[1]);
printf("Scegliere n = 0..%d: ", lunghezza);
scanf("%d", &n);

// 1. n negativo
if (n < 0)
{
fprintf(stderr, "Error: n dev'essere positivo o nullo -- esco! \n");
exit(1);
}

// 2. Sicurezza (inutile?): n > lunghezza_origine
if (n > lunghezza)
{
printf("Soltanto %d caratteri disponibili, eccoli tutti: \n", lunghezza);
char* vett_enne;
vett_enne = malloc(lunghezza+1);
strncpy(vett_enne, argv[1], lunghezza);
printf("%s\n", vett_enne);
}
// 3. Caso ordinario.
else
{
char* vett_enne;
vett_enne = malloc(n+1);
strncpy(vett_enne, argv[1], n);
printf("%s\n", vett_enne);
}
} // fine else_1

return 0;
}
----------------------------


>Senza offesa, ribadisco che affrontare il C a tentativi e senza documentarsi
>prima e' poco sensato.

Ma no grazie ma figurati se non mi documentero' fino anche all'
eccessiva pignoleria. Solo che, senza vedere il codice fatto e
compilato da me, non mi riesce di seguire nessun manuale.

--
Saluti,
Guido

Alessandro Pellizzari

unread,
Jun 10, 2017, 10:52:13 AM6/10/17
to
On 10/06/17 11:33, guido84 wrote:

>>> A questo punto, per evitare un'immissione che provocherebbe
>>> un sigfault, ho trovato due modi, potreste dirmi qual e' il

Si chiama segfault (Segmentation Fault).
Te lo dico perche` rischi di far casino con le funzioni che contengono
"sig" nel nome, e che servono a gestire segnali.

>>> if (argc == 1) // carica l'errore in stderror?
>>> {
>>> fprintf(stderr, "Usage: Duplica il vettore-stringa $1 in stdout \n");
>>> exit(1); // evita il sigfault?

Questo e` meglio. Leggi qui:

http://courses.cms.caltech.edu/cs11/material/general/usage.html

In generale il normale output del programma va in stdout. Tutto il resto
va in stderr.

> Dunque in conclusione e' meglio il primo modo: senza l'exit(1) ?
> Usa anche una libreria in meno.

stdio non e` proprio una libreria in Linux. E` per la maggior parte una
dichiarazione delle interfacce della libc, che viene linkata
praticamente a tutto tranne che al kernel, quindi non risparmi niente.

>> PS: Mi spieghi che significa "$1" nella stringa che *dovrebbe* spiegare
>> l'uso del programma>
>
> E' il $1 della bash, l'alternativa e' argv[1], mi sembrava piu'
> chiaro e veloce con $1, con argv[1] si puo' far casino rileggendo
> dopo un po' e ricordando male con la storia che comincia da 0.

Rischi di creare ancora piu` confusione nell'utente, che vedendo $1
magari si aspetta uno script di shell con un bug che gli mostra il nome
della variabile invece del contenuto.

Bye.


Alessandro Pellizzari

unread,
Jun 10, 2017, 10:59:21 AM6/10/17
to
On 10/06/17 14:45, guido84 wrote:

> Ma no grazie ma figurati se non mi documentero' fino anche all'
> eccessiva pignoleria. Solo che, senza vedere il codice fatto e
> compilato da me, non mi riesce di seguire nessun manuale.

Premetto che non e` per dirti di smettere di postare le tue domande (che
sono interessanti anche per altri), ma l'impressione che ho io e` che
forse dovresti cambiare manuale, visto che stai usando questo nuowgroup
come un gruppo di professori che ti spieghino le cose che non capisci e
che, a quanto pare, il manuale non spiega.

Poi sarei curioso di capire perche` stai studiando proprio il C.

Se stai iniziando a programmare e vuoi rimanere a bassissimo livello
(nel senso di "vicino all'hardware come il C") io ti consiglierei Rust.

Se vuoi un livello leggermente piu` alto direi Go.

Se non hai mai programmato prima io partirei da Python (per CLI e GUI) o
PHP (per web), che sono di livello piu` alto e piu` semplici da capire.

Bye.

guido84

unread,
Jun 10, 2017, 12:56:28 PM6/10/17
to
Il 10/6/2017 16:52:12 Alessandro Pellizzari scrisse:
>On 10/06/17 11:33, guido84 wrote:

>>>> A questo punto, per evitare un'immissione che provocherebbe
>>>> un sigfault, ho trovato due modi, potreste dirmi qual e' il

>Si chiama segfault (Segmentation Fault).
>Te lo dico perche` rischi di far casino con le funzioni che contengono
>"sig" nel nome, e che servono a gestire segnali.

Grazie! infatti lo confondevo proprio coi segnali SIG vari della
shell (ad es. per trap o kill), non avevo notato la E.

>>>> if (argc == 1) // carica l'errore in stderror?
>>>> {
>>>> fprintf(stderr, "Usage: Duplica il vettore-stringa $1 in stdout \n");
>>>> exit(1); // evita il sigfault?

>Questo e` meglio. Leggi qui:

>http://courses.cms.caltech.edu/cs11/material/general/usage.html

OK TNX poi me lo guardo.

>In generale il normale output del programma va in stdout. Tutto il resto
>va in stderr.

>> Dunque in conclusione e' meglio il primo modo: senza l'exit(1) ?
>> Usa anche una libreria in meno.

>stdio non e` proprio una libreria in Linux. E` per la maggior parte una
>dichiarazione delle interfacce della libc, che viene linkata
>praticamente a tutto tranne che al kernel, quindi non risparmi niente.

Quella per exit che ho dovuto aggiungere e' stdlib, volevi dire questa?

>>> PS: Mi spieghi che significa "$1" nella stringa che *dovrebbe* spiegare
>>> l'uso del programma>

>> E' il $1 della bash, l'alternativa e' argv[1], mi sembrava piu'
>> chiaro e veloce con $1, con argv[1] si puo' far casino rileggendo
>> dopo un po' e ricordando male con la storia che comincia da 0.

>Rischi di creare ancora piu` confusione nell'utente, che vedendo $1
>magari si aspetta uno script di shell con un bug che gli mostra il nome
>della variabile invece del contenuto.

Vabbe' anche Giuseppe D.B. m'ha detto di non prendere cattive
abitudini all'inizio, usero' argv[1]. Ciao e grazie!

--
Saluti,
Guido

guido84

unread,
Jun 10, 2017, 12:56:28 PM6/10/17
to
Il 10/6/2017 16:59:18 Alessandro Pellizzari scrisse:
>On 10/06/17 14:45, guido84 wrote:

>> Ma no grazie ma figurati se non mi documentero' fino anche all'
>> eccessiva pignoleria. Solo che, senza vedere il codice fatto e
>> compilato da me, non mi riesce di seguire nessun manuale.

>Premetto che non e` per dirti di smettere di postare le tue domande (che
>sono interessanti anche per altri), ma l'impressione che ho io e` che
>forse dovresti cambiare manuale, visto che stai usando questo nuowgroup
>come un gruppo di professori che ti spieghino le cose che non capisci e
>che, a quanto pare, il manuale non spiega.

Seguo (perche' e' cartaceo e perche' ce l'avevo a casa) un
vecchio testo del '97 dell'Apogeo "Il C in 12 giorni" che pero'
son piu' di 700 pagine... forse volevano dire 12 mesi!
I moltissimi pdf di rete per me risultano troppo scomodi.

>Poi sarei curioso di capire perche` stai studiando proprio il C.

Solo per pura curiosita' di conoscenza, impararlo non mi serve a
nulla. Ma per chi (io) usa Linux, o piu' in generale uno unix,
il C te lo ritrovi sempre un po' dappertutto.

>Se stai iniziando a programmare e vuoi rimanere a bassissimo livello
>(nel senso di "vicino all'hardware come il C") io ti consiglierei Rust.

Ecco, il Rust di Mozilla puo' essere molto interessante anche lui!

>Se vuoi un livello leggermente piu` alto direi Go.
>Se non hai mai programmato prima io partirei da Python (per CLI e GUI) o
>PHP (per web), che sono di livello piu` alto e piu` semplici da capire.

enoquick

unread,
Jun 10, 2017, 9:39:18 PM6/10/17
to
ma l'argomento era su stderr o sulla if ?
Ti rispondo a tutti e due
stderr si usa per i messaggi di errore quindi la prima printf la
metterei come fprintf(stderr,...)
La seconda e' corretta in quando non e' un messaggio di errore.
Per la if visto che il programma e' piccolo in questo caso usare l'uno o
l'altro comporta poco
Per routine piu complesse preferisco di molto il secondo modo,lo ritengo
piu leggibile.
Ho visto troppe if/else, e pure annidate, in codice scritto da altri
per preferire il secondo metodo che poi e' quello che uso.
Questo alla faccia dei detrattori (non me ne vogliano,sono gusti) che
affermano che una routine dovrebbe avere una sola uscita.


guido84

unread,
Jun 11, 2017, 5:16:09 AM6/11/17
to
Il 11/6/2017 03:39:14 enoquick scrisse:
Era solo sull'if, ma meglio cosi' :-)

>Ti rispondo a tutti e due
>stderr si usa per i messaggi di errore quindi la prima printf la
>metterei come fprintf(stderr,...)
>La seconda e' corretta in quando non e' un messaggio di errore.

Pensavo scioccamente che questa fprintf():
---------
if (argc == 1)
{
fprintf(stderr, "Usage: Duplica il vettore-stringa $1 in stdout \n");
exit(1);
}
-------------

facesse parte della sintassi corretta per l'exit(1), adesso ho
capito (potrei anche non metterlela e farlo uscire senza fare
nulla).
Pero' secondo me allora l'Usage dovrebbe andare in stdout,
perche' ho provato diversi comandi e su stderr non ci buttano
nulla:
cp --help 2> /tmp/prova
e /tmp/prova resta vuoto.

>Per la if visto che il programma e' piccolo in questo caso usare l'uno o
>l'altro comporta poco
>Per routine piu complesse preferisco di molto il secondo modo,lo ritengo
>piu leggibile.
>Ho visto troppe if/else, e pure annidate, in codice scritto da altri
>per preferire il secondo metodo che poi e' quello che uso.
>Questo alla faccia dei detrattori (non me ne vogliano,sono gusti) che
>affermano che una routine dovrebbe avere una sola uscita.

Ho capito, insomma e' semplicissimo, e' come con la bash fare:
-----------------------
if [ -z "$1" ]; then
echo "Usage: ..."
exit 0
fi
.....
--------------

Invece di:
-----------------------
if [ -z "$1" ]; then
echo "Usage: ..."
else
.....
fi
--------------

OK, usero' il primo senza else, cosi' non c'e' neanche il
pericolo di dimenticare il fi (cioe' la graffa chiusa).

Grazie e ciao!

P.S. Scusa ma sui detrattori che dici, la routine ha ugualmente
sempre una sola uscita in entrambi i casi: o esce l'Usage o
escono i risultati. Forse vogliono dire una sola riga d'uscita
dallo scritto del sorgente?
Cioe' se ci metti l'else o se ci metti l'exit il programma con
argv[1] vuoto esce sempre li', mica con l'else va avanti.

--
Saluti,
Guido

enoquick

unread,
Jun 11, 2017, 8:43:39 AM6/11/17
to
> ......
> --------------
>
> Invece di:
> -----------------------
> if [ -z "$1" ]; then
> echo "Usage: ..."
> else
> ......
> fi
> --------------
>
> OK, usero' il primo senza else, cosi' non c'e' neanche il
> pericolo di dimenticare il fi (cioe' la graffa chiusa).
>
> Grazie e ciao!
>
> P.S. Scusa ma sui detrattori che dici, la routine ha ugualmente
> sempre una sola uscita in entrambi i casi: o esce l'Usage o
> escono i risultati. Forse vogliono dire una sola riga d'uscita
> dallo scritto del sorgente?
> Cioe' se ci metti l'else o se ci metti l'exit il programma con
> argv[1] vuoto esce sempre li', mica con l'else va avanti.
>


Io accennavo a dei dettami di programmazione che dicono di usare una
sola uscita da una routine
Non in questo caso specifico.


Giuseppe Della Bianca

unread,
Jun 11, 2017, 10:22:18 AM6/11/17
to
guido84 wrote:


> Il terminatore \0 assicurano che strncpy lo mette lei /sempre/,
]zac[

http://digilander.libero.it/uzappi/C/librerie/funzioni/strcpy.html


guido84

unread,
Jun 11, 2017, 2:56:52 PM6/11/17
to
Il 11/6/2017 14:43:35 enoquick scrisse:
>Il 11/06/2017 04:16, guido84 ha scritto:

<snip>
>> Cioe' se ci metti l'else o se ci metti l'exit il programma con
>> argv[1] vuoto esce sempre li', mica con l'else va avanti.

>Io accennavo a dei dettami di programmazione che dicono di usare una
>sola uscita da una routine
>Non in questo caso specifico.

Ah be' non e' alla mia portata e non lo sara' per molto.

Questo C e' uno spasso! prende anche tutte le sequenze escape per
l'outup a colori scritti nel sorgente con gli ottali: "\033[33m"
eccetera e anche il "\" per andare a capo, tutto come la bash!
Li ho messi senza neanche cercare nel libro e li ha accettati.

--
Saluti,
Guido

Alessandro Pellizzari

unread,
Jun 12, 2017, 4:45:12 PM6/12/17
to
On 11/06/17 19:56, guido84 wrote:

> Questo C e' uno spasso! prende anche tutte le sequenze escape per
> l'outup a colori scritti nel sorgente con gli ottali: "\033[33m"

Questo non e` C che lo fa, ma la bash stessa. Quello che C fa e` mandare
i codici alla shell, che poi li gestisce a modo suo.

L'unica similitudine e` il \033 che non e` altro che il modo per
rappresentare il codice ASCII del tasto Escape in ottale, ma presumo che
sia la shell che l'ha copiato dal C, piu` che il contrario.

Bye.




0 new messages