连接从命令行传递的多个文件的内容

Concatenating the contents of multiple files passed from command line

我正在尝试连接执行代码时传递的所有 argv[] 参数的内容。这里的计数与argc相同。 **文件包含 argv.

char *merge_everything(int count, char **files) {
        size_t size = 0;
        char *buf = NULL;
        buf = malloc((size + 1) * sizeof(*buf)); /* size + 1 byte for the [=10=] */
        if (buf == NULL) {
            printf("MALLOC ERROR\n");
            exit(1);
        }
        char *temp = buf;
    
        for (int i = 0; i < count - 1; i++) {
            FILE *f = fopen(files[i], "rb");
    
            fseek(f, 0, SEEK_END);
            long bytes = ftell(f);
            fseek(f, 0, SEEK_SET);
    
            fread(temp, (size_t) bytes, 1, f);
            temp += bytes;
            fclose(f);
        }
        *temp = 0;
        free(buf); //If I don't free buf here then memory leak? If I do temp has null?
        return temp; //temp has all the concatenated stuff
    }

我进退两难,最后释放 buf 是在 return 语句之前。 请帮我纠正一下方法。 我热衷于使用缓冲区(通过 malloc)而不是将其写入新文件。因此,这种方法。

  1. 您分配了 1 个字节并阅读了大量内容。这是未定义的行为。
  2. 您需要增加为每个文件分配的内存大小。
  3. 您应该检查文件 I/O 个错误。
  4. 我不知道为什么 count-1 但也许你有你的理由。
char *merge_everything(int count, char **files) {
        size_t size = 0;
        long bytes;
        char *buf = NULL, *temp;

        for (int i = 0; i < count - 1; i++) {
            FILE *f = fopen(files[i], "rb");
    
            fseek(f, 0, SEEK_END);
            bytes = ftell(f);
            fseek(f, 0, SEEK_SET);

            
            temp = realloc(buf, size + bytes);
            if(!temp)
            {
                free(buf);
                break;
            }
            buf = temp;
    
            fread(buf + size, (size_t) bytes, 1, f);
            size += bytes;
            fclose(f);
        }
        return buf; //temp has all the concatenated stuff
    }

您需要随时增加缓冲区。例如:

/* Read all named files into a buffer. */                                          
                                                                                   
#include <stdio.h>                                                                 
#include <stddef.h>                                                                
#include <ctype.h>                                                                 
#include <stdlib.h>                                                                
                                                                                   
struct buffer {                                                                    
        char *start;                                                               
        char *end;                                                                 
        size_t cap;                                                                
};                                                                                 
                                                                                   
void push(int c, struct buffer *);                                                 
int pop(struct buffer *a);                                                         
void * xrealloc(void *buf, size_t num, size_t siz, void *endvp);                   
FILE * xfopen(const char *path, const char *mode);                                 
                                                                                   
int                                                                                
main(int argc, char **argv)                                                        
{                                                                                  
        struct buffer a = {0};                                                     
        int c;                                                                     
        for( int i = 1; i < argc; i++ ){                                           
                FILE *ifp = xfopen(argv[i], "r");                                  
                while( (c = fgetc(ifp)) != EOF ) {                                 
                        push(c, &a);                                               
                }                                                                  
        }                                                                          
        while( (c = pop(&a)) != EOF ) {                                            
                putchar(c);                                                        
        }                                                                          
        return 0;                                                                  
} 

                                                                                   
int                                                                                
pop(struct buffer *a)                                                              
{                                                                                  
        return (a->start < a->end) ? *a->start++ : EOF;                            
}                                                                                  
                                                                                   
void                                                                               
push(int c, struct buffer *b)                                                      
{                                                                                  
        if( b->start == NULL || b->end >= b->start + b->cap ) {                    
                b->start = xrealloc(b->start, b->cap += BUFSIZ, 1, &b->end);       
        }                                                                          
        *b->end++ = c;                                                             
}                                                                                  
                                                                                   
void *                                                                             
xrealloc(void *buf, size_t num, size_t siz, void *endvp)                           
{                                                                                  
        char **endp = endvp;                                                       
        char *b = buf;                                                             
        ptrdiff_t offset = b && endp && *endp ? *endp - b : 0;                     
        b = realloc(b, num * siz);                                                 
        if( b == NULL ){                                                           
                perror("realloc");                                                 
                exit(EXIT_FAILURE);                                                
        }                                                                          
        if( endp != NULL ){                                                        
                *endp = b + offset;                                                
        }                                                                          
        return b;                                                                  
}                                                                                  
                                                                                   
FILE *                                                                             
xfopen(const char *path, const char *mode)                                         
{                                                                                  
        FILE *fp = fopen(path, mode);                                              
        if( fp == NULL ){                                                          
                perror(path);                                                      
                exit(EXIT_FAILURE);                                                
        }                                                                          
        return fp;                                                                 
}