Newsgroup: it.comp.lang.c
Titolo: Azioni diverse, durante differenti esecuzioni dello stesso programma

Mi è stato chiesto di scrivere un programma in linguaggio C che, nella
sua prima esecuzione esegua una determinata azione, alla sua seconda
esecuzione ne esegue una diversa, ed il tutto senza l'utilizzo di file
esterni o di altro: l'eseguibile deve essere unico.
Esempio del tipico "Hello World".
1° Esecuzione
-Output programma
Hello World
- terminazione normale del programma
2° Esecuzione
-Output programma
Sono le ore 17
- terminazione normale del programma
Non ho particolare restrizioni riguardo al SO su cui lavorare.
Io, sinceramente, mi trovo spiazzato.

 ha scritto

Su riga di comando gli passi un valore (es. 1: prima esecuzione, altro
valore: non prima esecuzione).
L'eseguibile è sempre lo stesso.

usi una funzione rand() per decidere cosa fare e inizializzi il seme
con srand(time(NULL));


Con la randomizzazione non esiste la garanzia che due
esecuzioni distinte diano per forza valori distinti.
Dovrebbe essere migliore una soluzione
che "dipende direttamente dal tempo" e non
da un numero casuale che "dipende dal tempo".
--
Giorgio Silvestri
DSP/Embedded/Real Time OS   Software Engineer

 DSP/Embedded/Real Time OS   Software Engineer
e allora usi il seme invece del numero casuale che il seme genera.
Per tempi diversi, semi diversi.
Potresti ad esempio eseguire 4 operazioni diverse ogni 25 secondi.
ma se uno esegue il programma a distanza di 100 secondi accade lo
stesso evento.
La domanda è: non vuoi che due esecuzioni consecutive siano uguali? o
vuoi che generalmente le esecuzioni siano diverse?
nel primo caso, abbandona l'idea di srand() e pensa invece, ad
esempio, a nascondere una variabile in ram, nella cache... nella
memoria privilegiata... boh.

memoria privilegiata... boh.
Non sembra consentito dalle ipotesi.
Sarebbe utile sapere se interessa solo
avere output diversi o diversi e ben definiti (es: stampare "A" o "B").
Il primo caso č piů semplice ma il secondo la vedo dura.
Inoltre esiste anche il problema che se eseguo il programma
a distanza di tempo sufficientemente ravvicinata posso
ottenere lo stesso output anche stampando la data.
Il problema andrebbe per lo meno piů specificato.
Ma non sembra di semplice soluzione.
Potrebbe anche non essere possibile risolverlo completamente,
infatti deve essere a disposizione un'informazione di
stato che le ipotesi sembrano non consentire.
Anche l'idea di dare input diversi potrebbe essere
una soluzione ma sembra andare contro
le ipotesi dell'esercizio. Cioč quelle di non avere
ingerenze esterne.


a dir la verità ci sarebbe una soluzione semplice.
Il nostro prof ci ha spiegato che esiste un modo per passare dei
parametri da un'esecuzione all'altra, anche quando chiudi il
programma, semplicemente mantenendo salvato in memoria un dato.
Solo che sembrava complicatissimo...

 programma, semplicemente mantenendo salvato in memoria un dato.
Che cosa insegna il vostro prof.?
E.


Una soluzione semplice ma complicatissima... Infatti, è quello che si
evince dal post.
Se salvi in memoria un dato, sparisce appena chiudi il programma. Se
l'eseguibile dev'essere unico (senza file di testo o altro), ci
vorrebbe codice automodificante che alteri l'eseguibile ogni volta che
lo esegui... Preferirei un'altro corso, veramente. O forse -spero- sto
sovringegnerizzando il problema.
Saludos
Adriano


Eh codice automodificante!!! Ovvero ?

 Eh codice automodificante!!! Ovvero ?
http://en.wikipedia.org/wiki/Self-modifying_code

>lo esegui...
Ma era vietato aprire file esterni. Se puoi modificare il file 
contenente l'eseguibile non serve modificare il codice, basterebbe 
incrementare il valore di una costante globale, o aggiungere dati in coda.
Mi sembra di capire che quello che voleva il prof. era andare a scrivere 
in una locazione di memoria inutilizzata dal computer. Una cosa che un 
programma con i privilegi di sistema potrebbe in effetti fare... ma non 
mi sembra un esercizio molto istruttivo.
E.

"?manu*" ha scritto

Se spegni il PC tra le 2 esecuzioni del programma non funziona.

CI SONO!!!!
metti i parametri nel main...
argv[0] è il nome del programma.
A te basta modificare il nome a ogni esecuzione, e fare un check su
argv all'inizio per vedere quale esecuzione scegliere!!!

argv all'inizio per vedere quale esecuzione scegliere!!!
Inoltre con la frase "l'eseguibile deve essere unico" si potrebbe
anche intendere che il nome del file non deve essere cambiato.
Anche qui l'OP potrebbe dire la sua.
Il problema andrebbe meglio definito!



http://vigna.dsi.unimi.it/

 anche intendere che il nome del file non deve essere cambiato.
l'eseguibile E' unico. Il nome fa parte dell'eseguibile.


ciao, forse puoi provare a usare dei semafori o zona condivise di
memoria?


Quindi la soluzione che fa uso di argv non va bene anche se
il nome del programma è a disposizione.
Se le ipotesi iniziali erano :
" ... il tutto senza l'utilizzo di file esterni o di altro: l'eseguibile
deve essere unico."
Allora devo supporre che:
(1) non si possono usare file esterni;
(2) non si può usare memoria condivisa;
(3) non si può modificare il file eseguibile (quando c'è);
(4) non si possono passare dati in ingresso al programma;
In sostanza l'esecuzione non pò far uso di input di nessun tipo.
Quindi una "vera" soluzione mi sembra che non possa esistere
mancando qualunque informazione sullo stato.


 In sostanza l'esecuzione non pò far uso di input di nessun tipo.
mmm
abbastanza tirata per i capelli (tra l'altro presuppone ANCHE che le due
esecuzioni avvengano di fila)
e utilizzare il valore di ritorno verso il sistema operativo?
(penso al valore $? delle varie *sh)
-- 
Under construction

 mancando qualunque informazione sullo stato.
Concordo. Per quanto mi riguarda ho abbandonato le ricerche :)
Ciao
-- 
Cybertoldo
Per rispondermi via email, sostituisci moc.liamg con 
gmail.com

 Inoltre spesso "main" non è la funzione chiamata allo start-up.
In questo caso si tratta di implementazioni non conformi allo standard.
Per lo standard, è "main" la funzione chiamata allo start-up:
"The function called at program startup is  named  main."
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it


C99 (n1124.pdf)
Devi leggere anche il paragrafo: 5.1.2.1 (freestanding).
Hai letto solo il paragrafo: 5.1.2.2 (hosted).


 (questa, pero', e' una licenza sullo standard - o mi sbaglio?)
In ambiente freestanding la funzione di start-up
si può chiamare anche in un altro modo con diversi parametri.
(Vedi anche la risposta ad Andrea).


Ok, ho la soluzione: fai che stampi la data e ora completa dalla epoch
ogni volta che è eseguito. Quello sarà sempre diverso.
Per qualcosa di "un pò" meno triviale: usa la data e ora complete per
stampare diversi messaggi diversi quando lo esegui.
Siccome ogni esecuzione dovrebbe (a meno che non lo usi in più
computer contemporaneamente, o che tu non riscriva qualche piccola
legge della fisica) accadere a un istante diverso, hai il modo di
determinare cosa fare.
Saludos
Adriano

 ogni volta che è eseguito. Quello sarà sempre diverso.
Si era già parlato di data e ora in precedenti post.
Inoltre in un altro post si è detto che non ci devono essere input di nessun
tipo.
- Se le ipotesi iniziali erano :
- " ... il tutto senza l'utilizzo di file esterni o di altro: l'eseguibile
- deve essere unico."
-
- Allora devo supporre che:
-
- (1) non si possono usare file esterni;
- (2) non si può usare memoria condivisa;
- (3) non si può modificare il file eseguibile (quando c'è);
- (4) non si possono passare dati in ingresso al programma;
-
- In sostanza l'esecuzione non pò far uso di input di nessun tipo.

 - In sostanza l'esecuzione non pò far uso di input di nessun tipo.
In questo caso, non è un'esercizio di programmazione, è Zen.
(No, rand() non serve: può dare lo stesso risultato per più esecuzioni
(specie se -come spero- è limitata a un rango di interi piccolo).).
--
Saludos
Adriano

determinare cosa fare.
Questo è virtualmente impossibile.
Poni che devi stampare "A" alla prima esecuzione e "B" alla
seconda.
Come fai a basarti solo sul tempo ?
Non c'è modo di sapere che prima di "B" c'è stata
una precedente esecuzione che ha prodotto "A".
Questo sempre nella ipotesti che non si possa far uso di input.
Ma questo non è stato definitivamente chiarito, dall'OP intendo.


 una precedente esecuzione che ha prodotto "A".
Oh, sono d'accordo con il fatto che fargli stampare ogni volta un
messaggio utile e dipendente da altre cose sia complicato. Puoi però
prendere la data e ora ottenute, che dovrebbero essere giuste a una
frazione accettabile di secondo, e lavorarci su per stampare sempre
qualcosa di diverso. Il tempo è bello perchè è lineare.
--
Saludos
Adriano

 Devi leggere anche il paragrafo: 5.1.2.1 (freestanding).
Verissimo!


 (Vedi anche la risposta ad Andrea).
Quando ho detto 'licenza' non era ironico: sinceramente non ho ben 
capito se un programma in ambiente freestanding sia effettivamente uno 
/*strictly* conforming program/; e quindi - nello specifico caso - se 
era da prendere in considerazione, come vincolo, la chiamata al main()...
(a casa mi daro' una sana rilettura di questa parte dello standard :) )



Non ti preoccupare, lo so che non era ironico :-)
E' che a volte mi faccio prendere dall'eccessiva pignoleria.
In effetti sono stato troppo cattivo.
Mi sembra scontato che in certi contesti
se stiamo parlando di "main" si dovrebbe intendere
senza dubbio "hosted" senza stare troppo a dettagliare.
Anche perchè ad esempio un programma che
usa i tipi complessi non sarebbe portabile (in quanto
nell'ambiente freestanding non è detto che siano
supportati).
Il succo del discorso è che esistono due
"parrocchie" entrambe definite dallo standard e
normalmente ci dedichiamo a una senza pensare all'altra.
Anzi ad essere proprio pignolo quando
si parla di portabilità non si dovrebbe intendere
che un programma deve girare perfettamente su
tutti e due gli ambienti.
Ma ci si deve concentrare solo su uno di essi.
Comunque anche nell'ambiente hosted, pur avendo
"int main(int argc,char **argv)", non per forza argv[0] indica il
nome del programma.
Quindi il suo utilizzo non sarebbe comunque portabile.


Io, sinceramente, mi trovo spiazzato.
Questa funziona, e a me piace pure:
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
char *my_env [] =
	{
	"HOMER=SIMPSON",
	NULL
	};
int main (int argc,char *argv [])
{
char *EnvVar;
EnvVar = getenv ("HOMER");
if (EnvVar != NULL)
	if (!strcmp (EnvVar,"SIMPSON"))
		{
		printf ("\nSeconda Esecuzione.\n");
		return 0;
		}
printf ("\nPrima Esecuzione.\n");
_execve (argv [0],argv,my_env);
return 0;
}

 ha scritto nel messaggio
news:smamt2lq0586v1vfd...@4ax.com...

Molto interessante!
Comunque rimangono alcuni punti:
l'OP dice:
/* prima esecuzione */
1) Esecuzione
2) Output
3) Terminazione normale
/* seconda esecuzione */
1) Esecuzione
2) Output (diverso da prima)
3) Terminazione normale
Sarebbe discutibile se si possa considerare terminata
la prima esecuzione con ancora un "exec" in corso.
In definitiva si tratta pur sempre di un "child process".
Inoltre rimane ancora da stabilire se le variabili
di ambiente sono ammesse.
Visto che, sempre l'OP, dice: "... senza l'utilizzo di file
esterni o di altro: l'eseguibile deve essere unico."
C'è sempre quell' "altro" che pone dei problemi.
Finchè non si chiarisce cosa si voglia intendere ...
Comunque simpatica la trovata!
