Newsgroup: it.comp.lang.c
Titolo: Progetto: help! I need somebody! Help!

Salve ^^
Sono niubba e, soprattutto, nuova del C... 
Avrei bisogno del
vostro aiuto per quanto riguarda il progetto di cui parlo nel subject.
Mi viene chiesto di fare un programma che faccia una serie di calcoli
statistici con dati prelevati da un file contenente il numero di nascite
nell'anno corrente e nell'anno passato divise per mesi.
Avevo intenzione
di assegnare questi numeri ad un array (visto che poi li devo ordinare). Mi
viene richiesto pero' di fare in modo che se il file contiene "stringhe non
riconducibili a numeri interi non negativi, queste vanno ignorate durante
l'elaborazione delle statistiche". 
Per fare questo volevo usare un
if... ma non so che istruzione fargli eseguire per dirgli di "skippare" il
dato e passare a quello dopo (senza lasciare posti vuoti nell'array).
Consigli?
Ah, e poi: secondo voi con "stringhe non riconducibili a
numeri interi non negativi vuole intendere anche le lettere e le parole? Se
e'cosi', come fareste?
Grazie mille,
-- 
Monica
UIN #55084330
-Ho visto una luce in fondo al tunnel...
-E' da dove siamo entrati.
--------------------------------
Inviato via 
http://usenet.iol.it

l'elaborazione delle statistiche". 
I modi sono molti, senza sapere com'e' fatto il file e' difficile dare
una soluzione.
La teoria di fondo e' che tu avrai dei dati (immagino salvati come
testo da quello che dici) e separati da alcuni caratteri separatori
(spazi e tab magari).
Tu devi iniziare a leggere i singoli caratteri dall'inizio (o da dove
ti sei fermata l'ultima volta) fino al prossimo separatore.
Assunzione: ti spiego dopo come interpretare quello che hai letto.
Es.
"2131 a473 3892" con separatore " "
 ^  ^ ^ ^ ^  ^
 +--+ +-+ +--+
Tutto quello che leggi lo salvi in un buffer temporaneo. Quindi al
primo passo dell'esempio nel buffer avrai "2131"; chiami il parser sul
buffer e questo ti ritornera' (per es.) il numero 2131 (prima avevi la
stringa) oppure -1 in caso di errore (visto che i numeri devono essere
solo positivi, va bene il -1).
Al secondo passaggio sulla stringa "a473" ritornera' -1 perche' c'e'
un carattere alfanumerito.
Per analizzare la stringa letta da file e isolare tutte le
sottostringhe separate da alcuni caratteri speciali ti viene in aiuto
la strtok() (gli passi come primo parametro la stringa in input, e
come secondo una stringa contenente tutti i caratteri separatori dei
token).
Per vedere se la stringa restituita dalla strtok() e' un intero valido
puoi provare a leggerlo con una sscanf()... se fallisce non era
valido. Poi controlli se era positivo o negativo, se era negativo lo
consideri non valido (oppure fai a priori un controllo sul primo char
della stringa e vedi se e' un '-' oppure no).
Questa e' la teoria. Ci sono poi vari modi per implementare questo,
sia usando funzioni gia' fornite che scrivendole ex-novo.
Se hai bisogno di un aiuto preciso chiedi e ti verra' dato :)
Consiglio: leggi dal file una riga intera con fgets() e poi applica la
strtok() su questa.
Mox

strtok() su
questa.
Ecco, volevo chiedere questo ma mi hai anticipato. Che
istruzione avrei dovuto usare per leggere l'intera riga... Grazie ^^
Credo che vi torturero' ancora per un po' prossimamente. Intanto provo a
fare quello che mi hai detto. Spero solo di riuscirci.
-- 
Monica
UIN
#55084330


Come suggerito, sono di nuovo qui a chiedere aiuto.
Ti spiacerebbe
spiegarmi il funzionamento della strtok()?
Provando a buttare giu'
qualche riga di codice:
inpfilep = fopen (FILE, "r");
fgets (buffer,
n, FILE);
strtok (buffer, ' ', '\n');
sscanf (s, "%s", &dati);
printf
("%s", dati);
Domande:
- il buffer e' un array di grandezza indefinita?
Come va dichiarato? 
Ho provato a dichiarlo "char buffer []" ma mi da
errore il compilatore   dicendo che la lunghezza di buffer non e'
dichiarata.
- il secondo parametro della fgets che cos'e? La lunghezza del
primo parametro?
- Nella strtok()la stringa di caratteri separatori la
devo creare prima?
- Nella sscanf il terzo parametro va dichiarato come
"char dati"?
Vi ringrazio per la pazienza.


sscanf (s, "%s", &dati);
Sia che tu dichiari dati come array che come puntatore a carattere non
serve la "e" commerciale, ma in tutti e 2 i casi devi allocarci
abbastanza spazio (nel primo caso quando dichiari dati, nel secondo
con una malloc).
Mox :)

 ha scritto: 
[cut]
Ok, risolto il problema della stringa con strtok()...
Dopo ho convertito
le varie stringhe con atoi() da char a int e funziona tutto. Prima pero'
devo fare un controllo sulle stringhe se queste contengono lettere, numeri
negativi o numeri con la virgola... 
Cercando nel libro avevo pensato di
usare strchr(), pero' le cose da controllare sono parecchie (se la stringa
contiene lettere da 'a' a 'z', da 'A' a 'Z', meno, virgola, punto e
quant'altro) e il secondo parametro della funzione e' un char. 
Che
funzione posso usare? Ne devo creare una ad hoc? 



Io proverei in questo modo, ma credo che non sia 
perfetto, non ci ho pensato molto.
sscanf( tempstring, "%[lettere consentite]s", string_to_check);
per ottenere una stringa che contenga solo i caratteri consentiti
della stringa di pertenza, ed a questo punto, potresti controllare se
le due stringhe; tempstring  string_to_check sono uguali.
Se sono uguali vuol dire che TUTTI i caratteri della stringa di
partenza erano consentiti.
Se non funziona fetemelo sapere, grazie

Ci ho pensato un po'... 
E se usassi uno switch che passa di volta in
volta alla strchr(stringa, c) il valore di c?
Del tipo:
switch (c){
case 'a': c >= 'a' && c <= 'z';
          if (strchr (stringa, c) != NULL)
continue;
           else
               num = atoi(stringa);
break;
case 'A': c >= 'A' && c <= 'Z';
          if (strchar (stringa, c)
!= NULL)
              continue;
          else
              num =
atoi(stringa);
              break;
case '-': c == '-';
          if
(strchr (stringa, c) != NULL)
              continue;
          else
num = atoi(stringa);
          break;
case '.': c == '.';
          if
(strchr (stringa, c) != NULL)
              continue;
          else
num = atoi (stringa);
          break;
}
(Non oso immaginare come iol
stia formattando questi messaggi, probabilmente sara' un macello...
Scusatemi, appena posso mi procuro un newsreader degno di questo nome.)


volta alla strchr(stringa, c) il valore di c?
Allora, a Molli serve un algoritmo per parsificare una espressione
regolare molto semplice.
ER: (0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9)+
(per i piu' formali: scusate, ma il simbolo di unione U rendeva
veramente male, ho preferito la sintassi usando la pipe).
In pratica deve parsificare un unsigned int.
Ora, l'automa che rinosce questo deve semplicemente scorrere tutta la
stringa fino al \0 (avendola letta con una fgets() siamo certi che ci
sara' il '\0')... e restituire errore qualora trovi un simbolo che non
sia una cifra (a livello molto formale dovremmo dire che l'automa di
ferma in uno stato non finale).
tip: In C possiamo usare la isdigit() molto comoda per riconoscere le
cifre.
Il codice che posto non e' ottimizzato, ma dovrebbe essere corretto e
soprattutto mi pare chiaro.
Note: sia la atoi() che la snprintf() non controllano se l'intero che
e' rappresentato dalla stringa possa effettivamente essere contenuto
nel tipo int... non avevo voglia di provvedere a parsificare a mano:
se qualcuno vuole puo' provarlo come esercizio :)
Per chi fosse interessato alla fine c'e' una breve descrizione
dell'automa che viene implementato.
<CODE>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define N 50
int main()
{
char buffer[N];
int d, i, stato;
while (1) {
    printf("> ");
    fgets (buffer, N, stdin);
    printf ("debug: %s\n", buffer);
    stato = 0;
    for (i=0; buffer[i] != '\0'; i++) {
        if (isdigit(buffer[i]))
            stato = 1;
        else {
            stato = 0;
            break;
        }
    }
    if (stato == 1) {
        d = atoi(buffer);
        printf("Ok: %d\n", d);
    }
    else
        printf("Error\n");
}
return 0;
}
</CODE>
Definizione (quasi) formale:
Q= 0 1 2
q0 = 0
F = 1
SIGMA = tutti i caratteri codificabili con il tipo char del c
delta:
- delta(0, digit) = 1;
- delta(1, digit) = 1;
- delta(1, SIGMA - digit) = 2;
nota implementativa: per comodita' uso solo 2 stati e anziche'
spostarmi nello stato 2 torno a zero ma blocco l'automa (cosa che non
si puo' fare con un automa, ma si puo' in C :P).
Mox :)