简体   繁体   English

最后一个字符未打印到文件

[英]The last character is not printed to a file

I am trying to figure out why using C function strtok is not working properly for me. 我试图弄清楚为什么使用C函数strtok对我来说无法正常工作。 Here's the problem: I have a file which contains two types of information: headers and text descriptions. 问题出在这里:我有一个文件,其中包含两种类型的信息:标题和文本描述。 Each line in the file is either a header or part of a text description. 文件中的每一行都是标题或文本描述的一部分。 A header starts with '>'. 标头以“>”开头。 The description text follows the header and can span multiple lines. 描述文本位于标题之后,可以跨越多行。 At the end of the text there is an empty line which separates the description from the next header. 文本末尾有一个空行,用于将描述与下一个标题分开。 My aim is to write two separate files: one contains the headers on each line and the other contains the corresponding description on a line by itself. 我的目的是编写两个单独的文件:一个文件包含每一行的标题,另一个文件本身包含一行的相应描述。 To implement the codes in C, I used fgets to read the file one line at a time into dynamically allocated memory. 为了用C语言实现代码,我使用fgets一次将文件读取一行到动态分配的内存中。 In order to write the description text on one single line, I used `strtok to get rid of any new line characters exists in the text. 为了将描述文本写在一行上,我使用了`strtok来消除文本中存在的任何新行字符。

My code is working properly for the header files. 我的代码对于头文件正常工作。 However, for the descriptions file, I noticed that the last character of the text is not printed out to the file even though it is printed to the stdout. 但是,对于描述文件,我注意到即使将文本最后一个字符打印到标准输出,也不会将其打印到文件中

FILE *headerFile = fopen("Headers", "w"); //to write headers
FILE *desFile = fopen("Descriptions", "w"); //to write descriptions

FILE *pfile = fopen("Data","r");

if ( pfile != NULL )
{

  int numOfHeaders =0;

  char **data1 = NULL; //an array to hold a header line
  char **data2 = NULL; //an array to hold a description line 
  char line[700] ; //maximum size for the line

  while (fgets(line, sizeof line, pfile ))
  {

      if(line[0] =='>') //It is a header
      {
          data1 = realloc(data1,(numOfHeaders +1)* sizeof(*data1));
          data1[numOfHeaders]= malloc(strlen(line)+1);
          strcpy(data1[numOfHeaders],line);

          fprintf(headerFile, "%s",line);//writes the header

          if(numOfHeaders >0)
            fprintf(desFile, "\n");//writes a new line in the desc file

          numOfHeaders++;              
      }

      //it is not a header and not an empty line
      if(line[0] != '>' && strlen(line)>2)
      {
          data2 = realloc(data2,(numOfHeaders +1)* sizeof(*data2));
          data2[numOfHeaders]= malloc(strlen(line)+1);

          char *s  = strtok(line, "\n ");              
          strcpy(data2[numOfHeaders],s);

          fprintf(desFile, "%s",data2[numOfHeaders]);              
          printf(desFile, "%s",data2[numOfHeaders]);
       }

  } //end-while
  fclose(desFile);
  fclose(headerFile);
  fclose(pfile );

  printf("There are %d headers in the file.\n",numOfHeaders);

}

As mentioned in the comments: 如评论中所述:

  fprintf(desFile, "%s",data2[numOfHeaders]);  //okay            
  printf(desFile, "%s",data2[numOfHeaders]);  //wrong  

Second line should be: 第二行应为:

  printf("%s",data2[numOfHeaders]);  //okay

Or, you could do this: 或者,您可以这样做:

  sprintf(buffer, "%s",data2[numOfHeaders]);
  fprintf(desFile, buffer);
  printf(buffer);    

Other possible issues : 其他可能的问题
Without an input file it is not possible to know for certain what strtok() is doing, but here is a guess based on what you have described: 没有输入文件,就不可能确定strtok()在做什么,但这是基于您所描述的猜测:

In these two lines : 在这两行中

  data2[numOfHeaders]= malloc(strlen(line)+1);

  char *s  = strtok(line, "\n ");          

if the string contained in data2 has any embedded spaces, s will only contain the segment occurring before that space. 如果data2中包含的字符串具有任何嵌入的空格,则s将仅包含该空格之前的段。 And because you are only calling it once before line gets refreshed: 并且因为您仅在刷新之前调用它一次:

while (fgets(line, sizeof line, pfile ))  

only one token (the very first segment) will be read. 仅读取一个令牌(第一段)。

Not always, but Normally , strtok() is called in a loop: 并非总是如此,但通常在循环中调用strtok()

char *s = {0};
s= strtok(stringToParse, "\n ");//make initial call before entering loop
while(s)//ALWAYS test to see if s contains new content, else NULL
{
    //do something with s
    strcpy(data2[numOfHeaders],s);
    //get next token from string
    s = strtok(NULL, "\n ");//continue to tokenize string until s is null
}

But, as I said above, you are calling it only once on that string before the content of the string is changed. 但是,正如我上面所说,在更改字符串的内容之前,您只能在该字符串上调用一次。 It is possible then, that the segment not printing has simply not yet been tokenized by strtok() . 这样就有可能未打印的段尚未被strtok()标记。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM