在 C 中的函数和字数中使用二维数组
using 2-d arrays within functions and word count in C
我是C新手,一直在业余时间学习。我正在努力掌握函数,所以对这些函数的任何帮助都会很棒,但也会让我的字数统计工作。
我的程序是统计文件中所有单词出现的次数,同时产生一个单词计数。我已经尽了最大的努力,并在主要功能中显示所有事件时让它工作,但在使用我自己的功能时它们不起作用。
由于某些我不太明白的原因,我的字数统计也不起作用。
如有任何帮助,我们将不胜感激!
最诚挚的问候,
约翰
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void print_occur_word(int initialarray[1000][10], int finalarray[1000][10], words);
void count_words(initialarray[1000][10])
int main(int argc, char *argv[])
{
FILE *file = fopen("file.txt", "rb");//opens sentences file
fseek(file, 0, SEEK_END);
long fsize = ftell(file);
fseek(file, 0, SEEK_SET);
char *str = malloc(fsize + 1);//uses malloc to find size
fread(str, fsize, 1, file);
fclose(file);//closes
str[fsize] = 0;
int count = 0, c = 0, i, j = 0, appearance, space = 0, temp, temp1;
char initialarray[1000][10], finalarray[1000][10];
char *ptr;
for (i = 0;i<strlen(str);i++)
{
if ((str[i] == ' ')||(str[i] == ',')||(str[i] == '.'))
{
space++;
}
}
for (i = 0, j = 0, appearance = 0;j < strlen(str);j++)
{
if ((str[j] == ' ')||(str[j] == 44)||(str[j] == 46))
{
initialarray[i][appearance] = '[=10=]';
i++;
appearance = 0;
}
else
initialarray[i][appearance++] = str[j];
}
appearance = 0;
for (i = 0;i <= space;i++)
{
for (j = 0;j <= space;j++)
{
if (i == j)
{
strcpy(finalarray[appearance], initialarray[i]);
appearance++;
count++;
break;
}
else
{
if (strcasecmp(finalarray[j], initialarray[i]) != 0)
continue;
else
break;
}
}
}
count_words(initialarray);
print_occur_word(initialarray, finalarray, words);
return 0;
}
int count_words(int initialarray[1000][10])
{
int i,words=0;
if(strlen(initialarray)==1)//if there are no words
printf("Number of words in array:=%d",words);
else
{
for(i=0;initialarray[i]!='[=10=]';i++)//loop for finding words
{
//checking for blank space,new line and tab
if((initialarray[i]==32)||initialarray[i]=='\t'||initialarray[i]=='\n')
words++;//incrementing count of words
}
if(initialarray[i]=='[=10=]')
words++;
return words;
}
}
void print_occur_word(int initialarray[1000][10], int finalarray[1000][10], words)
{
Printf("Number of words are: %d\n", words);
int i, count, space, j, c;
for (i = 0;i < count;i++)
{
for (j = 0;j <= space;j++)
{
if (strcasecmp(finalarray[i], initialarray[j]) == 0)
c++;
}
printf("%s : %d \n", finalarray[i], c);
c = 0;
}
}
这不是一个容易解决的问题,因为你要拆分内容,
存储单词,统计单词等。涉及的步骤很多。
首先,我注意到一些事情:
if ((str[j] == ' ')||(str[j] == 44)||(str[j] == 46))
使用 ASCII 值 不是 不正确,但它使阅读代码
更难,为了我们审查你的代码,为了你以后。使用字符
相反:
if ((str[j] == ' ')||(str[j] == ',')||(str[j] == '.'))
这更容易阅读。你也没有考虑什么时候
示例多个定界符一个接一个出现:
"these are my thoughts.... I'd like to say"
。你数到很多 "spaces"
并将许多空字符串添加到 initialarray
.
当你这样声明时:
char initialarray[1000][10];
您将自己限制为最多 1000 个单词,最大长度为 9。那是
好的,但是你必须检查你没有写越界。你是
不做任何边界检查,如果你有超过 1000 个单词,你会溢出
缓冲区,如果单词超过 9 个字符,则溢出
缓冲区。
我会这样写:首先定义一个包含单词和
出场次数。为每个单词创建一个结构数组,当你
添加一个新词,你必须检查这个词是否已经存在。如果是,那么
将计数器加一,否则添加新单词并将其计数设置为 1。例如:
typedef struct word_count {
char *word;
size_t count;
} word_count;
int add_word(word_count **wc, size_t *len, const char *word)
{
if(wc == NULL || word == NULL || len == NULL)
return 0;
// empty list
if(*wc == NULL)
*len = 0;
// search for word
for(size_t i = 0; i < *len; ++i)
{
if(strcasecmp((*wc)[i].word, word) == 0)
{
(*wc)[i].count++;
return 1;
}
}
word_count *nwc = realloc(*wc, (*len + 1) * sizeof *nwc);
if(nwc == NULL)
return 0;
// creating copy of word
nwc[*len].word = strdup(word);
if(nwc->word == NULL)
return 0; // do not update *len
nwc[*len].count = 1;
*wc = nwc;
(*len)++;
return 1;
}
void free_words(word_count *wc, size_t len)
{
if(wc == NULL)
return;
for(size_t i = 0; i < len; ++i)
free(wc[i].word);
free(wc);
}
与add_word
我存储单词并同时计算它们。我先走
通过数组并检查单词是否已存储在数组中。在那里面
如果我只增加计数。如果这是一个新词,那么我重新分配
记忆多一个词并添加该词并将计数设置为 1.
现在您可以:
void foo(void)
{
size_t len = 0;
word_count *wc = NULL;
add_word(&wc, &len, "word1");
add_word(&wc, &len, "word2");
add_word(&wc, &len, "word3");
add_word(&wc, &len, "word2");
add_word(&wc, &len, "wORD1");
if(wc)
{
for(size_t i = 0; i < len; ++i)
printf("word: '%s', count: %zu\n", wc[i].word, wc[i].count);
}
free_words(wc, len);
}
你会得到:
word: 'word1', count: 2
word: 'word2', count: 2
word: 'word3', count: 1
然后统计单词的函数使用strtok
得到单词。 strtok
修改了源字符串,所以为了保留原来的内容,我做了
一份并在上面使用 strtok
。
word_count *get_word_counts(const char *file, size_t *len)
{
if(file == NULL || len == NULL)
return NULL;
word_count *wc = NULL;
*len = 0;
// I do a copy because strtok modifies the source
// preserving the original content
char *copy = strdup(file);
if(copy == NULL)
{
fprintf(stderr, "Not enough memory\n");
return NULL;
}
const char *delim = " \t,.\r\n!"; // \n to consume newlines as well
char *token = strtok(copy, delim);
do {
// if empty word
if(token[0] == 0)
continue;
if(add_word(&wc, len, token) == 0)
{
fprintf(stderr, "failed to add word '%s'\n", token);
free(copy);
return wc; // returning all words so far
}
} while((token = strtok(NULL, delim)));
free(copy);
return wc;
}
我将这些函数放在一起并创建了一个文本文件,其中包含您的问题
内容。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef struct word_count {
char *word;
size_t count;
} word_count;
int add_word(word_count **wc, size_t *len, const char *word)
{
if(wc == NULL || word == NULL || len == NULL)
return 0;
// empty list, create one
if(*wc == NULL)
*len = 0;
// search for word
for(size_t i = 0; i < *len; ++i)
{
if(strcasecmp((*wc)[i].word, word) == 0)
{
(*wc)[i].count++;
return 1;
}
}
word_count *nwc = realloc(*wc, (*len + 1) * sizeof *nwc);
if(nwc == NULL)
return 0;
nwc[*len].word = strdup(word);
if(nwc->word == NULL)
return 0; // do not update *len
nwc[*len].count = 1;
*wc = nwc;
(*len)++;
return 1;
}
void free_words(word_count *wc, size_t len)
{
if(wc == NULL)
return;
for(size_t i = 0; i < len; ++i)
free(wc[i].word);
free(wc);
}
long get_file_size(const char *filename)
{
if(filename == NULL)
return -1;
FILE *file = fopen(filename, "rb");
if(file == NULL)
{
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
return -1;
}
if(fseek(file, 0, SEEK_END) == -1)
{
fprintf(stderr, "Could not seek to the end: %s\n", strerror(errno));
fclose(file);
return -1;
}
long fsize = ftell(file);
fclose(file);
return fsize;
}
char *get_file(const char *filename, long *filesize)
{
if(filename == NULL)
return NULL;
long fs = get_file_size(filename);
if(fs == -1)
{
fprintf(stderr, "Could not calculate file size\n");
return NULL;
}
if(filesize)
*filesize = fs;
// I use calloc so that the buffer is [=17=]-terminated
char *res = calloc(1, fs + 1);
if(res == NULL)
return NULL;
FILE *fp = fopen(filename, "rb");
if(fp == NULL)
{
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
free(res);
fclose(fp);
return NULL;
}
if(fread(res, 1, fs, fp) != fs)
{
fprintf(stderr, "Could not get the whole file\n");
free(res);
fclose(fp);
return NULL;
}
fclose(fp);
return res;
}
word_count *get_word_counts(const char *file, size_t *len)
{
if(file == NULL || len == NULL)
return NULL;
word_count *wc = NULL;
*len = 0;
// I do a copy because strtok modifies the source
// preserving the original content
char *copy = strdup(file);
if(copy == NULL)
{
fprintf(stderr, "Not enough memory\n");
return NULL;
}
const char *delim = " \t,.\r\n!"; // \n to consume newlines as well
char *token = strtok(copy, delim);
do {
// if empty word
if(token[0] == 0)
continue;
if(add_word(&wc, len, token) == 0)
{
fprintf(stderr, "failed to add word '%s'\n", token);
free(copy);
return wc; // returning all words so far
}
} while((token = strtok(NULL, delim)));
free(copy);
return wc;
}
int cmp_count(const void *s1, const void *s2)
{
word_count *w1 = (word_count*) s1, *w2 = (word_count*) s2;
return strcasecmp(w1->word, w2->word);
}
int main(int argc, char **argv)
{
int ret = 0;
if(argc != 2)
{
fprintf(stderr, "usage: %s file\n", argv[0]);
return 1;
}
long fs = 0;
char *file = get_file(argv[1], &fs);
if(file == NULL)
return 1;
size_t len = 0;
word_count *wc = get_word_counts(file, &len);
if(wc == NULL)
{
fprintf(stderr, "failed to count words\n");
ret = 1;
len = 0;
}
// sorting words
if(wc)
qsort(wc, len, sizeof *wc, cmp_count);
for(size_t i = 0; i < len; ++i)
printf("word: '%s', count: %zu\n", wc[i].word, wc[i].count);
free_words(wc, len);
free(file);
return ret;
}
输出为:
word: 'a', count: 1
word: 'all', count: 2
word: 'also', count: 2
word: 'am', count: 2
word: 'and', count: 3
word: 'any', count: 2
word: 'appearances', count: 1
word: 'appreciated', count: 1
word: 'at', count: 1
word: 'be', count: 2
word: 'been', count: 1
word: 'best', count: 1
word: 'but', count: 2
word: 'C', count: 1
word: 'can't', count: 1
word: 'count', count: 4
...
请注意,我使用 strdup
创建单词和文件内容的副本。如果你的系统
没有strdup
,你可以用这个:
char *strdup(const char *text)
{
if(text == NULL)
return;
char *copy = malloc(strlen(text) + 1);
if(copy == NULL)
return NULL;
return strcpy(copy, text);
}
编辑
OP asked in the comment section
how would I go about sorting the file by having the biggest number of occurrences first?
您需要做的就是更改函数 cmp_count
或创建一个新函数
不同的比较。 qsort
传递一个指针
到需要比较的值,如果值,则必须 return 0
相等,如果左边的值较小则小于 0,如果左边的值较小则大于 0
左边的值更大。在降序的情况下,你必须交换符号,
这意味着如果左边的值更大,你 return 小于 0,并且
如果左边的值较小,则大于 0。
所以,如果你想按出现次数排序,你必须检查 w1->count
w2->count
.
int cmp_count_by_count_desc(const void *s1, const void *s2)
{
word_count *w1 = (word_count*) s1, *w2 = (word_count*) s2;
return w2->count - w1->count;
}
那么您必须将 main
中的 qsort
行更改为:
if(wc)
qsort(wc, len, sizeof *wc, cmp_count_by_count_desc);
运行 新排序的相同测试输入,我得到
word: 'to', count: 6
word: 'my', count: 6
word: 'I', count: 4
word: 'count', count: 4
word: 'the', count: 4
word: 'and', count: 3
word: 'have', count: 3
word: 'word', count: 3
word: 'work', count: 3
word: 'am', count: 2
word: 'in', count: 2
word: 'Functions', count: 2
word: 'any', count: 2
word: 'help', count: 2
word: 'would', count: 2
word: 'be', count: 2
word: 'but', count: 2
word: 'also', count: 2
word: 'of', count: 2
word: 'all', count: 2
word: 'it', count: 2
word: 'when', count: 2
word: 'new', count: 1
word: 'C', count: 1
word: 'been', count: 1
...
我是C新手,一直在业余时间学习。我正在努力掌握函数,所以对这些函数的任何帮助都会很棒,但也会让我的字数统计工作。
我的程序是统计文件中所有单词出现的次数,同时产生一个单词计数。我已经尽了最大的努力,并在主要功能中显示所有事件时让它工作,但在使用我自己的功能时它们不起作用。
由于某些我不太明白的原因,我的字数统计也不起作用。
如有任何帮助,我们将不胜感激!
最诚挚的问候, 约翰
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void print_occur_word(int initialarray[1000][10], int finalarray[1000][10], words);
void count_words(initialarray[1000][10])
int main(int argc, char *argv[])
{
FILE *file = fopen("file.txt", "rb");//opens sentences file
fseek(file, 0, SEEK_END);
long fsize = ftell(file);
fseek(file, 0, SEEK_SET);
char *str = malloc(fsize + 1);//uses malloc to find size
fread(str, fsize, 1, file);
fclose(file);//closes
str[fsize] = 0;
int count = 0, c = 0, i, j = 0, appearance, space = 0, temp, temp1;
char initialarray[1000][10], finalarray[1000][10];
char *ptr;
for (i = 0;i<strlen(str);i++)
{
if ((str[i] == ' ')||(str[i] == ',')||(str[i] == '.'))
{
space++;
}
}
for (i = 0, j = 0, appearance = 0;j < strlen(str);j++)
{
if ((str[j] == ' ')||(str[j] == 44)||(str[j] == 46))
{
initialarray[i][appearance] = '[=10=]';
i++;
appearance = 0;
}
else
initialarray[i][appearance++] = str[j];
}
appearance = 0;
for (i = 0;i <= space;i++)
{
for (j = 0;j <= space;j++)
{
if (i == j)
{
strcpy(finalarray[appearance], initialarray[i]);
appearance++;
count++;
break;
}
else
{
if (strcasecmp(finalarray[j], initialarray[i]) != 0)
continue;
else
break;
}
}
}
count_words(initialarray);
print_occur_word(initialarray, finalarray, words);
return 0;
}
int count_words(int initialarray[1000][10])
{
int i,words=0;
if(strlen(initialarray)==1)//if there are no words
printf("Number of words in array:=%d",words);
else
{
for(i=0;initialarray[i]!='[=10=]';i++)//loop for finding words
{
//checking for blank space,new line and tab
if((initialarray[i]==32)||initialarray[i]=='\t'||initialarray[i]=='\n')
words++;//incrementing count of words
}
if(initialarray[i]=='[=10=]')
words++;
return words;
}
}
void print_occur_word(int initialarray[1000][10], int finalarray[1000][10], words)
{
Printf("Number of words are: %d\n", words);
int i, count, space, j, c;
for (i = 0;i < count;i++)
{
for (j = 0;j <= space;j++)
{
if (strcasecmp(finalarray[i], initialarray[j]) == 0)
c++;
}
printf("%s : %d \n", finalarray[i], c);
c = 0;
}
}
这不是一个容易解决的问题,因为你要拆分内容, 存储单词,统计单词等。涉及的步骤很多。
首先,我注意到一些事情:
if ((str[j] == ' ')||(str[j] == 44)||(str[j] == 46))
使用 ASCII 值 不是 不正确,但它使阅读代码 更难,为了我们审查你的代码,为了你以后。使用字符 相反:
if ((str[j] == ' ')||(str[j] == ',')||(str[j] == '.'))
这更容易阅读。你也没有考虑什么时候
示例多个定界符一个接一个出现:
"these are my thoughts.... I'd like to say"
。你数到很多 "spaces"
并将许多空字符串添加到 initialarray
.
当你这样声明时:
char initialarray[1000][10];
您将自己限制为最多 1000 个单词,最大长度为 9。那是 好的,但是你必须检查你没有写越界。你是 不做任何边界检查,如果你有超过 1000 个单词,你会溢出 缓冲区,如果单词超过 9 个字符,则溢出 缓冲区。
我会这样写:首先定义一个包含单词和 出场次数。为每个单词创建一个结构数组,当你 添加一个新词,你必须检查这个词是否已经存在。如果是,那么 将计数器加一,否则添加新单词并将其计数设置为 1。例如:
typedef struct word_count {
char *word;
size_t count;
} word_count;
int add_word(word_count **wc, size_t *len, const char *word)
{
if(wc == NULL || word == NULL || len == NULL)
return 0;
// empty list
if(*wc == NULL)
*len = 0;
// search for word
for(size_t i = 0; i < *len; ++i)
{
if(strcasecmp((*wc)[i].word, word) == 0)
{
(*wc)[i].count++;
return 1;
}
}
word_count *nwc = realloc(*wc, (*len + 1) * sizeof *nwc);
if(nwc == NULL)
return 0;
// creating copy of word
nwc[*len].word = strdup(word);
if(nwc->word == NULL)
return 0; // do not update *len
nwc[*len].count = 1;
*wc = nwc;
(*len)++;
return 1;
}
void free_words(word_count *wc, size_t len)
{
if(wc == NULL)
return;
for(size_t i = 0; i < len; ++i)
free(wc[i].word);
free(wc);
}
与add_word
我存储单词并同时计算它们。我先走
通过数组并检查单词是否已存储在数组中。在那里面
如果我只增加计数。如果这是一个新词,那么我重新分配
记忆多一个词并添加该词并将计数设置为 1.
现在您可以:
void foo(void)
{
size_t len = 0;
word_count *wc = NULL;
add_word(&wc, &len, "word1");
add_word(&wc, &len, "word2");
add_word(&wc, &len, "word3");
add_word(&wc, &len, "word2");
add_word(&wc, &len, "wORD1");
if(wc)
{
for(size_t i = 0; i < len; ++i)
printf("word: '%s', count: %zu\n", wc[i].word, wc[i].count);
}
free_words(wc, len);
}
你会得到:
word: 'word1', count: 2
word: 'word2', count: 2
word: 'word3', count: 1
然后统计单词的函数使用strtok
得到单词。 strtok
修改了源字符串,所以为了保留原来的内容,我做了
一份并在上面使用 strtok
。
word_count *get_word_counts(const char *file, size_t *len)
{
if(file == NULL || len == NULL)
return NULL;
word_count *wc = NULL;
*len = 0;
// I do a copy because strtok modifies the source
// preserving the original content
char *copy = strdup(file);
if(copy == NULL)
{
fprintf(stderr, "Not enough memory\n");
return NULL;
}
const char *delim = " \t,.\r\n!"; // \n to consume newlines as well
char *token = strtok(copy, delim);
do {
// if empty word
if(token[0] == 0)
continue;
if(add_word(&wc, len, token) == 0)
{
fprintf(stderr, "failed to add word '%s'\n", token);
free(copy);
return wc; // returning all words so far
}
} while((token = strtok(NULL, delim)));
free(copy);
return wc;
}
我将这些函数放在一起并创建了一个文本文件,其中包含您的问题 内容。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef struct word_count {
char *word;
size_t count;
} word_count;
int add_word(word_count **wc, size_t *len, const char *word)
{
if(wc == NULL || word == NULL || len == NULL)
return 0;
// empty list, create one
if(*wc == NULL)
*len = 0;
// search for word
for(size_t i = 0; i < *len; ++i)
{
if(strcasecmp((*wc)[i].word, word) == 0)
{
(*wc)[i].count++;
return 1;
}
}
word_count *nwc = realloc(*wc, (*len + 1) * sizeof *nwc);
if(nwc == NULL)
return 0;
nwc[*len].word = strdup(word);
if(nwc->word == NULL)
return 0; // do not update *len
nwc[*len].count = 1;
*wc = nwc;
(*len)++;
return 1;
}
void free_words(word_count *wc, size_t len)
{
if(wc == NULL)
return;
for(size_t i = 0; i < len; ++i)
free(wc[i].word);
free(wc);
}
long get_file_size(const char *filename)
{
if(filename == NULL)
return -1;
FILE *file = fopen(filename, "rb");
if(file == NULL)
{
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
return -1;
}
if(fseek(file, 0, SEEK_END) == -1)
{
fprintf(stderr, "Could not seek to the end: %s\n", strerror(errno));
fclose(file);
return -1;
}
long fsize = ftell(file);
fclose(file);
return fsize;
}
char *get_file(const char *filename, long *filesize)
{
if(filename == NULL)
return NULL;
long fs = get_file_size(filename);
if(fs == -1)
{
fprintf(stderr, "Could not calculate file size\n");
return NULL;
}
if(filesize)
*filesize = fs;
// I use calloc so that the buffer is [=17=]-terminated
char *res = calloc(1, fs + 1);
if(res == NULL)
return NULL;
FILE *fp = fopen(filename, "rb");
if(fp == NULL)
{
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
free(res);
fclose(fp);
return NULL;
}
if(fread(res, 1, fs, fp) != fs)
{
fprintf(stderr, "Could not get the whole file\n");
free(res);
fclose(fp);
return NULL;
}
fclose(fp);
return res;
}
word_count *get_word_counts(const char *file, size_t *len)
{
if(file == NULL || len == NULL)
return NULL;
word_count *wc = NULL;
*len = 0;
// I do a copy because strtok modifies the source
// preserving the original content
char *copy = strdup(file);
if(copy == NULL)
{
fprintf(stderr, "Not enough memory\n");
return NULL;
}
const char *delim = " \t,.\r\n!"; // \n to consume newlines as well
char *token = strtok(copy, delim);
do {
// if empty word
if(token[0] == 0)
continue;
if(add_word(&wc, len, token) == 0)
{
fprintf(stderr, "failed to add word '%s'\n", token);
free(copy);
return wc; // returning all words so far
}
} while((token = strtok(NULL, delim)));
free(copy);
return wc;
}
int cmp_count(const void *s1, const void *s2)
{
word_count *w1 = (word_count*) s1, *w2 = (word_count*) s2;
return strcasecmp(w1->word, w2->word);
}
int main(int argc, char **argv)
{
int ret = 0;
if(argc != 2)
{
fprintf(stderr, "usage: %s file\n", argv[0]);
return 1;
}
long fs = 0;
char *file = get_file(argv[1], &fs);
if(file == NULL)
return 1;
size_t len = 0;
word_count *wc = get_word_counts(file, &len);
if(wc == NULL)
{
fprintf(stderr, "failed to count words\n");
ret = 1;
len = 0;
}
// sorting words
if(wc)
qsort(wc, len, sizeof *wc, cmp_count);
for(size_t i = 0; i < len; ++i)
printf("word: '%s', count: %zu\n", wc[i].word, wc[i].count);
free_words(wc, len);
free(file);
return ret;
}
输出为:
word: 'a', count: 1
word: 'all', count: 2
word: 'also', count: 2
word: 'am', count: 2
word: 'and', count: 3
word: 'any', count: 2
word: 'appearances', count: 1
word: 'appreciated', count: 1
word: 'at', count: 1
word: 'be', count: 2
word: 'been', count: 1
word: 'best', count: 1
word: 'but', count: 2
word: 'C', count: 1
word: 'can't', count: 1
word: 'count', count: 4
...
请注意,我使用 strdup
创建单词和文件内容的副本。如果你的系统
没有strdup
,你可以用这个:
char *strdup(const char *text)
{
if(text == NULL)
return;
char *copy = malloc(strlen(text) + 1);
if(copy == NULL)
return NULL;
return strcpy(copy, text);
}
编辑
OP asked in the comment section
how would I go about sorting the file by having the biggest number of occurrences first?
您需要做的就是更改函数 cmp_count
或创建一个新函数
不同的比较。 qsort
传递一个指针
到需要比较的值,如果值,则必须 return 0
相等,如果左边的值较小则小于 0,如果左边的值较小则大于 0
左边的值更大。在降序的情况下,你必须交换符号,
这意味着如果左边的值更大,你 return 小于 0,并且
如果左边的值较小,则大于 0。
所以,如果你想按出现次数排序,你必须检查 w1->count
w2->count
.
int cmp_count_by_count_desc(const void *s1, const void *s2)
{
word_count *w1 = (word_count*) s1, *w2 = (word_count*) s2;
return w2->count - w1->count;
}
那么您必须将 main
中的 qsort
行更改为:
if(wc)
qsort(wc, len, sizeof *wc, cmp_count_by_count_desc);
运行 新排序的相同测试输入,我得到
word: 'to', count: 6
word: 'my', count: 6
word: 'I', count: 4
word: 'count', count: 4
word: 'the', count: 4
word: 'and', count: 3
word: 'have', count: 3
word: 'word', count: 3
word: 'work', count: 3
word: 'am', count: 2
word: 'in', count: 2
word: 'Functions', count: 2
word: 'any', count: 2
word: 'help', count: 2
word: 'would', count: 2
word: 'be', count: 2
word: 'but', count: 2
word: 'also', count: 2
word: 'of', count: 2
word: 'all', count: 2
word: 'it', count: 2
word: 'when', count: 2
word: 'new', count: 1
word: 'C', count: 1
word: 'been', count: 1
...