2015-04-17 4 views
1

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

Вот код:

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

#define MAXWORDS 10000 
#define MAXSTRING 100 

/* structure holding word frequency information */ 

typedef struct _word { 
    char s[MAXSTRING]; /* the word */ 
    int count;  /* number of times word occurs */ 
} word; 

void insert_word(word *words, int *n, char *s) { 
    int i; 

    for (i = 0; i < *n; i++) { 
     if (strcmp(s, words[i].s) == 0) { 
      /* found it? increment and return. */ 
      words[i].count++; 
      return; 
     } 
    }  
    strcpy(words[*n].s, s); 

    /* this word has occurred once up to now, so count = 1 */ 
    words[*n].count = 1; 

    /* one more word */ 
    (*n)++; 
} 

/* comparison function for quicksort. this lets quicksort sort words 
* by descending order of count, i.e., from most to least frequent 
*/ 
int wordcmp(word *a, word *b) { 
    if (a->count < b->count) return +1; 
    if (a->count > b->count) return -1; 
    return 0; 
} 

/* return 1 if c is alphabetic (a..z or A..Z), 0 otherwise */ 
int is_alpha(char c) { 
    if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) return 1; 
    return 0; 
} 

/* remove the i'th character from the string s */ 
void remove_char (char *s, int i) { 
    while (s[i]) { 
     i++; 
     s[i-1] = s[i]; 
    } 
    s[i] = 0; 
} 

/* remove non-alphabetic characters from the string s */ 
void remove_non_alpha(char *s) { 
    int i; 

    for (i = 0; s[i]; i++) { 
     if (!is_alpha (s[i])) 
      remove_char (s, i); 
    } 
} 

/* make all the letters in s lowercase */ 
void make_lowercase(char *s) { 
    int i; 

    for (i = 0; s[i]; i++) 
     s[i] = tolower(s[i]); 
} 

/* main program */ 
int main() { 
    word words[MAXWORDS]; 
    char s[1000]; 
    int i, n, m; 

    n = 0; 
    int a; 
    scanf("%d",&a); 

    /* read all the words in the file... */ 

    while (!feof(stdin)) { 
     scanf("%s", s); 

     if (is_alpha(s[0])) { 
      remove_non_alpha(s); 
      make_lowercase(s); 
      insert_word(words, &n, s); 
     } 
    } 

    qsort((void *)words, n, sizeof(word), 
      (int (*)(const void *, const void *))wordcmp); 

    /* if fewer than 20 words in total, just print up the the 
    * first n words 
    */ 
    if (n < a) 
     m = n; 
    else 
     m = a; 

    /* print the words with their frequencies */ 
    for (i = 0; i < m; i++) 
     printf("%s %d\n", words[i].s, words[i].count); 
} 
+0

Каков ваш выход, если «два или более слова происходят столько же раз»? Подумайте об этом, что это значит? –

ответ

2

Вы должны уточнить функцию сравнения: если число вхождений равно, возвращает сравнение самих строк:

/* comparison function for quicksort. this lets quicksort sort words 
* by descending order of count, i.e., from most to least frequent. 
* words with equal frequency will be sorted in ascending lexicographical 
* order. 
*/ 
int wordcmp (word *a, word *b) { 
    if (a->count < b->count) return +1; 
    if (a->count > b->count) return -1; 
    return strcmp(a->s, b->s); 
} 

Также обратите внимание, что ваш синтаксический петля неверна: while (!feof(stdin)) не останавливается правильно в конце файла, последнее слово анализируется дважды. Вы должны изменить логику:

while (scanf("%999s", s) == 1) { 
    ... 
} 

Формат "%999s" предотвращает сверхдолгое слово из вызывая переполнение буфера. Такое длинное слово будет разделено молча и, следовательно, немного исказить статистику, вместо того, чтобы ссылаться на неопределенное поведение (потенциальный сбой).

+0

Примечание: 'strcmp' не является алфавитом вообще (он сравнивает значения байтов). Хотя это * * в алфавитном порядке в этом случае (ввод строчный a..z). – jfs

+0

@ J.F. Себастьян: это правильно! 'strcmp()' выполняет лексикографическое сравнение в локали 'C', то есть байтовое сравнение по байтам. Если OP хочет более сложный метод сопоставления, он может использовать 'strcoll()' вместо этого и молиться, чтобы локаль была правильно определена и выбрана. Даже с прописными буквами a-z правильная сортировка на испанском языке отличается от того, что будет производиться 'strcmp':' ll' и 'ch' требуют специальной обработки. – chqrlie

Смежные вопросы