Newsgroup: it.comp.lang.c++
Titolo: variabili 'long'

Salve a tutti,
ho due quesiti da porvi:
1)
quando scrivo
printf ( " Testo :  %d " , int) ;
se per esempio voglio che venga preso un 'long', cosa devo mettere al posto
di %d?
2)
Come si fa a creare le finestre di windows in C++(finora ho lavorato sotto
DOS in modalità testo e grafica!), c'è qualche funzione particolare?,quale?
grazie e ciao ;-)

DOS in modalità testo e grafica!), c'è qualche funzione particolare?,quale?
Anzitutto, notiamo che il C++ supporta tutta la API di Windows, quindi, se
vuoi, puoi fare in C++ tutto quello che potevi fare in C.
Normalmente, pero`, e` preferibile ottenere la piu` elevata produttivita`
permessa in C++ dall'uso di librerie di classi, e di framework veri e
propri.
Il framework C++ piu` diffuso sotto Windows e` l'MFC (Microsoft
Foundation Classes), che purtroppo da tanti punti di vista progettuali
e` una petecchia schifida (soprattutto perche` originalmente progettato
tanto, tanto tempo fa, quando il linguaggio C++ era molto piu` povero
e ancora poco standardizzato), pero` e` funzionalmente molto ricco,
con tanti libri che te lo insegnano, e decentemente supportato dagli
strumenti di programmazione, soprattutto il Visual C++ Microsoft.
Ce ne sono tanti altri, ma, personalmente, quando devo scrivere un
programma C++ per Windows, stringo i denti, tiro un bel respiro
fondo fondo, mi ripeto tre volte il mantra "un giorno o l'altro emergera`
un framework migliore e altrettanto ricco", poi faccio partire VC++5.0,
File/New/Projects/MFC Appwizard (Exe)/e dico al Wizard come
chiamare il mio programma, che feature ci voglio dentro, eccetera.
Lui mi genera uno scheletro di codice che "non fa nulla" ma genera
gia` una prima window in modo appropriato, poi con ClassWizard
e l'editor di risorse aggiungo via via le funzionalita` che servono
effettivamente al mio programma.
Altri ambienti, come C++Builder di Borland, o C++ VisualAge di
IBM, offrono framework completamente diversi, ma di approccio
complessivo analogo: tu scrivi solo il codice che ti serve davvero,
tutta la "infrastruttura" (e in particolare la creazione delle finestre)
e` invece normalmente gestita dalla libreria o da codice generato
per tuo conto dall'ambiente di programmazione.
Alex

 Cio` detto, il modificatore che cerchi e` "%ld".
Questa e' la risposta semplice (e esatta)....
Ci sarebbe da decidere cosa e' un long, cosa uno short, e specialmente
cosa e' un int. Quest'ultimo infatti ha la sgradevole tendenza a
dipendere dal compilatore, e nonostante sia "almeno" 16 bit tutti
oramai tendono ad assumere che sia 32 (e fra questi criminali mi ci
metto anche io :).
Ciao,
Alberto
-- 
Alberto BARSELLA
PGP fingerprint = 13 3F 22 D2 0B 0A D3 25  F1 89 FE B5 82 AD 75 2A
** Beliefs are dangerous. Beliefs allow the mind to stop functioning.
A non-functioning mind is clinically dead.  Believe in nothing... **

 cosa e' un int. Quest'ultimo infatti ha la sgradevole tendenza a
non e` necessario saperlo, la procedura di printf si prende l'incarico di
fare queste cose, percio` un printf("%d",int) funzionera` sempre qualsiasi
sia sizeof(int). ci potrebbero essere problemi con printf("%ld",int) che
funziona coi normali sistemi, ma non tutti.
---
Ranger, togli .fr dal mio indirizzo per rispondere
http://members.tripod.com/%7Eranger_rg/

> in C++, oggi, significano molto piu` spesso "accumula dati" ed
"estrai dati" e come tali si possono _sistematicamente_ usare molto
meglio delle funzioni variadiche.
Confrontiamo dunque la "leggibilita`" (compattezza, potenza, ecc
ecc) di una _tipica_ situazione "incasinata".
Ho una struttura che descrive una data:
struct	tm {			/* see ctime(3) */
        int     tm_sec;         /* seconds after the minute [0-60] */
        int     tm_min;         /* minutes after the hour [0-59] */
        int     tm_hour;        /* hours since midnight [0-23] */
        int     tm_mday;        /* day of the month [1-31] */
        int     tm_mon;         /* months since January [0-11] */
        int     tm_year;        /* years since 1900 */
        int     tm_wday;        /* days since Sunday [0-6] */
        int     tm_yday;        /* days since January 1 [0-365] */
        int     tm_isdst;       /* Daylight Savings Time flag */
        long    tm_gmtoff;
        char    *tm_zone;
};
puntata da "struct tm* pippo;", e voglio emetterla su standard output.
Con printf, ad esempio:
printf("%d-%d-19%d %d:%d:%d"
	pippo->tm_mday, pippo->tm_mon+1, pippo->tm_year,
	pippo->tm_hour, pippo->tm_min, pippo->tm_sec);
Quante volte l'abbiamo scritta, questa lunga riga?  Quante volte
al primo test abbiamo bestemmiato per esserci scordati il +1 al
mese?  Quante volte ci siamo accorti del tipico "year-2000 bug"
che si nasconde in questa forma?  Ecc, ecc.
Uso tipico con iostream:
	cout << *pippo;
e l'operator<<(ostream&, const struct tm&) e` stato scritto e
debuggato una volta per tutte.  Non che sia poi cosi` terribile:
inline ostream& operator<<(ostream& o, const struct tm&p) {
    return o<<p.tm_mday<<'-'<<p.tm_mon+1<<'-'<<p.tm_year+1900<<
	 ' '<<p.tm_hour<<':'<<p.tm_min<<':'<<p.tm_sec;
}
Comunque, anche l'approccio con "stringa di formato" ha la sua
ragion d'essere, e NON richiede l'uso di funzioni variadiche.
James Kanze, frequente contributor a comp.lang.c++.moderated,
ha alcune interessanti approcci a questo proposito sulla sua
homepage, credo (sorry, non ho l'URL sotto mano!), basate ad
esempio sul concetto, piu` simile al COBOL:
	picture format("99-99-9999 99:99:99");
	format << pippo->tm_day << pippo->tm_mon+1 << pippo->tm_year+1900;
	format << pippo->tm_hour << pippo->tm_min << pippo->tm_sec;
	cout << format;
ma ovviamente nulla impedisce a usare come stringa di 'picture'
altri formati, come i fatidici "%d", invece di quelli basati
sul concetto di '9' come "segnaposto per una cifra" che ci
viene dal Cobol, o altri ancora.  Il punto cruciale e` che con
l'operator<< per "accumulare dati in un oggetto" evitiamo le
funzioni variadiche e quindi guadagnamo un pieno controllo su
quel che succede ai nostri dati...!
Alex
--
 ____    Alex Martelli, Bologna, Italia -- email: 
al...@magenta.com
 \SM/___                                 
http://magenta.com/~alex
  \/\bi/     You never know what is enough unless you know what
     \/          is more than enough.

peggiore che abbia mai visto in C++. 
sono d'accordo, anch'io uso quasi esclusivamente la printf().
Gianpaolo Bottin
- The truth is out there -

debuggato una volta per tutte.  Non che sia poi cosi` terribile:
verissimo, hai ragione, il riutilizzo e' l'unica ragion d'essere di un
costrutto simile. Comunque la printf e' piu' versatile e d'uso piu'
immediato, se devo fare un minimo di output formattato gia' devo
andarmi a cercare una classe che lo faccia o scriverne una. Poi in
windows ci sono altri problemi meramente pratici: con il VC non mi
risulta che iostream supporti i widechar (UNICODE), poi utilizzare le
risorse con iostream complica ancora piu' le cose mentre MFC fornisce
alcune comode funzioni analoghe alla sprintf. Certo sarebbe stato
diverse se MS avesse fornito al VC una serie di classi per la gestione
dell'output formattato, visto che cosi' non e' continuo ad usare
sprintf() o l'analoga CString::Format()
Gianpaolo Bottin
- Live Long and Prosper -

sprintf() o l'analoga CString::Format()
Io mi trovo molto bene con <sstream> (mai piu` dover preallocare
un buffer e magari sbagliare lunghezza, come con sprintf, certo
fra le piu` rischiose funzioni di tutto il C...!!!).  Per le mie modeste
esigenze di formattazione iostream basta e avanza, e se e quando
mi serve qualcosa di piu`, non c'e` in giro altra abbondanza...:-).
Alex

fra le piu` rischiose funzioni di tutto il C...!!!).
ma rischiose per chi !! ;) per quel che mi ricordo non mi e' mai
successo di avere avuto un solo problema su una printf(), nemmeno nei
programmi a 16bit dove sono necessari codici di formattazione diversi
per int e long. Sono funzioni talmente usate che sbagliare e' proprio
difficile. :)


successo di avere avuto un solo problema su una printf(), nemmeno nei
Mai fatta una "sprintf(buffer,"line %d: %s\n", linum, atext);" per poi
scoprire che atext era troppo lungo e debordava dal buffer?  Se
non sbaglio questo bug era nel sendmail di vari unix e fu sfruttato
da un noto virus (o meglio "cavallo di troia") qualche anno fa per
mettere in ginocchio tutta l'internet.  Se succede agli autori di
sendmail, puo` succedere anche a me; ed e` proprio il tipo di bug
che vive nascosto per molti anni in un programma che tutti credono
solido e stabile, perche` "di solito" atext ha lunghezze ragionevoli,
poi, una volta, viene invece da un file corrotto, una linea rumorosa,
o un utente cattivello, e BUM.
Una funzione standard C che non puo` MAI essere corretto usare
e` gets(); in quel caso e` impossibile determinare a priori quanto
e` lunga la prossima riga da standard input, pero` tu stai passando
un buffer di dimensione fissa, quindi *necessariamente qualsiasi
chiamata a gets e` un bug (fragilita` ad input "irregolare") nel
programma che la usa.
Sentir difendere quel catorcio di "stdio", una delle librerie peggio
progettate della storia, e` divertente... mostra proprio che la gente
si abitua a tutto!  Dove va l'argomento "FILE*" nelle varie funzioni
di questa libreria, ad esempio...?  iostream, in confronto a stdio,
e` una fulgente gemma di limpido design, cari miei...:-).
(Non che la string.h sia poi fatta tanto bene -- la specifica, benche`
coerente, idiozia di far tornare da quasi ogni funzione str...() lo
stesso argomento gia` passatole, che il programmatore sa gia`,
invece dell'indirizzo della _fine_ [0 di terminazione] che la funzione
sa ma per il programmatore costa O(N) riscoprire, fa si` che mettere
insieme una stringa con una serie di strcat() ha un costo O(N**2),
computazionalmente assurdo per un'operazione banalmente
riducibile a O(N)... comunque stdio.h ha troppe piu` scemenze
di string.h perche` quest'ultima possa contenderle la palma, anche
se la non rientranza di strtok() come scemenza non e` male...:-).
Alex

se la non rientranza di strtok() come scemenza non e` male...:-).
ehi, ma cosi' mi distruggi i cari K&R !! :) Comunque hai ragione,
quella della stracat() e della strtok() sono due belle scemenze.


della variabile)
In che senso printf é insicura ???
Ciao by Stefano from Italy
http://freeweb.aspide.it/free/imperial

In che senso printf é insicura ???
Nel senso che viola la "type safety", che i compilatori si
fanno normalmente in quattro per garantire.
Supponiamo: sviluppo un programma in Italiano che a un
certo punto deve dare un messaggio, tipo:
    printf("Comprati sinora: %d %s\n", nCompr, szCompr);
Sara` meglio che nCompr sia un int, e szCompr una
stringa di caratteri terminata da zero, altrimenti, crash.
Questo e` il tipo di insicurezze di printf che alcuni buoni
compilatori (tipo gcc) sanno controllare.  Ma i controlli
naturalmente sono molto limitati, e specificamente sono
possibili solo se il primo argomento di printf e` una
stringa costante.  Quando internazionalizzo il programma
nel modo piu` semplice, tipo:
    const char *format = getLocalizedString(IDS_PMSFA93);
    printf(format, nCompr, szCompr);
non posso neppure concettualmente avere nessun warning
dal compilatore... solo un crash clamoroso se un certo
linguaggio naturale prevede che nel messaggio numero
e nome siano scambiati, e colui che ha editato la string
table si e` ingenuamente limitato a scambiare gli indicatori,
mettendo %s prima di %d.  printf() e` _interpretativa_ e lo
e` relativamente a quello che nella filosofia stessa del C++
deve invece intrinsecamente essere controllato compile
time: la correttezza dei tipi degli argomenti di una funzione!
Alex

stringa di caratteri terminata da zero, altrimenti, crash.
Altrimenti crash? Ma cosa dici? Guarda che quando si tratta di *leggere*
dalla memoria e scrivere a schermo come con printf, anche la lettura da un
indirizzo casuale non ti porterà mai a un crash, anche se chissà cosa ti
verrà scritto sullo schermo :-(

mettendo %s prima di %d.
le traduzioni, questo si' che e' un bel problema. Capita abbastanza
spesso che traducendo in altre lingue sia necessario cambiare l'ordine
dei codici di formattazione, finora non ho trovato nessun sistema
valido, le uniche due soluzioni sono:
1) Minacciare di morte il traduttore in modo che non sposti nessun
codice di formattazione. Soluzione praticabile, ma poco elegante :)
2) Preparare separatamente le stringhe con i numeri formattati e poi
comporre una stringa con il messaggio finale, magari usando
AfxFormatString(). Solo che fare cosi' e' una bella seccatura, un
mucchio di codice per ogni messaggio di errore.
Hai qualche idea in merito ?


verrà scritto sullo schermo :-(
no, no, in qualunque ambiente che abbia la protezione della memoria
(windows,unix,os/2,dos-extender) un accesso con un puntatore errato ti
da' un Access Violation o un GP fault, provare per credere :). Solo in
dos puro dove non c'e' protezione di memoria si verifica quanto dici.


dos puro dove non c'e' protezione di memoria si verifica quanto dici.
Perň... e dire che pensavo che Win32 la proteggesse la memoria... mah,
evidentemente non č cosě, altrimenti col C++ Builder otterrei l'Access
Violation di cui tu mi parli invece che una stringa a casaccio... misteri!
:-)))

:-)))
nella sfortuna del baco sei stato doppiamente sfortunato, l'unico caso
in cui la protezione della memoria non funziona e' quando l'indirizzo
pur sbagliato e' comunque un indirizzo di un blocco di memoria valido.
Se invece di passare un puntatore a caso alla printf passi un numero
<64k vedrai che bell'Access Violation !! 
I bachi piu' difficili da beccare sono proprio quelli in cui un
accesso alla memoria con un puntatore sballato non ti da' un Access
Violation ma ti va a scrivere a caso nella memoria usata dal
programma.


programma.
Ma allora parliamo due lingue diverse! Io non ho mai detto *scrivere*. E'
palese che se vado a scrivere nella memoria protetta da Windows mi becco
l'Access Violation. Io però ho semplicemente detto che la printf, poichè
*legge* dalla memoria, non ti sbatte in faccia quel maledetto Access
Violation...

Violation...
leggere o scrivere fa poca differenza, se a quell'indirizzo il tuo
programma non ha allocato memoria ottieni un Access Violation, non
c'e' scampo. In win32 non e' che puoi andarti a leggere la memoria
cosi' come ti pare e piace, puoi solo accedere alla memoria che ti
appartiene, alcune di queste aree sono read/write, altre sono
read-only ma in genereale se in un puntatore metti un valore casuale
devi essere veramente molto fortunato ad andare a beccare una zona di
memoria esistente. Spesso pero' nei programmi reali i valori
"sbagliati" che finiscono in un puntatore non sono cosi' sbagliati da
dare Access Violation, sono magari valori "vecchi" che indirizzano
memoria esistente ma utilizzata per altri scopi. 
Voi un Access Violation in lettura ? Prova a leggere un indirizzo <4K
(64k in NT), vedrai un bell'exception 0xc0000005.


(64k in NT), vedrai un bell'exception 0xc0000005.
Sai, leggere un indirizzo minore di 4k (a dire il vero < di 64k, non 4) con
una normale applicatione gui win95 mi produce effettivamente una bella
exception... ma quello che mi ha stupito č che se faccio lo stesso con una
console application (sempre a 32 bit) invece che produrmi un'access
violation mi impalla l'applicazione!!! E lo fa *sempre*!!!

violation mi impalla l'applicazione!!! E lo fa *sempre*!!!
boh ! che strano ! puo' darsi che le funzioni runtime del compilatore
in qualche modo intervengano nella gestione delle eccezioni. In realta
non e' obbligatorio che salti sempre fuori la finestra standard di
windows, l'eccezione potrebbe anche essere gestita all'interno del
programma in modo da cercare di recuperare l'errore o perlomeno
salvare i dati prima della chiusura.
