C 打印文件中重复出现的前10个单词
编辑问题: 大家好,我的目标是打印一个文件中出现的前10个单词,从读取文件到计算单词出现次数并打印它,我已经设法让一切都正常工作,但是当我实现qsort时,我遇到了一个错误。我看了一下我的指针,它们看起来很好,如果有任何反馈,我将不胜感激C 打印文件中重复出现的前10个单词,c,file,io,segmentation-fault,C,File,Io,Segmentation Fault,编辑问题: 大家好,我的目标是打印一个文件中出现的前10个单词,从读取文件到计算单词出现次数并打印它,我已经设法让一切都正常工作,但是当我实现qsort时,我遇到了一个错误。我看了一下我的指针,它们看起来很好,如果有任何反馈,我将不胜感激 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #define MAX 51 struct words
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 51
struct words
{
char *ch;
int index;
struct words *pNext;
};
struct words* createWordCounter(char *ch)
{
struct words *pCounter = NULL;
pCounter = (struct words*)malloc(sizeof(char));
pCounter->ch = (char*)malloc(strlen(ch)+1);
strcpy(pCounter->ch, ch);
pCounter->index = 1;
pCounter->pNext = NULL;
return pCounter;
}
struct words *pStart = NULL;
char* removePunc(struct words* ch)
{
char *src = ch, *dst = ch;
while (*src)
{
if (ispunct((unsigned char)*src))
{
src++;
}
else if (isupper((unsigned char)*src))
{
*dst++ = tolower((unsigned char)*src);
src++;
}
else if (src == dst)
{
src++;
dst++;
}
else
{
*dst++ = *src++;
}
}
*dst = 0;
}
void addWord(char *word)
{
struct words *pCounter = NULL;
struct words *pLast = NULL;
if(pStart == NULL)
{
pStart = createWordCounter(word);
return;
}
pCounter = pStart;
while(pCounter != NULL)
{
if(strcmp(word, pCounter->ch) == 0)
{
++pCounter->index;
return;
}
pLast = pCounter;
pCounter = pCounter->pNext;
}
pLast->pNext = createWordCounter(word);
}
void printWord(struct words *pCounter)
{
printf("\n%-30s %5d\n", pCounter->ch, pCounter->index);
}
//sort
int compare (const void * a, const void * b){
struct words *A1 = (struct words *)a;
struct words *B1 = (struct words *)b;
return B1->index - A1->index;
/*
if ((A1->count - B1->count) > 0)
return -1;
else if ((A1->count - B2->count) < 0)
return 1;
else
return 0;
*/
}
int main(int argc, char * argv[])
{
struct words *pCounter = NULL;
char temp[MAX];
FILE *fpt;
if(argc == 2)
{
printf("File name is: %s\n",argv[1]);
fpt = fopen(argv[1], "r");
//fail test
if(fpt == NULL)
{
printf("cannot open file, exiting program...\n");
exit(0);
}
//get the data out of the file and insert in struct
int wordCounter = 0;
int i = 0;
int lines = 0;
while((fscanf(fpt, "%s ", &temp)) == 1)
{
removePunc(temp);
addWord(temp);
if(temp == ' ')
i++;
if(temp == '\n')
lines++;
wordCounter++;
}
/*
pCounter = pStart;
while(pCounter != NULL)
{
printWord(pCounter);
pCounter = pCounter->pNext;
}
*/
//sort
qsort(pCounter, wordCounter, sizeof(struct words), compare);
for(int j = 0; i < 10; i++)
{
printWord(pCounter);
}
}
fclose(fpt);
return 0;
}
#包括
#包括
#包括
#包括
#定义最大值51
结构词
{
char*ch;
整数指数;
结构词*pNext;
};
结构字*createWordCounter(字符*ch)
{
结构字*pCounter=NULL;
pCounter=(结构字*)malloc(sizeof(char));
pCounter->ch=(char*)malloc(strlen(ch)+1);
strcpy(pCounter->ch,ch);
pCounter->index=1;
pCounter->pNext=NULL;
返回pccounter;
}
结构字*pStart=NULL;
char*removePunc(结构词*ch)
{
char*src=ch,*dst=ch;
while(*src)
{
if(ispunct((无符号字符)*src))
{
src++;
}
else if(isupper((无符号字符)*src))
{
*dst++=tolower((无符号字符)*src);
src++;
}
否则如果(src==dst)
{
src++;
dst++;
}
其他的
{
*dst++=*src++;
}
}
*dst=0;
}
void addWord(char*word)
{
结构字*pCounter=NULL;
结构字*pLast=NULL;
if(pStart==NULL)
{
pStart=createWordCounter(字);
返回;
}
pCounter=pStart;
while(pCounter!=NULL)
{
if(strcmp(字,计数->通道)==0)
{
++pCounter->index;
返回;
}
pLast=pCounter;
pCounter=pCounter->pNext;
}
pLast->pNext=createWordCounter(word);
}
无效打印字(结构字*pCounter)
{
printf(“\n%-30s%5d\n”,pCounter->ch,pCounter->index);
}
//分类
整数比较(常数无效*a,常数无效*b){
结构词*A1=(结构词*)a;
结构词*B1=(结构词*)b;
返回B1->index-A1->index;
/*
如果((A1->count-B1->count)>0)
返回-1;
如果((A1->count-B2->count)<0,则为else
返回1;
其他的
返回0;
*/
}
int main(int argc,char*argv[])
{
结构字*pCounter=NULL;
字符温度[MAX];
文件*fpt;
如果(argc==2)
{
printf(“文件名为:%s\n”,argv[1]);
fpt=fopen(argv[1],“r”);
//失败测试
如果(fpt==NULL)
{
printf(“无法打开文件,正在退出程序…\n”);
出口(0);
}
//从文件中取出数据并插入到struct中
int字计数器=0;
int i=0;
int行=0;
而((fscanf(fpt,%s,&temp))==1)
{
移除PUNC(温度);
addWord(temp);
如果(温度=“”)
i++;
如果(临时=='\n')
行++;
wordCounter++;
}
/*
pCounter=pStart;
while(pCounter!=NULL)
{
打印字(pCounter);
pCounter=pCounter->pNext;
}
*/
//分类
qsort(pCounter,wordCounter,sizeof(struct words),compare);
对于(int j=0;i<10;i++)
{
打印字(pCounter);
}
}
fclose(fpt);
返回0;
}
我认为当您尝试使用fscanf时,主要问题是临时数组的大小
while((fscanf(fpt, "%s ", temp)) == 1)
当一条线的长度大于最大值时,会发生分段错误
您可以像这样更改代码
#define SCANF_LEN2(x) #x
#define SCANF_LEN(x) SCANF_LEN2(x)
//...
//your original code
//...
while((fscanf(fpt, "%"SCANF_LEN(MAX)"s ", temp)) == 1)
顺便说一下,你应该检查一下
(1) 编译关于类型的警告
char*removePunc(结构词*ch)
应该是char*removePunc(char*ch)
if(temp='')
应该是if(temp[0]='')
if(temp=='\n')
应该是if(temp[0]='\n')
(2) 马洛克大小
pCounter=(结构词*)malloc(sizeof(char))代码>应该是pCounter=(struct words*)malloc(sizeof(struct words))代码>
(3) 记住使用malloc后的free我认为主要问题是在尝试使用fscanf时临时数组的大小
while((fscanf(fpt, "%s ", temp)) == 1)
当一条线的长度大于最大值时,会发生分段错误
您可以像这样更改代码
#define SCANF_LEN2(x) #x
#define SCANF_LEN(x) SCANF_LEN2(x)
//...
//your original code
//...
while((fscanf(fpt, "%"SCANF_LEN(MAX)"s ", temp)) == 1)
顺便说一下,你应该检查一下
(1) 编译关于类型的警告
char*removePunc(结构词*ch)
应该是char*removePunc(char*ch)
if(temp='')
应该是if(temp[0]='')
if(temp=='\n')
应该是if(temp[0]='\n')
(2) 马洛克大小
pCounter=(结构词*)malloc(sizeof(char))代码>应该是pCounter=(struct words*)malloc(sizeof(struct words))代码>
(3) 记住使用malloc后的free首先temp
已经是一个指针,所以不要在fscanf
中包含'&
。其次,不要忽略缓冲区大小(例如#define MAX 1024
)。第三,使用字段宽度修饰符保护数组边界,不要在格式字符串中添加尾随空格
把它放在一起(假设您使用1024作为MAX
,您可以使用
fscanf(fpt, "1023%s", temp))
在阅读过程中检查fscanf
的返回做得很好。首先temp
已经是一个指针,所以不要在fscanf
之前包含'&
。其次,不要忽略缓冲区大小(例如\define MAX 1024
).第三,使用字段宽度修饰符保护数组边界,不要在格式字符串中添加尾随空格
把它放在一起(假设您使用1024作为MAX
,您可以使用
fscanf(fpt, "1023%s", temp))
在阅读过程中检查fscanf
的返回情况做得很好。添加了前面提到的内容
在createWordCounter(…)
您正在为字符
分配内存。即使指向结构的指针是指向其第一个成员的指针,但单词
的第一个元素是指向字符的指针。最好小心编写
struct words *pCounter = malloc(sizeof *pCounter);
此外,请注意运算符优先级。
在addWord(…)
中,您有
++pCounter->index;
这样做的目的是在访问索引之前增加指针pCounter