
Originariamente Scritto da
xardas
Beh, me la sono cercata... non avrei dovuto intromettermi

Riguardo alla fscanf() e scanf() non sapevo fossero deprecate, le ho sempre usate senza problemi.

Al contrario, il tuo intervento è invece apprezzabile, per la buona volontà mostrata e perché ci dà occasione di affrontare aspetti non banali e troppo spesso trascurati nei moderni corsi.
Come ricordato più volte dagli stessi autori del linguaggio e da altri ricercatori a loro vicini, la scanf() è sostanzialmente una funzione segnaposto: esiste per usarla solo durante le fasi prototipali, per mettere a punto la parte algoritmica ed elaborativa vera e propria senza preoccuparsi di scrivere un vero parser ad hoc.
Tuttavia, non deve essere utilizzata nella versione finale del software: nella sua eccessiva genericità e intrinseca complessità, la funzione risente di numerose penalità prestazionali (sia in footprint che in velocità, soprattutto nella versione fscanf), e soprattutto è prona ad errori e comportamenti indefiniti se la si utilizza per l'input di singoli caratteri e/o di stringhe.
Il sottosistema di trattamento delle stringhe di formato è inerentemente complesso, tanto da accettare anche un subset regexp poco documentato, e non si può dire di conoscerlo fino in fondo neppure dopo mesi di studio dei sorgenti di varie implementazioni della libreria standard e relativi test con input di ogni genere.
Ad esempio, pochissimi sanno che l'uso di scanf() con limitazioni sulla lunghezza del buffer, per evitare pericolosi sconfinamenti (buffer overflow), è possibile - anche se solo a prezzo di artifici sintattici non indifferenti:
Codice:
#include <stdio.h>
#include <string.h>
#define LENGTH 4
#define BUFFER_SIZE (LENGTH + 1)
#define str(x) # x
#define xstr(x) str(x)
int main(void)
{
char buff[BUFFER_SIZE];
int rc;
printf("\nSCANF : please enter text => \n");
rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", buff);
if (!feof(stdin))
{
getc(stdin);
}
if (rc == 0 || rc == EOF)
{
*buff = '\0';
}
printf("\nSCANF : length is %u\n", (unsigned)strlen(buff));
printf("size is %u\n", (unsigned)sizeof(buff));
printf("string is #%s#\n", buff);
return 0;
}
Inutile anche tentare un confronto con la concisione e affidabilità di una banale fgets(). Si veda anche questo post.
Inoltre l'uso di scanf sullo standard input è connesso all'altro annosissimo problema del flush sugli stream di input, lasciato come opzione dagli standard e causa di interminabili faide generazionali tra mondo unix (che sdegnosamente rifiuta anche solo l'idea) e mondo PC/DOS (che lo supporta da sempre).
In ultima analisi, di tutta la famiglia di scanf con le sue innumerevoli opzioni, nel software C scritto da professionisti (es. librerie commerciali, frameworks, stack di protocolli, applicazioni...) troverete al più l'uso di sscanf() per parametri di tipo numerico di formato fisso e ben noto, letti in un buffer e tipicamente machine-generated.
Questi aspetti sono trattati in pochi ma importanti testi, molti dei quali ho ricordato qui.
Per il resto, ricorda che occorrono anni di esperienza per interpretare correttamente tra le righe le richieste di aiuto nei forum.
Ad esempio, il codice proposto era sicuramente in C e questo equivale ad un chiaro vincolo d'impostazione. Nei corsi di base attuali non viene insegnato C++ in tutta la sua estensione, ma solo una specie di C on steroids.
Di fatto, le primissime lezioni sono tutte incentrate sugli iostreams: tanto che capita spessissimo di vedere stralci di tentate soluzioni che fanno pieno uso di iomanip e altre caratteristiche avanzate, per poi cascare brutalmente sull'uso di idiomi tipici del C puro o su array legacy che in C++ sono deprecati, obsoleti e sostituiti definitivamente da vector, valarray eccetera.
Dunque se il richiedente avesse avuto facoltà di usare C++, il codice proposto avrebbe avuto plausibilmente tutt'altra l'impostazione.
Inoltre, quando qualcuno che ha più esperienza di noi omette qualcosa di piuttosto evidente in una risposta, c'è sempre da domandarsi per quale motivo l'ha fatto. 
La probabilità che si tratti di una banale dimenticanza o di fretta è decisamente ridotta al minimo, dunque di norma un motivo c'è, anche se al momento non ci sovviene.
A volte, ad esempio (non è questo il caso) semplicemente non si vuole fornire una soluzione a portata di manuale, per stimolare chi ha fatto la richiesta. Altre volte si vuole incuriosire o spingere ad un approfondimento... oppure preparare il thread per una ulteriore domanda di chiarimento.

Originariamente Scritto da
Simonemigliore
volevo semplicemente chiedere una cosa...nella seguente riga di codice:
Codice:
p = strtok(b, DELIMS);
il programma non dovrebbe riconoscere se i numeri sono distanziati da spazio o tabulatore o carry return o line feed?
il problema e che se scrivo nel file di testo 65 tre spazi 32
in output mi da 65 32 32 32 32....

Ciò sarebbe alquanto anomalo, in effetti... 
Devi ancora lavorare un po' per individuare il problema.
La strtok() funziona perfettamente con tutti i delimitatori previsti, com'era ovvio.
Altrettanto ovviamente, come ampiamente previsto, la atoi() fallisce miseramente con spazi multipli o tabulazioni, perché il riposizionamento del puntatore è volutamente molto fragile.
HINT: Consiglio di dare un'occhiata anche a questo, per pensare ad una soluzione più sofisticata di token counting.