Ho buttato giù brevemente una possibile infrastruttura di test per sviluppare il discorso.
Codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define BUFF_SIZE 128
#define MAX_NUMERI 100
#define DELIMS " \t\n\r"
int PopolaArray1(const char *Buff, int *Array, const int Limite)
{
int i = 0;
char *p;
/*
Ai soli fini del test: la strtok() non è priva
di side effects, mentre a noi occorre riusare Buff.
*/
char *b = strdup(Buff);
p = strtok(b, DELIMS);
while ((NULL != p) && (i < Limite))
{
Array[i++] = atoi(p);
p = strtok(NULL, DELIMS);
}
return (i);
}
int PopolaArray2(const char *Buff, int *Array, const int Limite)
{
int i = 0;
int val = atoi(Buff);
/*
La atoi è molto potente anche da sola, ma ha una
notevole limitazione...
*/
while (0 != val)
{
Array[i++] = val;
while (isdigit(*Buff++));
val = atoi(Buff);
}
return (i);
}
int PopolaArray3(const char *Buff, int *Array, const int Limite)
{
return (0);
}
void StampaArray(int *Array, int Limite)
{
int i;
printf("# L'array letto contiene %d interi:\n", Limite);
for (i = 0; i < Limite; ++i)
{
printf("Array[%d] = %d\n", i, Array[i]);
}
}
int main(void)
{
FILE *fin;
char buff[BUFF_SIZE];
int numeri[MAX_NUMERI];
int tot_numeri;
puts("# Apertura del file");
fin = fopen("prova.txt", "r");
if (NULL == fin)
{
fputs("Errore durante l'apertura del file !", stderr);
return (1);
}
if (NULL == fgets(buff, BUFF_SIZE, fin))
{
fputs("Errore di lettura dal file !", stderr);
return (2);
}
fclose(fin);
printf("\n# Lettura, metodo 1\n# Buffer: [%s]\n", buff);
tot_numeri = PopolaArray1(buff, numeri, MAX_NUMERI);
if (tot_numeri)
{
StampaArray(numeri, tot_numeri);
}
printf("\n# Lettura, metodo 2\n# Buffer: [%s]\n", buff);
tot_numeri = PopolaArray2(buff, numeri, MAX_NUMERI);
if (tot_numeri)
{
StampaArray(numeri, tot_numeri);
}
printf("\n# Lettura, metodo 3\n# Buffer: [%s]\n", buff);
tot_numeri = PopolaArray3(buff, numeri, MAX_NUMERI);
if (tot_numeri)
{
StampaArray(numeri, tot_numeri);
}
getchar();
return (0);
}
La questione è purtroppo molto semplice nella sua primitiva brutalità: più sono destrutturati i dati, più la programmazione necessaria al parsing tenderà ad essere inelegante e difensiva.
In generale quindi si tende a separare i numeri tramite CR/LF (uno per riga), oppure usando quantità predefinite di caratteri di interpunzione come ';' o tabulazioni '\t', si cerca inoltre di comunicare all'inizio del file o per ogni linea quanti sono i dati (questo evita il ricorso a pesanti e macchinosi parser a due step)...
Soprattutto, si tende ad usare file di dati in formati binari ben strutturati e non semplici file ASCII, ovunque possibile.
Illustrare un sia pur semplice parser numerico talmente robusto da "macinare" senza errori le peggiori schifezze che l'utonto riesce ad infilare in un banale file di testo "delimited" va decisamente al di là delle possibilità del forum. Tuttavia, si possono prendere in considerazione un paio di soluzioni di base, che comunque - per robustezza, e stante la natura sostanzialmente low level del C - non possono esimersi dal procedere carattere per carattere nell'analisi del buffer di input.
La terza soluzione, lasciata come semplice esercizio per il lettore interessato, prevede l'uso di sscanf().