2017-05-06 28 views
1

如何使用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; 
} 
+3

您是否嘗試過什麼了嗎?如果是這樣,你失敗了什麼?如果他們看到一些努力,人們會更願意提供幫助。 – HolyBlackCat

+3

這是一個家庭作業,指示以某種方式做事嗎?如果沒有,「逐行打印」和「直到你看到它打印每個字符」之間有什麼區別,直到EOF。由於「\ n」是一個字符,因此它在某種意義上也會打印*行*,並且不需要任何內存分配。 – Telemachus

+1

'malloc()'不打印。你打算怎麼讀線條? ['fgets()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fgets.html), ['getline()'](http://pubs.opengroup.org/onlinepubs/ 9699919799/functions/getline.html),別的?你是否擔心來自終端(或FIFO或管道或其他非磁盤文件源)的信息? –

回答

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); 
    }