连接从命令行传递的多个文件的内容
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 个字节并阅读了大量内容。这是未定义的行为。
- 您需要增加为每个文件分配的内存大小。
- 您应该检查文件 I/O 个错误。
- 我不知道为什么
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;
}
我正在尝试连接执行代码时传递的所有 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 个字节并阅读了大量内容。这是未定义的行为。
- 您需要增加为每个文件分配的内存大小。
- 您应该检查文件 I/O 个错误。
- 我不知道为什么
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;
}