I would like to know if there is a way I can loop through a FILE *ptr so that I can get its size.For example:
char *buffer = malloc(512);
FILE *command = popen("pwd","r");
pclose(command);
I would like to loop through *command output until the end and create a counter size++ that way I can calculate its size. But I don't know how to do the loop here. If anyone could please tell me if this is possible and how. Thanks.
You can only read data from the pipe once. If you want to calculate the amount of data, you will need to store it all and count. Something like:
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
static void * xrealloc(void *buf, size_t num, size_t siz, void *end);
struct string{ char *start, *end; size_t cap; };
static void
push(int c, struct string *b)
{
if( b->start == NULL || b->end >= b->start + b->cap ) {
b->start = xrealloc(b->start, b->cap += 128,
sizeof *b->start, &b->end);
}
*b->end++ = c;
}
int
main(int argc, char **argv)
{
int c;
int text = 1;
char *cmd = argc > 1 ? argv[1] : "pwd";
struct string content = {0};
FILE *command = popen(cmd,"r");
if( command == NULL ) {
perror("pwd");
return EXIT_FAILURE;
}
while( (c = getc(command)) != EOF ){
push(c, &content);
if( ! isprint(c) && ! isspace(c)) {
text = 0;
}
}
printf("%zu bytes\n", content.end - content.start);
if( text ) {
push('\0', &content);
printf("%s", content.start);
}
return 0;
}
static void *
xrealloc(void *buf, size_t num, size_t siz, void *endvp)
{
void **endp = endvp;
ptrdiff_t offset = endp && *endp ? *endp - buf : 0;
buf = realloc(buf, num * siz);
if( buf == NULL ){
perror("realloc");
exit(EXIT_FAILURE);
}
if( endp != NULL ){
*endp = buf + offset;
}
return buf;
}
Just a two simple doubts 1- Why is *b->end++ = c works, but not the other way around I mean c = *b->end++. I know the results are different but it is a assignment in both ways. 2- And why I can't declare struct string *content = {0} instead of content without pointer; when I use the pointer and modify the code to use content->something it stops working. It may sound odd but I'm still learning the C language there are some things I don't really understand. And by the way thanks for the quick answer.
*b->end++ = c
works because it puts the value of c into the correct location.c = *b->end++
cannot work because*b->end
is uninitialized so attempting to read its value is undefined behavior and c is a local variable so assigning it just before returning from the function is pointless.You cannot declare
struct string *content = {0}
because the value on the right hand side of the initializer is of the wrong type. You could dostruct string a; struct string *content = &a
.