如何使用动态内存分配逐行打印文件?

时间:2017-05-06 20:44:36

标签: c

如何使用malloc逐行打印文件?理想情况下,我想分配足够的空间来保存文件中的一行,打印,释放它,然后重复该过程。

请包含代码段,谢谢!

这是我到目前为止所做的,但Valgrind说我有内存泄漏。

int main (int argc, char **argv)
{
    // char *line = NULL;
    char *line;

    FILE *fp = fopen(argv[1], "r");
    if (!fp) {
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    line = malloc(1);

    while (readline(fp, line)) {
        // printf("%s\n", line);
    }
    free(line);

    if (fp != stdin) fclose (fp);

    return  0;
}

char *readline (FILE *fp, char *buffer) 
{
    char ch;
    int place = 0;
    size_t nchar = 1;

    ch = fgetc(fp);
    while (ch != '\n' && ch != EOF)
    {
        nchar++;
        (buffer)[place] = ch;

        char *tmp = realloc (buffer, nchar);
        if (!tmp) {
            fprintf (stderr, "error: realloc failed, "
                            "returning partial buffer.\n");
            (buffer)[place] = 0;
            return buffer;
        }
        buffer = tmp;

        ch = fgetc(fp);
        place++;
    }
    (buffer)[place] = '\0'; /* nul-terminate */

    if (ch == EOF) {
        if (strlen(buffer) > 1) {
            printf("%s\n", buffer);
        }

        // free(buffer);
        buffer = NULL;
    } else {

        if (strlen(buffer) > 1) {
            printf("%s\n", buffer);
        }
    }

    return buffer;
}

1 个答案:

答案 0 :(得分:0)

我就是这样做的:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/******************************************************************************
** Read a line from specified stream into allocated memory.
**   (Caller is responsable to free the allocated memory).
**
** Parameters:
**    I__fp       File stream to read.
**    _O_line_A   Sets caller's pointer to the allocated memory containing the read line.
**                Caller's pointer is set to NULL if a blank line is encountered.
**    _O_eof      Sets caller's integer value as follows:
**                   0 = (FALSE) More lines available to read from file.
**                  -1 = (TRUE)  The end-0f-file was encountered while reading the line.
** Return values:
**    0           Call was successful.
**    ENOMEM      Could not allocate sufficient memory to read a line.
*/
int ReadLine(
      FILE  *I__fp,
      char **_O_line_A,
      int   *_O_eof       
      )
   {
   int    rCode      = 0;      /* Function return status.  0=SUCCESS. */
   char  *line_A     = NULL;   /* Pointer to allocated memory containing line read. */
   size_t lineLength = 0;      /* Length of the allocated line, not including the termination character. */
   int    eof        = 0;      /* End-of-file encountered flag. */

   for(;;)                     /* Loop forever. */
      {
      int ch;
      char *newmem;

      ch=fgetc(I__fp);         /* Read a single character from the stream. */
      if(EOF == ch)            /* If the value EOF was read... */
         {
         eof=(-1);             /* ...Set the end-of-file flag */
         break;                /* ...Break out of the for-loop */
         }

      if('\n' == ch)           /* If a new-line character was read... */
         break;                /* ...Break out of the for-loop */

      /* Allocate additional memory, sufficient to hold all characters so far read,
      **    plus one for the currently read character,
      **       plus one for the termination character.
      */
      newmem=realloc(line_A, lineLength + 1 + 1);
      if(!newmem)             /* Ensure that realloc() did not fail. */
         {
         rCode=ENOMEM;
         goto CLEANUP;
         }

      line_A = newmem;             /* Change to newly allocated memory. */
      line_A[lineLength++] = ch;   /* Append the newly read character to the allocated memory. */ 
      line_A[lineLength] = '\0';   /* Append a string termination character to the allocated memory. */
      };

//RESULTS:

   /* Set the caller's pointer to the allocated line read from the stream. */
   if(_O_line_A)        /* Allows the caller to pass in a NULL value for _O_line_A...   */
      {                 /* ...For example, if the content of the line is not wanted by the caller. */
      *_O_line_A = line_A;
      line_A = NULL;
      }

    /* Set the caller's eof flag. */
    if(_O_eof)          /* Allows the caller to pass in a NULL value for _O_eof... */
      *_O_eof = eof;    /* ...For example, if the caller doesn't need the eof value. */

CLEANUP:

   /* It is possible that the caller supplied a "NULL" value for _O_line_A.
   ** ...If so, line_A will not be NULL.\
   ** ...In that case, free line_A to eliminate potential memory leak.
   */
   if(line_A)
      free(line_A);

   return(rCode);
   }

/******************************************************************************
** Program start.
*/
int main(
      int    argc,
      char **argv)
   {
   int   rCode  = 0;   
   char *line_A = NULL;
   FILE *fp_A   = NULL;
   int   eof; 

   errno=0;   
   fp_A = fopen(argv[1], "r");
   if(!fp_A)
      {
      fprintf(stderr, "fopen(\"%s\") failed. errno: %d %s\n", argv[1], errno, strerror(errno));
      goto CLEANUP;
      }

   rCode=ReadLine(fp_A, &line_A, &eof);         /* Read first line from stream. */
   while(!rCode)
      {
      printf("%s\n", line_A ? line_A : "");
      free(line_A);                            /* Free line memory when finished with it. (after printing, etc.) */
      if(eof)                                  /* Break out of the while-loop if this is the last line in the stream. */
         break;

      rCode=ReadLine(fp_A, &line_A, &eof);      /* Read next line from stream. */
      }

   if(rCode)
      fprintf(stderr, "ReadLine() reports: %d %s\n", errno, strerror(errno));

CLEANUP:

   if(fp_A && (fp_A != stdin))
      {
      errno=0;
      if(EOF == fclose(fp_A))
         fprintf(stderr, "fclose() failed.  errno: %d %s\n", errno, strerror(errno));
      }

   return(rCode);
   }