在C代码中创建输出字数、不同字数和最常用字数的代码
我需要编写代码来读取文本文件并输出字数、不同字数和C中最常用的字数 我已经完成了输出单词数量的代码,但是我不知道如何找到不同单词的数量或最常见的单词。我知道我应该用strcmp,但我不知道怎么做。任何帮助都将不胜感激。这是我到目前为止所拥有的在C代码中创建输出字数、不同字数和最常用字数的代码,c,C,我需要编写代码来读取文本文件并输出字数、不同字数和C中最常用的字数 我已经完成了输出单词数量的代码,但是我不知道如何找到不同单词的数量或最常见的单词。我知道我应该用strcmp,但我不知道怎么做。任何帮助都将不胜感激。这是我到目前为止所拥有的 int main(int argc, char *argv[]) { int number=0; char temp[25000][50]; char word[25000][50]; char *word2[25000][
int main(int argc, char *argv[])
{
int number=0;
char temp[25000][50];
char word[25000][50];
char *word2[25000][50];
int wordCount=0;
int distinctCount=0;
FILE *fp;
//reads file!
fp = fopen("COEN12_LAB1.txt", "r");
if(fp == NULL)
{
printf("File Missing!\n");
return 0;
}
//counts words in file!
while(fscanf(fp,"%s", word) == 1)
wordCount++;
printf("Total number of words: %d\n", wordCount);
fclose(fp);`
}
首先,您可能需要实现一种结构,该结构允许您有效地保留不同的单词。是可能的(也许是最好的)之一 下面是在C上实现和使用哈希的示例:
您还可以研究这个问题:我为您编写了程序,请参阅此处的源代码: 当然,没有检查特殊情况,像单行上的很多字, 不同的单词数量>16000,等等。但是,您可以获得基本代码: 运行示例:
$ cat aaa.txt
aaa
bbb
ccc
aaa
xxx
aaa
cc
$ cc words.c ; ./a.out aaa.txt
1 xxx
1 ccc
1 bbb
1 cc
3 aaa
[编辑]1.将malloc替换为calloc(将内存初始化为0)
2.替换qsort中的第二个参数
3.该程序现在可以处理范围更广的文件(更多的字,更多的分隔符) 这并不漂亮,可能需要一些小的调试,但它会让您开始计算不同的和最常用的单词的数量:
#include <ansi_c.h>
#include <stdio.h>
#define FILENAME "c:\\dev\\play\\test3.txt" //put your own path here
#define DELIM "- .,:;//_*&\n"
int longestWord(char *file, int *cnt);
void allocMemory(int numStrings, int max);
void freeMemory(int numStrings);
static int sortstring( const void *str1, const void *str2 );
char **strings;
int main()
{
int wc, longest, cnt, distinct, i, mostFreq, mostFreqKeep=0;
char line[260];
char *buf=0;
FILE *fp;
longest = longestWord(FILENAME, &wc);
char wordKeep[longest];
allocMemory(wc, longest);
//read file into string arrays
fp = fopen(FILENAME, "r");
cnt=0;
while(fgets(line, 260, fp))
{
buf = strtok(line, DELIM);
while(buf)
{
if((strlen(buf) > 0) && (buf[0] != '\t') && (buf[0] != '\n') && (buf[0] != '\0')&& (buf[0] > 0))
{
strcpy(strings[cnt], buf);
cnt++; //use as accurate count of words.
}
buf = strtok(NULL, DELIM);
}
}
fclose(fp);
//now get most frequent word
//sort
qsort(strings, cnt, sizeof(char*), sortstring);
distinct = 1;
mostFreq = 1; //every word will occur once
wordKeep[0]=0;
for(i=0;i<cnt-1;i++)
{
//depends on a successful sort (alphabetization)
if(strlen(strings[i]) >0)
{
if(strcmp(strings[i], strings[i+1]) == 0)
{
mostFreq++;
if(mostFreq > mostFreqKeep)
{
strcpy(wordKeep, strings[i]);
mostFreqKeep = mostFreq;
}
}
else
{
mostFreq = 1;
distinct++;
}
}
}
printf("number of words: %d\nNumber of distinct words:%d\nmost frequent word: %s - %d\n", cnt, distinct, wordKeep, mostFreqKeep);
freeMemory(cnt);
getchar();
return 0;
}
int longestWord(char *file, int *nWords)
{
FILE *fp;
int cnt=0, longest=0, numWords=0;
char c;
fp = fopen(file, "r");
while ( (c = fgetc ( fp) ) != EOF )
{
if ( isalpha ( c ) ) cnt++;
else if ( ( ispunct ( c ) ) || ( isspace ( c ) ) )
{
(cnt > longest) ? (longest = cnt, cnt=0) : (cnt=0);
numWords++;
}
}
*nWords = numWords;
fclose(fp);
return longest+1;
}
void allocMemory(int numStrings, int max)
{
int i;
strings = calloc(sizeof(char*)*(numStrings+1), sizeof(char*));
for(i=0;i<numStrings; i++)
{
strings[i] = calloc(sizeof(char)*max + 1, sizeof(char));
}
}
void freeMemory(int numStrings)
{
int i;
for(i=0;i<numStrings; i++)
if(strings[i]) free(strings[i]);
free(strings);
}
static int sortstring( const void *str1, const void *str2 )
{
const char *rec1 = *(const char**)str1;
const char *rec2 = *(const char**)str2;
int val = strcmp(rec1, rec2);
return val;
}
#包括
#包括
#定义文件名“c:\\dev\\play\\test3.txt”//在此处放置您自己的路径
#定义DELIM“-,:;/*&\n”
int longestWord(字符*文件,int*cnt);
无效allocMemory(整数字符串,整数最大值);
void freemory(int numStrings);
静态int排序字符串(常量无效*str1,常量无效*str2);
字符**字符串;
int main()
{
int wc,longest,cnt,distinct,i,mostFreq,mostFreqKeep=0;
字符行[260];
char*buf=0;
文件*fp;
最长=最长单词(文件名,&wc);
字符字保持[最长];
allocMemory(wc,最长);
//将文件读入字符串数组
fp=fopen(文件名,“r”);
cnt=0;
而(fgets(第260行,fp))
{
buf=strtok(直线,DELIM);
while(buf)
{
如果((strlen(buf)>0)&&(buf[0]!='\t')&&(buf[0]!='\n')&&(buf[0]!='\0')&&(buf[0]>0))
{
strcpy(字符串[cnt],buf);
cnt++;//用作精确的字数。
}
buf=strtok(NULL,DELIM);
}
}
fclose(fp);
//现在获取最频繁的单词
//分类
qsort(字符串、cnt、sizeof(char*)、sortstring);
独特=1;
mostFreq=1;//每个字只出现一次
字保持[0]=0;
对于(i=0;i0)
{
if(strcmp(strings[i],strings[i+1])==0)
{
mostFreq++;
如果(mostFreq>mostFreq保持)
{
strcpy(wordKeep,strings[i]);
mostFreqKeep=mostFreq;
}
}
其他的
{
mostFreq=1;
独特的++;
}
}
}
printf(“字数:%d\n不同字数:%d\n最常使用的字数:%s-%d\n”,cnt,distinct,wordKeep,mostFreqKeep);
自由存储器(cnt);
getchar();
返回0;
}
int longestWord(字符*文件,int*nWord)
{
文件*fp;
int cnt=0,最长=0,numWords=0;
字符c;
fp=fopen(文件“r”);
而((c=fgetc(fp))!=EOF)
{
if(isalpha(c))cnt++;
如果((ispunct(c))| |(isspace(c)))
{
(cnt>最长)?(最长=cnt,cnt=0):(cnt=0);
numWords++;
}
}
*nWords=numWords;
fclose(fp);
返回最长+1;
}
无效allocMemory(整数字符串,整数最大值)
{
int i;
strings=calloc(sizeof(char*)*(numStrings+1),sizeof(char*);
例如(i=0;i您可以使用一个简单的数据库来计算输入文本的不同字数。为了简单起见,我建议使用。下面我添加了一些示例代码(为了简洁起见,我省略了错误处理)
对于读取单词,我采用了使用fgets
将单行读入缓冲区的方法。我注意到,只要您能够保证缓冲区始终足够大,以容纳输入文件中的实际行,这种方法就可以很好地工作。否则,单词将在缓冲区的末尾拆分,这需要以某种方式进行处理
在解析文本时,我使用了strtok
。在实现过程中,我了解到很难正确使用单词分隔符。除此之外,这种方法完全忽略了可能的拼写差异(例如,大写)和其他相等单词的拼写差异,因此可能会对结果产生负面影响
一旦数据进入数据库,查询语言非常适合制定查询以获得最大值(不同)因此,当您想从输入文本计算多个统计信息时,我认为这种灵活的方法具有优势,因为您不必在C中实现每个特殊情况。为了进行测试,我将a复制到文件words.txt
下面是一个例子:
#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
#define DELIM " \r\n\t,.-;:_#+*\\=)(/&%$§\"“”!1234567890}][{'"
#define BUFSIZE 4096
#define SQLSIZE 256
int print_row(void* p, int ncols, char **values, char **names) {
for (int i = 0; i < ncols; i++)
printf("| %15s : %15s %s", names[i], values[i], i<ncols-1?"":"|\n");
return 0;
}
int main(int argc, char * argv[]) {
/* open infile */
FILE * infile = fopen("words.txt", "r");
/* initialize database */
sqlite3 *db_handle = 0;
sqlite3_open(":memory:", &db_handle);
sqlite3_exec(db_handle, "CREATE TABLE word (word TEXT);", 0, 0, 0);
/* parse file, populate db */
char buf[BUFSIZE], sql[SQLSIZE], *word;
while(fgets(buf, BUFSIZE, infile))
for (word = strtok(buf, DELIM); word != 0; word = strtok(0, DELIM)) {
snprintf(sql, SQLSIZE, "INSERT INTO word VALUES ('%s');", word);
sqlite3_exec(db_handle, sql, 0, 0, 0);
}
/* count of words */
sqlite3_exec(db_handle,
"SELECT COUNT(word) AS total_words FROM word;",
print_row, 0, 0);
/* count of distinct words */
sqlite3_exec(db_handle,
"SELECT COUNT(DISTINCT word) AS distinct_words FROM word;",
print_row, 0, 0);
/* top five most frequent words */
sqlite3_exec(db_handle,
"SELECT word, COUNT(*) AS count FROM word "
"GROUP BY word ORDER BY count DESC LIMIT 5;",
print_row, 0, 0);
sqlite3_close(db_handle);
}
供参考:
某种地图数据结构将是最好的解决方案,如果没有这种解决方案,您将需要一个与word
数组大小相同的int
数组,并且每次您阅读一个新词时,您都必须在word
数组中循环,并用strcmp()检查每个数组
查看是否已找到它。如果未找到,请添加一个新词。如果已找到,请将int
数组中的相应元素增加1。这显然是一种效率极低的方法。这是一个自动分配的大量存储空间。查找并阅读有关fgets()和strtok()的信息,以读取文件并将行解析为字符串(单词)。然后阅读关于strstr的文章(
$ gcc test.c -std=c99 -lsqlite3 && ./a.out
| total_words : 561 |
| distinct_words : 314 |
| word : SQLite | count : 17 |
| word : is | count : 16 |
| word : the | count : 15 |
| word : a | count : 14 |
| word : to | count : 12 |