0
#include<stdio.h>
#include<stdlib.h>
#include<dirent.h>
#include<string.h>

int main()
{
  FILE *fin,*fout;
  char dest[80]="/home/vivs/InexCorpusText/";
  char file[30];
  DIR *dir;
  char c,state='1';
  int len;
  struct dirent *ent;
  if((dir=opendir("/home/vivs/InexCorpus"))!=NULL)
  {
    while((ent=readdir(dir))!=NULL)
    {
      if(strcmp(ent->d_name,".") &&
         strcmp(ent->d_name,"..") &&
         strcmp(ent->d_name,".directory"))
      {
        len=strlen(ent->d_name);
        strcpy(file,ent->d_name);
        file[len-3]=file[len-1]='t';
        file[len-2]='x';
        //strcat(source,ent->d_name);
        strcat(dest,file);
        printf("%s\t%s\n",ent->d_name,dest);
        fin=fopen(ent->d_name,"r");
        fout=fopen(dest,"w");
        while((c=fgetc(fin))!=EOF)
        {
          if(c=='<')
          {
            fputc(' ',fout);
            state='0';
          }
          else if(c=='>')
            state='1';
          else if(state=='1')
          {
            if(c!='\n')
            fputc(c,fout);
            if(c=='.')
            {
              c=fgetc(fin);
              if(c==' '||c=='\n'||c=='<')
              {
                fputc('\n',fout);
                ungetc(c,fin);
              }
              else fputc(c,fout);
            }
          }
        }
      }
      close(fin);
      close(fout);
      strcpy(dest,"/home/vivs/InexCorpusText/");
    }
    closedir(dir);
  }
  else
  {
    printf("Error in opening directory\n");
  }
  return 0;
}

我试图将 xml 文件转换为文本。这段代码只是删除标签而已。当我对大约 300 个文件执行此代码时,它没有显示任何错误,但是当数字达到 500 或更多时,我在处理大约 300 个文件后收到分段错误。

4

3 回答 3

2

“从一开始”至少有一个原因:

这是struct dirent男人的声明:

   On Linux, the dirent structure is defined as follows:

       struct dirent {
           ino_t          d_ino;       /* inode number */
           off_t          d_off;       /* offset to the next dirent */
           unsigned short d_reclen;    /* length of this record */
           unsigned char  d_type;      /* type of file; not supported
                                          by all file system types */
           char           d_name[256]; /* filename */
       };

您在任何超过 30 个(实际上是 29 个)字符的名称上都会遇到麻烦。发生内存覆盖是因为文件只有 30 个字节(为 '\0' 终止符保留 1):

char file[30];
...
strcpy(file,ent->d_name);
于 2013-03-22T19:07:52.293 回答
1

XML 中有两种结构,您似乎没有考虑到这些结构。

  1. 属性内容可以包含未转义>的字符,这可能会影响您的计数。请参阅http://www.w3.org/TR/REC-xml/#NT-AttValue

  2. CDATA 部分可以同时包含<>字符作为文字文本,只要它们不作为结束]]>字符串的一部分出现。请参阅http://www.w3.org/TR/REC-xml/#NT-CharData。这可能会严重偏离您的逻辑。

您为什么不查看文件以查看是否包含文本CDATA

您可能要考虑使用xsltproc 或 libxslt;一个非常简单的 XSLT 转换将给你你想要的。有关此类转换引擎,请参阅使用 XSLT 将 XML 文件的一部分提取为纯文本。

于 2013-03-23T10:12:42.923 回答
0

好的,另一个有问题的地方:

len=strlen(ent->d_name);
....
file[len-3]=file[len-1]='t';
file[len-2]='x';

因为d_name可能少于 3 个字符,它可能再次导致内存覆盖。您应该小心使用类似的函数strlen()并始终验证它们的结果。

于 2013-03-23T09:47:14.540 回答