Tengo un FILE *
de una tubería (popen), y quiero pasarlo a char *artist
. El tamaño de la información que estará en el ARCHIVO es desconocido, por lo que debe usar malloc()
.
FILE *tmp1; char *artist; tmp1 = popen("cmus-remote -Q | grep 'tag artist' | sed s/'tag artist'/''/g | sed '1s/^.//'", "r");
¿Cómo puedo hacer esto?
La forma de hacerlo es usar un búfer temporal para leer fragmentos y adjuntarlos al artista de la siguiente manera:
char buf[8192]; char *artist = NULL; size_t len = 0, total_len = 0; FILE *fp; fp = popen("cmus-remote -Q | grep 'tag artist' | sed s/'tag artist'/''/g | sed '1s/^.//'", "r"); while (!feof(fp)) { if ( fgets(buf, sizeof(buf), fp) == NULL ) break; len = strlen(buf); artist = realloc(artist, len+1); /* +1 for \0 */ if (artist == NULL) { fprintf(stderr, "Ran out of memory\n"); exit(-1); } strncpy(artist+total_len, buf, len+1); /* concatenate the string at the end of artist */ total_len += len; }
La forma más fácil de hacer esto en una máquina con POSIX getline()
es:
char *buffer = 0; size_t bufsiz = 0; ssize_t nbytes; FILE *tmp1 = popen("cmus-remote -Q | sed -n '/tag artist./ { s/tag artist//g; s/^.//p; }'", "r"); if (tmp1 == 0) …report problem and do not use tmp1… while ((nbytes = getline(tmp1, &buffer, &size)) > 0) { …process line of data… } free(buffer);
Esto limita sus líneas al tamaño de la memoria asignable; Esto rara vez es una limitación real. Tenga en cuenta que solo necesita un único comando sed
para procesar la salida de cmus-remote
.