C 打印文件中重复出现的前10个单词

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

编辑问题: 大家好,我的目标是打印一个文件中出现的前10个单词,从读取文件到计算单词出现次数并打印它,我已经设法让一切都正常工作,但是当我实现qsort时,我遇到了一个错误。我看了一下我的指针,它们看起来很好,如果有任何反馈,我将不胜感激

#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