PDA

View Full Version : [C] conteggio lettere...non standard!


angelica
04-02-2004, 01:25
mi faccio risentire dopo lungo tempo! :)

allora, il programmino stupido in questione conta le lettere contenute in un file di testo, e mette il risultato in un altro.

codice:

#include <stdio.h>
#include <string.h>

main()

{
int letto, i;
int conta[59];
FILE *pf;

for (i = 0; i < 59; i++)
conta[i] = 0;

pf=fopen("origine.txt","r");
do
{
letto = getc(pf);
switch (letto)
{
case 'a': conta[0]++; break;
case 'b': conta[1]++; break;
case 'c': conta[2]++; break;
case 'd': conta[3]++; break;
case 'e': conta[4]++; break;
case 'f': conta[5]++; break;
case 'g': conta[6]++; break;
case 'h': conta[7]++; break;
case 'i': conta[8]++; break;
case 'j': conta[9]++; break;
case 'k': conta[10]++; break;
case 'l': conta[11]++; break;
case 'm': conta[12]++; break;
case 'n': conta[13]++; break;
case 'o': conta[14]++; break;
case 'p': conta[15]++; break;
case 'q': conta[16]++; break;
case 'r': conta[17]++; break;
case 's': conta[18]++; break;
case 't': conta[19]++; break;
case 'u': conta[20]++; break;
case 'v': conta[21]++; break;
case 'w': conta[22]++; break;
case 'x': conta[23]++; break;
case 'y': conta[24]++; break;
case 'z': conta[25]++; break;
case 'A': conta[26]++; break;
case 'B': conta[27]++; break;
case 'C': conta[28]++; break;
case 'D': conta[29]++; break;
case 'E': conta[30]++; break;
case 'F': conta[31]++; break;
case 'G': conta[32]++; break;
case 'H': conta[33]++; break;
case 'I': conta[34]++; break;
case 'J': conta[35]++; break;
case 'K': conta[36]++; break;
case 'L': conta[37]++; break;
case 'M': conta[38]++; break;
case 'N': conta[39]++; break;
case 'O': conta[40]++; break;
case 'P': conta[41]++; break;
case 'Q': conta[42]++; break;
case 'R': conta[43]++; break;
case 'S': conta[44]++; break;
case 'T': conta[45]++; break;
case 'U': conta[46]++; break;
case 'V': conta[47]++; break;
case 'W': conta[48]++; break;
case 'X': conta[49]++; break;
case 'Y': conta[50]++; break;
case 'Z': conta[51]++; break;
case 'à': conta[52]++; break;
case 'è': conta[53]++; break;
case 'é': conta[54]++; break;
case 'ì': conta[55]++; break;
case 'ò': conta[56]++; break;
case 'ó': conta[57]++; break;
case 'ù': conta[58]++; break;
default: break;
}
}
while(letto != EOF);
fclose(pf);
pf=fopen("conteggio.txt","w");
fprintf(pf, "a=%4d A=%4d à=%4d\n", conta[0], conta[26], conta[52]);
fprintf(pf, "b=%4d B=%4d\n", conta[1], conta[27]);
fprintf(pf, "c=%4d C=%4d\n", conta[2], conta[28]);
fprintf(pf, "d=%4d D=%4d\n", conta[3], conta[29]);
fprintf(pf, "e=%4d E=%4d è=%4d é=%4d\n", conta[4], conta[30], conta[53], conta[

54]);
fprintf(pf, "f=%4d F=%4d\n", conta[5], conta[31]);
fprintf(pf, "g=%4d G=%4d\n", conta[6], conta[32]);
fprintf(pf, "h=%4d H=%4d\n", conta[7], conta[33]);
fprintf(pf, "i=%4d I=%4d ì=%4d\n", conta[8], conta[34], conta[55]);
fprintf(pf, "j=%4d J=%4d\n", conta[9], conta[35]);
fprintf(pf, "k=%4d K=%4d\n", conta[10], conta[36]);
fprintf(pf, "l=%4d L=%4d\n", conta[11], conta[37]);
fprintf(pf, "m=%4d M=%4d\n", conta[12], conta[38]);
fprintf(pf, "n=%4d N=%4d\n", conta[13], conta[39]);
fprintf(pf, "o=%4d O=%4d ò=%4d ó=%4d\n", conta[14], conta[40], conta[56], conta

[57]);
fprintf(pf, "p=%4d P=%4d\n", conta[15], conta[41]);
fprintf(pf, "q=%4d Q=%4d\n", conta[16], conta[42]);
fprintf(pf, "r=%4d R=%4d\n", conta[17], conta[43]);
fprintf(pf, "s=%4d S=%4d\n", conta[18], conta[44]);
fprintf(pf, "t=%4d T=%4d\n", conta[19], conta[45]);
fprintf(pf, "u=%4d U=%4d ù=%4d\n", conta[20], conta[46], conta[58]);
fprintf(pf, "v=%4d V=%4d\n", conta[21], conta[47]);
fprintf(pf, "w=%4d W=%4d\n", conta[22], conta[48]);
fprintf(pf, "x=%4d X=%4d\n", conta[23], conta[49]);
fprintf(pf, "y=%4d Y=%4d\n", conta[24], conta[50]);
fprintf(pf, "z=%4d Z=%4d\n", conta[25], conta[51]);
fclose(pf);
}

domande:
1) non legge i caratteri accentati...come faccio a farglielo fare?
2) come faccio, nel caso volessi far inserire all'utente il nome del file col testo da analizzare? (che nel prog sopra è tassativamente origine.txt
Gli chiedo il nome del file, ok, e magari lo registro con un gets(nome)...ma come faccio a fargli mettere tale stringa in
pf=fopen("???","r");

un'altra cosa...il codice è noiosissimo, vale a dire, tutte quelle righe perché non posso usare solo un array numerico, devo mettere a=, b=, ecc ecc...
non c'è proprio altro modo?

grazie dei consigli!!! :)

cionci
04-02-2004, 01:50
IMHO:
Fai un vettore di 256 interi...c'è un minimo di spreco, ma non è importante ed il tutto si riduce a:

do
{
letto = getc(pf);
conta[letto]++;
}
while(letto != EOF);
....
fprintf(pf, "a=%4d A=%4d à=%4d\n", conta['a'], conta['A'], conta['à']);

Prova un po' se così funziona...

cionci
04-02-2004, 02:42
E volendo si possono ridurre anche le fprintf (anche se risulterebbe un po' complesso da leggere)...

cionci
04-02-2004, 02:45
char nomefile[256];

printf("Inserisci il nome del file: ");
scanf("%s", nomefile);
....
pf=fopen(nomefile,"r");

verloc
04-02-2004, 07:07
switch lungo:

considera che i char sono (piccoli?) interi,il loro valore numerico segue l'ordine alfabetico(prima le maiuscole).
Se a=1 ,b=2 A=... etc (però non mi ricordo da dove partono :D )

quindi basta un if(char>0 &&char<finealfabeto) faiquellochevuoi();

escludendo tutti i caratteri non stampabili.
Mi ricordo che è il primo esempio del Kernighan & Ritchie :)

cionci
04-02-2004, 09:28
Considera che lei cerca anche i caratteri accentati e che sono intorno a 150 dei codisci ASCII...

Comunque se vuoi risparmiare sul vettore:

switch(letto)
{
case 'à': conta[52]++; break;
case 'è': conta[53]++; break;
case 'é': conta[54]++; break;
case 'ì': conta[55]++; break;
case 'ò': conta[56]++; break;
case 'ó': conta[57]++; break;
case 'ù': conta[58]++; break;
default:
if(letto >= 'a' && letto <= 'z')
conta[letto - 'a']++;
else if(letto >= 'A' && letto <= 'Z')
conta[26 + letto - 'A']++;
}

angelica
04-02-2004, 10:40
Originariamente inviato da cionci
char nomefile[256];

printf("Inserisci il nome del file: ");
scanf("%s", nomefile);
....
pf=fopen(nomefile,"r");
;) ci avevo pensato stanotte!
passi il puntatore alla stringa, come da funzione fileopen :p

angelica
04-02-2004, 10:51
Originariamente inviato da cionci
IMHO:
Fai un vettore di 256 interi...c'è un minimo di spreco, ma non è importante ed il tutto si riduce a:

do
{
letto = getc(pf);
conta[letto]++;
}
while(letto != EOF);
....
fprintf(pf, "a=%4d A=%4d à=%4d\n", conta['a'], conta['A'], conta['à']);

Prova un po' se così funziona...

buona idea, grazie! ora provo!

verloc
04-02-2004, 10:51
Originariamente inviato da cionci
Considera che lei cerca anche i caratteri accentati e che sono intorno a 150 dei codisci ASCII...

Comunque se vuoi risparmiare sul vettore:

switch(letto)
{
case 'à': conta[52]++; break;
case 'è': conta[53]++; break;
case 'é': conta[54]++; break;
case 'ì': conta[55]++; break;
case 'ò': conta[56]++; break;
case 'ó': conta[57]++; break;
case 'ù': conta[58]++; break;
default:
if(letto >= 'a' && letto <= 'z')
conta[letto - 'a']++;
else if(letto >= 'A' && letto <= 'Z')
conta[26 + letto - 'A']++;
}


Precisamente quello che intendevo! :)

angelica
04-02-2004, 14:31
...purtroppo, neppure la soluzione del primo post di cionci mi legge i caratteri accentati... :(

(ah, perché vettore proprio a 256 caratteri?)

ad esempio, se nel file di input c'è:
aaaaAAAAAAAAAAAaaAAàààààààààà

in conteggio.txt, alla fine, mi scrive:
a= 6 A= 13 à=2000

ho visto che mette 2000 in barba al numero delle à presenti...
anzi, non è vero...ho provato con questo altro input:
aaaaaaaaaaaaaaaAAAAAAAAAAAAAAAAAAAAAAAa
e mi dà
a= 16 A= 23 à= 52
se poi aggiungo "à" in fondo, resta a 52...
come mai?

...altre idee, ragazzi? :)
grazie per il supporto!

a2000
04-02-2004, 14:34
Originariamente inviato da verloc


ah poveravvui ! :p

e poi dice "inventare la ruota" :rolleyes:

ma vui sit ancora a "inventare la clava" ! :D

verloc
04-02-2004, 15:41
i caratteri sono in totale 256: 128+128 estesi.Quindi il vettore ha 256 elementi.
L'unica cosa che potrebbe spiegare il conteggio a cacchio potrebbe essere il vettore non inizializzato ma non dovrebbe essere così(almeno credo :confused: ).

Tu che dici cionci?

cionci
04-02-2004, 16:52
switch((char)letto)
{
case 'à': conta[52]++; break;
case 'è': conta[53]++; break;
case 'é': conta[54]++; break;
case 'ì': conta[55]++; break;
case 'ò': conta[56]++; break;
case 'ó': conta[57]++; break;
case 'ù': conta[58]++; break;
default:
if(letto >= 'a' && letto <= 'z')
conta[letto - 'a']++;
else if(letto >= 'A' && letto <= 'Z')
conta[26 + letto - 'A']++;
}

Così funziona... Il motivo è questo...
getc legge un byte dal file (un vile sempre positivo da 0 a 255)...
'à' è un char (con segno)...i caratteri standard vanno da 0 a 127, mentre quelli estesi da -128 a -1... Essendo le lettere accentate caratteri estesi il valore di 'à' è negativo...
Di conseguenza veniva confrontato un valore positivo con uno negativo...e di conseguenza non c'era mai successo... Forzando letto a char i valori maggiori di 127 vengono convertiti in numeri negativi...di conseguenza il confronto ha successo...

verloc
04-02-2004, 17:35
miezzeca m'ero dimenticato che era signed! :muro:

:sofico:

angelica
04-02-2004, 17:41
grazie!
sei stato gentilissimo (la tua bravura è incredibile)! :)

ora, ti volevo fare un'altra domanda:

hai scrittoE volendo si possono ridurre anche le fprintf (anche se risulterebbe un po' complesso da leggere)...Ecco, come faresti? :)

cionci
04-02-2004, 18:19
for(letto = 0; letto<26; ++letto)
{
fprintf(pf, "%c=%4d %c=%4d", 'a'+letto, conta[letto], 'A'+letto, conta[26+letto]);
switch('a'+letto)
{
case 'a': fprintf(pf, " à=%4d\n", conta[52]); break;
case 'e': fprintf(pf, " è=%4d é=%4d\n", conta[53], conta[54]); break;
case 'i': fprintf(pf, " ì=%4d\n", conta[55]); break;
case 'o': fprintf(pf, " ò=%4d ó=%4d\n", conta[56], conta[57]); break;
case 'u': fprintf(pf, " ù=%4d\n", conta[58]); break;
default: fprintf(pf, "\n");
}
}

Ziosilvio
04-02-2004, 18:21
Vi siete ricordati di pulire l'array di 256 char prima di eseguire il ciclo do...while?
Che so, cosette tipo:

for (i=0; i<256; i++)
conta[i]=0;

cionci
04-02-2004, 18:25
Ecco un'altra cosa che mi ero scordato di correggere:

for (i = 0; i < 59; i++)
conta = 0;

Ovviamente c'è un errore...

angelica
04-02-2004, 20:58
grazie ancora, cionci! :)

ora sono proprio poche righe di codice, come piace a me!

ah, per l'inizializzazione dell'array...l'avevo fatta! ;)

cionci
04-02-2004, 22:02
Originariamente inviato da angelica
ah, per l'inizializzazione dell'array...l'avevo fatta! ;)
Nel codice originale c'era un errore (conta = 0...andava messo conta[i] = 0)....

angelica
04-02-2004, 23:29
Originariamente inviato da cionci
Nel codice originale c'era un errore (conta = 0...andava messo conta[i] = 0)....
;) me ne sono accorta in fretta (almeno quello! :p ), anche se non ho modificato il mio primo post qui! :)

Black imp
05-02-2004, 02:03
scusa, ho letto di sfuggita ma non ti conviene anzichè usare quella sfilza di case fare una cosa del tipo

count[letto-'a']++;

posto che
1.nel codice ASCII 'a' sia il minore dei caratteri che ti servono
2.che ci sia un controllo prima in modo che si escludano i caratteri sotto e sopra un certo codice ASCII che non ti servono
3. che i caratteri che vuoi contare abbiano codici ASCII consecutivi

non mi ricordo e non ho letto bene cnque forse ci va anche un cast sulla 'a' del tipo

count[letto-(int)'a']++;

ma non ricordo. la sintassi dei linguaggi la ripasso solo quando mi serve

:p

cionci
05-02-2004, 13:17
Il problema è che i caratteri non sono consecutivi... Quelli accentati sono oltre il 200...