PDA

Visualizza la versione completa : [C] Esercizio: confronto caratteri e incremento contatore


Deleted
15-02-2011, 11:14
Realizzare un programma C che legga un file di testo e produca il seguente output:
Calcolo del numero totale di caratteri inseriti nel file e relativa visualizzazione;
Calcolo del numero di occorrenze di ogni carattere non alfanumerico e relativa
visualizzazione;
Copia su disco del file di testo letto.

Ho problemi nel risolvere il quesito evidenziato in grassetto nella traccia qui sopra. Infatti sembra che quando entra nel ciclo della funzione calcolo simboli() il confronto sia sempre verificato e incrementa il contatore anche se il carattere è alfanumerico. Come mai?


/*Realizzare un programma C che legga un file di testo e produca il seguente output:
Calcolo del numero totale di caratteri inseriti nel file e relativa visualizzazione;
Calcolo del numero di occorrenze di ogni carattere non alfanumerico e relativa
visualizzazione;
Copia su disco del file di testo letto.*/

#include<stdio.h>

void letturatesto(FILE *output);
void stampatesto(FILE *output);
void calcolosimboli(FILE *output);

int main()
{
FILE *output;
//LETTURA
printf("Inserisci un testo (* per terminare l'inserimento):\n");
if((output=fopen("testo.txt","w"))==NULL)
printf("Impossibile aprire il file!\n");
else
letturatesto(output);
fclose(output);
//STAMPA
if((output=fopen("testo.txt","r"))==NULL)
printf("Impossibile aprire il file!\n");
else
stampatesto(output);
fclose(output);
//CALCOLO SIMBOLI
if((output=fopen("testo.txt","r"))==NULL)
printf("Impossibile aprire il file!\n");
else
calcolosimboli(output);
fclose(output);

system("pause");
return 0;
}


void letturatesto(FILE *output){
char c;
c=getchar();
while(c!='*'){
fputc(c,output);
c=getchar();
}
}
void stampatesto(FILE *output){
char c;
int i=0;
printf("-----------------------\n");
printf("Stampa contenuto file:\n");
c=fgetc(output);
while(c!=EOF){
printf("%c",c);
c=fgetc(output);
i++;
}
printf("\nNel file ci sono %d caratteri;\n",i);
printf("-----------------------\n");
}

void calcolosimboli(FILE *output){
char c;
int i=0;
printf("-----------------------\n");
printf("Occorrenze caratteri non alfanumerici:\n");
c=fgetc(output);
while(c!=EOF){
if(c!='a'||c!='b'||c!='c'||c!='d'||c!='e'||c!='f'| |c!='g'||c!='h'||c!='i'||c!='j'||c!='k'||
c!='l'||c!='m'||c!='n'||c!='o'||c!='p'||c!='q'||c! ='r'||c!='s'||c!='t'||c!='u'||c!='v'||c!='w'||c!=' x'||c!='y'||c!='z'
||c!='0'||c!='1'||c!='2'||c!='3'||c!='4'||c!='5'|| c!='6'||c!='7'||c!='8'||c!='9'){
i++;
}
c=fgetc(output);
}
printf("\nNel file ci sono %d caratteri non alfanumerici;\n",i);
printf("-----------------------\n");

}

YuYevon
15-02-2011, 11:28
La condizione dell'if() che hai scritto, oltre al fatto di essere inutilmente lunga, non ha praticamente alcun senso... riflettici sopra.
Tra l'altro, a meno che tu non abbia necessità di scrivere la funzione ex novo per motivi "didattici", puoi ricorrere alla funzione di libreria isdigit() (http://www.cplusplus.com/reference/clibrary/cctype/isdigit/) nell'header ctype.h

Deleted
15-02-2011, 11:33
Originariamente inviato da YuYevon
La condizione dell'if() che hai scritto, oltre al fatto di essere inutilmente lunga, non ha praticamente alcun senso... riflettici sopra.
Tra l'altro, a meno che tu non abbia necessità di scrivere la funzione ex novo per motivi "didattici", puoi ricorrere alla funzione di libreria isdigit() (http://www.cplusplus.com/reference/clibrary/cctype/isdigit/) nell'header ctype.h
Intanto mi documenterò su questa funzione che mi hai segnalato, ad ogni modo, si, dovrei scrivere una funzione/procedura ex novo. Ma non capisco proprio cosa c'è di sbagliato. Ho pensato che magari il confronto andava fatto con strcmp() ma quello funziona con le stringhe, non con i caratteri singoli, o sbaglio?

Edit:
ho provato anche con isdigit e isalpha e ho lo stesso risultato:


c=fgetc(output);
while(c!=EOF){
if(isdigit(c)!=0 || isalpha(c)!=0){
i++;
}
c=fgetc(output);
}

YuYevon
15-02-2011, 11:46
No intanto scusami ho sbagliato a leggere la traccia, ti chiede di leggere tutti i caratteri *non alfanumerici*... avevo capito solo quelli numerici :D in questo caso la funzione di libreria di riferimento diventa isalnum() (http://www.cplusplus.com/reference/clibrary/cctype/isalnum/), stesso header.

Intanto se proprio vuoi lasciare la condizione scritta così lunga, capirai che devi sostituire tutte le OR con delle AND... cioè se il carattere è diverso da a e diverso da b e diverso da c... allora incrementi il contatore.

In ogni caso scritta in quel modo la condizione è poco elegante, tra l'altro non hai incluso i caratteri maiuscoli. Prova a ragionare con i range delle codifiche dei caratteri (ipotizzando che si tratti di codifica ASCII) per rendere più compatta la condizione.

GliderKite
15-02-2011, 11:47
Il modo migliore di risolvere questo problema è pensare a quello della connettività, dandoti lo spunto di provare questo procedimento:



#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>


#define ASCII 256



/* Torna la struttura dati con il numero di coccorrenze */
unsigned * compute();

/* Stampa le occorrenze non alfanumeriche */
void print_occorrenze( const unsigned *occorrenze );




int main()
{
unsigned *occorrenze = compute();

if( occorrenze != NULL )
{
print_occorrenze( occorrenze );
free( occorrenze );
}

getchar();
return 0;
}


/* Stampa le occorrenze non alfanumeriche */
void print_occorrenze( const unsigned *occorrenze )
{
unsigned i;

printf( "\n\nOccorrenze:\n" );
for( i = 0; i != ASCII; ++i )
{
if( !isalnum(i) && occorrenze[i] )
printf( "%c %u\n", (unsigned char) i, occorrenze[i] );
}

putchar('\n');
}



/* Torna la struttura dati con il numero di coccorrenze */
unsigned * compute()
{
char filename[ 300 ];
FILE *fileptr = NULL;

printf( "Nome del file? " );
scanf( "%300s%*c", filename );

fileptr = fopen( filename, "rt" );

if( fileptr != NULL )
{
unsigned *occorrenze = (unsigned *) calloc( ASCII, sizeof(unsigned) );

if( occorrenze != NULL )
{
/* Parte principale */
while( !feof(fileptr) )
{
int c = fgetc(fileptr );

if( c != EOF )
++occorrenze[ c ];
}

fclose( fileptr );

return occorrenze;
}

fclose( fileptr );
}

return NULL;
}




Era quello che cercavi?

Deleted
15-02-2011, 11:53
Avevi ragione, avevo commesso un errore logico abbastanza stupido, infatti con && funziona. Comunque meglio utilizzare le ultratestate funzioni che mi hai segnalato.

Grazie

YuYevon
15-02-2011, 12:04
Originariamente inviato da GliderKite
Era quello che cercavi?

Magari consentire a lui di ragionarci sopra potrebbe essergli un tantino più di aiuto :stordita:
Tra l'altro attenzione a "rt" che non è una modalità di apertura file standard e il comportamento è indefinito.

GliderKite
15-02-2011, 12:10
Originariamente inviato da YuYevon
Magari consentire a lui di ragionarci sopra potrebbe essergli un tantino più di aiuto :stordita:
Tra l'altro attenzione a "rt" che non è una modalità di apertura file standard e il comportamento è indefinito.

Be dipende, credo che chi chieda qua, indipendentemente da lui, difficilmente si sarebbe posto il problema con la struttura dati da me utilizzata, vista la domanda. Non credi?

Per quanto riguarda "rt", avevo letto su cplusplus (http://www.cplusplus.com/) : Additional characters may follow the sequence, although they should have no effect. For example, "t" is sometimes appended to make explicit the file is a text file.

YuYevon
15-02-2011, 12:24
Originariamente inviato da GliderKite
Be dipende, credo che chi chieda qua, indipendentemente da lui, difficilmente si sarebbe posto il problema con la struttura dati da me utilizzata, vista la domanda. Non credi?


Non credo di aver capito ma vabbè :)


Originariamente inviato da GliderKite
Per quanto riguarda "rt", avevo letto su cplusplus (http://www.cplusplus.com/) : Additional characters may follow the sequence, although they should have no effect. For example, "t" is sometimes appended to make explicit the file is a text file.

E' quasi sempre così anche se non è garantito che lo sia: lo standard prevede come modalità di apertura r, w, a, rb, wb, ab, r+, w+, a+, r+b (o rb+), w+b (o wb+), a+b (o ab+). Nel caso non sia una di queste, il comportamento ufficialmente è indefinito anche se:



If the string begins with one of the above sequences, the implementation might choose to ignore the remaining characters, or it might use them to select different kinds of a file


sono i "might" che preoccupano ;D

GliderKite
15-02-2011, 12:37
Originariamente inviato da YuYevon

sono i "might" che preoccupano ;D

Grazie non lo sapevo ;)

Loading