我正在用C语言编写一个在UNIX上运行的程序,它计算输入文本文件中每个字母的数量。对于这样的文件:
猫坐在绿色的垫子上
输出如下:
The letter ’a’ occurs 3 times.
The letter ’c’ occurs 1 times.
The letter ’e’ occurs 4 times.
The letter ’g’ occurs 1 times.
The letter ’h’ occurs 2 times.
The letter ’m’ occurs 1 times.
The letter ’n’ occurs 2 times.
The letter ’o’ occurs 1 times.
The letter ’r’ occurs 1 times.
The letter ’s’ occurs 1 times.
The letter ’t’ occurs 5 times.
5 *
4 * *
4 * *
3 * * *
3 * * *
2 * * * * *
2 * * * * *
1 * * * ** *** ***
1 * * * ** *** ***
0 **************************
0 **************************
... abcdefghijklmnopqrstuvwxyz其中,图表表示字母出现的次数。(如果大于10,我只需在第10行后加上'+‘)。我目前编写的实现这一目标的代码如下:(还没有找到一种测试大写字母和小写字母的好方法)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void drawGraph(int letters[26], char alpha[26]);
void printLetters(int letters[26], char alpha[26]);
void getLetters(FILE *fp, int letters[26], char alpha[26]);
int main(int argc, char *argv[]) {
FILE *fp;
int letters[26] = { 0 };
char alpha[26] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z' };
int indexedAlpha[256] = { 0 };
int j = 1;
for (i = 97; i <= 127; i++)
{
indexedAlpha[i] = j;
j++;
}
//open file
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Cannot open file");
exit(EXIT_FAILURE);
}
getLetters(fp, letters, alpha);
printLetters(letters, alpha);
printf("\n");
drawGraph(letters, alpha);
printf("\n");
return EXIT_SUCCESS;
}
void getLetters(FILE *fp, int letters[26], char alpha[26]) {
int c;
for (int i = 0; (c = fgetc(fp)) != EOF; i++)
{
c = fgetc(fp);
if ( isalpha(c) )
{
for ( int j = 0; j < 26; j++ ) //find which letter it is
{
if( c == alpha[j] )
{
letters[j]++;
break;
}
}
}
}
}
void printLetters(int letters[26], char alpha[26]) {
for( int i = 0; i < 26; i++ )
{
if(letters[i] != 0){
printf("The letter '%c' occurs %d times.\n", alpha[i], letters[i]);
}
}
}
void drawGraph(int letters[26], char alpha[26]) {
int x = 11;
int y;
while(x >= 0)
{
y = 0;
while (y < 2)
{
if (x == 10)
{
printf(" %d ", x);
}
else if (x == 11)
{
printf(" ");
}
else
{
printf(" %d ", x);
}
for( int i = 0; i < 26; i++ )
{
if(letters[i] > 10)
{
printf("+");
letters[i] = 10;
y++; // Break out of while loop
}
else if(letters[i] == x)
{
printf("*");
}
else
{
printf(" ");
}
if (letters[i] == x && y == 1)
{
letters[i] = letters[i] - 1;
}
}
printf("\n");
y++;
}
x--;
}
printf("... ");
for( int i = 0; i < 26; i++ )
{
printf("%c", alpha[i]);
}
}我要找的是关于表示法、效率(编写的代码数量和内存使用量)以及任何其他好的提示/最佳实践或更好的方法来完成这项任务的建议和技巧。
谢谢!
发布于 2012-11-26 16:26:50
当我第一次读到这个问题的时候,我对这个图表印象深刻。
9~10成熟。
读取文件时的小错误:
char c;
for (int i = 0; !feof(fp); i++)
{
c = fgetc(fp);这在所有语言中都是错误的。除非你读过eof,否则就不会设置eof。最后一篇成功的读物是读到(但不是过去)的。因此,即使文件中没有其他字符,也不会设置eof标志(直到您尝试在eof之后读取该字符)。
因此,你正在遭受一个一次性的错误。该循环对多个执行一次。最后一次迭代中'c‘的值被截断成一个字符。
因此,标准的模式是从文件中读取并查看它是否有效。如果它有效,那么进入循环:
int c;
for (int i = 0; (c = fgetc(fp)) != EOF; i++)
{注意,我们需要将c从一个char更改为一个int,以确保EOF不会从值中被截断。
不是一个错误:但是您正在实现O(1)操作是O(n)。
for ( int j = 0; j < 26; j++ ) //find which letter it is
{
if( c == alpha[j] )
{
letters[j]++;
break;
}尽管你可以倒置数组,但是你可以稍微多一点。所以你用这封信来查找它的ID。
char alpha[256] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0->15 ignore
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16->31 ignore
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32->47 ignore
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48->63 ignore
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64->79 ignore
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80->95 ignore
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 96->111 a -
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 0, 0, 0, 0, // 112->127 -z
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128->143 ignore
.. etc
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 240->255 ignore
// Now the lookup becomes:
if (alpha[c] != 0)
{
letters[alpha[c] - 1]++;
}但你真的在乎你是否算上了所有的角色。我不会(除非有一些严重的空间限制)。你可以数数所有的字符。当你把它们打印出来时,你只需打印出你想要的。
int letters[256];
....
letters[c]++; // or maybe letters[tolower(c)]++;
.....
// Now we just need to de reference the count of the letters we are interested in.
for( int i = 0; i < 26; i++ )
{
int count = letters[alpha[i]];
if(count != 0){
printf("The letter '%c' occurs %d times.\n", alpha[i], count);
}
}一些小的整理(你似乎有嵌入标签,混乱的间隔在这个网站)。
https://codereview.stackexchange.com/questions/19019
复制相似问题