предложить:
для устранения любых «магических» чисел:
#define MAX_FILENAME_LEN 100
#define MAX_LINE_LEN 1024
#define MAX_CHARACTERS 256
заменить:
char *fname, a='A',b;
на:
char fname[ MAX_FILENAME_LEN ];
в противном случае, попытка прочитать имя файла в некоторую случайную память (хороший способ вызвать событие сбоя сегмента и его неопределенное поведение)
заменить:
printf(" ");
for (;a<='Z';a++) {
printf(" %c",a);
}
printf("\n");
на:
char line[ MAX_LINE_LEN ];
fgets( line, sizeof line, fr );
printf( "%s", line );
заменить это:
scanf("%s",fname);
fr = fopen(fname,"r");
на:
if( scanf("%99s",fname) != 1 )
{
fprintf( stderr, "scanf failed to input file name"
exit( EXIT_FAILURE );
}
// implied else, scanf successful
fr = fopen(fname,"r");
if( !fr )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
заменить
while (fscanf(fr,"%c",&b) != EOF) {
if (b == '\n') {
lines++;
}
}
на:
int lines = 1;
while( fgets( line, sizeof line, fr ) )
{
lines++;
}
rewind( fr );
замените:
while ((fscanf(fr,"%c",&b) != EOF)) {
printf("%c ",a);
//check a-z
for (a='A';a<='Z';a++) {
if (b == a || a+32 == b) {
counter++;
}
else if (b == '\n') {
line++; printf("\n");
}
}
printf("%d ",counter);
counter=0;
}
на:
int counts[ MAX_CHARACTERS ];
...
// use `While()` loop with `fgets()` to read data into `line[]`
...
memset( counts, '\0', sizeof( counts ) );
for( int i=0; line[i]; i++ )
{
counts[ line[i] ]++;
}
for( int i=0; i<MAX_CHARACTERS; i++)
{
if( counts[i] )
{
printf( "%c - %i\n" , (char)i, counts[ i ] );
}
}
Возможно, вы захотите «настроить» вышеприведенное, чтобы не выводить знаки препинания, переводы строк и т. д.
Возможно, вы захотите'настройте' вышеприведенное, чтобы подсчитать как верхние, так и строчные буквы как одинаковые.Простой способ сделать это -
#include <ctype.h>
, а затем для каждого символа, выбранного из массива 'line []:
line[i] = tolower( line[i] );
Примечание: exit()
и EXIT_FAILURE
находятся в заголовочном файле: stdlib.h