2016-09-28 6 views
2

Я занимаюсь домашней работой курса программирования C, и мне нужно найти наиболее распространенный символ в данном файле.Наиболее распространенный символ в файле в C

Мое тестирование тестовым файлом, пустым файлом и другими текстовыми файлами небольшого объема отлично работает (или, по крайней мере, я так думаю), но в последнем длинном тестовом файле что-то пошло не так, и сообщение об ошибке: «Должен был вернуться» '(101) для файла rfc791.txt. Вы вернули' b '(98) ".

Итак, что я спрашиваю, что может быть неправильным с моим кодом, когда неожиданно самая распространенная буква - это не то, что должно быть?

int most_common_character(char *filename) { 
    FILE *f; 
    if ((f = fopen(filename, "r")) == NULL) { 
     fprintf(stderr, "Not opened: %s\n", strerror(errno)); 
     return -1; 
    } 

    char frequency[26]; 
    int ch = fgetc(f); 
    if (ch == EOF) { 
     return 0; 
    } 

    for (ch = 0; ch < 26; ch++) { 
     frequency[ch] = 0; 
    } 

    while (1) { 
     ch = fgetc(f); 
     if (ch == EOF) { 
      break; 
     } 
     if ('a' <= ch && ch <= 'z') { 
      frequency[ch - 'a']++; 
     } 
     else if ('A' <= ch && ch <= 'Z') { 
      frequency[ch - 'A']++; 
     } 
    } 
    int maxCount = 0; 
    int maxChar = 0; 
    for (int i = 0; i <= 26; ++i) { 
     if (frequency[i] > maxCount) { 
      maxCount = frequency[i]; 
      maxChar = i; 
     } 
    } 
    fclose(f); 
    return maxChar + 'a'; 
} 

Я был бы очень признателен, если кто-то есть какие-то намеки, чтобы исправить мой код :) Я пытался найти решение этой проблемы от многого другого связанного с тем, но ничего не похоже на работу.

+7

'для (INT I = 0; г <= 26; ++ я)' ломает границы массива. –

+7

Я бы также не использовал массив 'char', он не будет работать с большими файлами. Используйте 'unsigned int'. –

+2

Кроме того, вы читаете и отбрасываете первый символ в файле. –

ответ

0

Вы должны использовать оператор < во втором цикле. Из-за этого, когда вы проверяете частоту [i]> maxCount, на частоте [26] это ведет к неопределенному поведению, что означает, что значение в этом индексе может быть меньше или выше сравниваемого значения.

0

У вашего кода есть некоторые проблемы. Тем не менее, они настолько малы, что код все еще хорошо работает с небольшими тестами.

  1. int ch = fgetc(f); падение первый символ в файле

  2. for (int i = 0; i <= 26; ++i) вырваться из массива «ов диапазона (только от 0 -> 25)

Помимо этих небольших ошибок , ваш код очень хорош. Молодцы #thumbsup

0
  1. Петля заканчивается. @Weather Vane

    // for (int i = 0; i <= 26; ++i) { 
    for (int i = 0; i < 26; ++i) { 
    
  2. код выбрасывает результат первого символа. @BLUEPIXY

    int ch = fgetc(f); 
    if (ch == EOF) { 
        return 0; 
    } 
    // This value of ch is not subsequently used. 
    

Другие исправления, как показано ниже

int most_common_character(char *filename) { 
    ... 

    // Use a more generous count @Weather Vane 
    // char frequency[26]; 
    // Consider there may be more than 26 different letters 
    // fgetc return EOF and value in the unsigned char range 
    int frequency[UCHAR_MAX + 1] = { 0 }; 

    // Not needed as array was initialize above 
    // for (ch = 0; ch < 26; ch++) { frequency[ch] = 0; } 

    // BTW correct type declaration of int, avoided rookie mistake of using char 
    int ch; 

    // Codes use tolower(), islower() as that is the portable way to 
    // handle type-of-character detection 
    while ((ch = fgetc(f)) != EOF) { 
     frequency[tolower(ch)]++; // could add check to insure frequency[] does not overflow 
    } 

    int maxCount = 0; 
    int maxChar = -1; 
    for (int i = 0; i <= UCHAR_MAX; ++i) { 
     if (islower(i) && frequency[i] > maxCount) { 
     maxCount = frequency[i]; 
     maxChar = i; 
     } 
    } 

    fclose(f); 
    return maxChar; 
}