How to format strings and store them in a dynamic vector

Asked

Viewed 120 times

2

In several parts of my code I need to use bash commands to run programs on Ubuntu. To do this, format the command using sprintf and then run with the system function.

Ex:

sprintf(sprintfoutput, "makeblastdb -in %s -dbtype prot -out SASBT_BLASTDB > /dev/null", one_rawreference);
system((char *)sprintfoutput);

However, note that the sprintfoutput size varies according to the "one_rawreference", whose value is defined by the user. How can I make sprintfoutput size equal to the size of my formatted string?

Note: I do this kind of thing over 40 times in my code.

2 answers

2


Try the asprintf() function, which allocates and returns the buffer needed to accommodate the result. Besides returning the right size, it is much safer.

As an extension of GNU libc, you need to define the macro

#define _GNU_SOURCE

before

#include <stdio.h>
  • Remembering that asprintf() is a GNU extension and is not part of the standard C (nor the POSIX).

1

The function snprintf() of the standard library stdio.h is able to calculate the size needed to accommodate the formatted string. The secret is to pass a buffer NULL, sized 0, causing snprintf() return the amount of bytes needed to accommodate the formatted string, see only:

size_t tam = snprintf( NULL, 0, "makeblastdb -in %s -dbtype prot -out SASBT_BLASTDB > /dev/null", one_rawreference );

Here is an example (tested) based on your need:

#include <stdio.h>
#include <stdlib.h>

char * formatar_comando( char const * one_rawreference )
{
    /* String de formatacao */
    const char * fmt = "makeblastdb -in %s -dbtype prot -out SASBT_BLASTDB > /dev/null";

    /* Calcula tamanho necessario para acomodar a string formatada */
    size_t tam = snprintf( NULL, 0, fmt, one_rawreference );

    /* Aloca a memoria necessaria para acomodar a string formatada */
    char * output = malloc( tam + 1 );

    /* Formata string efetivamente */
    sprintf( output, fmt, one_rawreference );

    /* Retorna */
    return output;
}


int main( void )
{
    /* Formatacao do comando em vetor dinamico */
    char * cmd = formatar_comando( "foobar" );

    /* Exibe o comando que sera executado */
    printf("Comando: %s\n", cmd );

    /* Execucao do comando */
    system(cmd);

    /* Libera memoria do vetor dinamico usada para formatacao */
    free(cmd);

    /* Sucesso */
    return 0;
}

The execution of your command can be encapsulated completely within a single function, which would be able to allocate only the memory needed to format the string, see only:

#include <stdio.h>
#include <stdlib.h>

int executar_makeblastdb( char const * one_rawreference )
{
    /* String de formatacao */
    const char * fmt = "makeblastdb -in %s -dbtype prot -out SASBT_BLASTDB > /dev/null";

    /* Calcula tamanho necessario para acomodar a string formatada */
    size_t tam = snprintf( NULL, 0, fmt, one_rawreference );

    /* Aloca a memoria necessaria para acomodar a string formatada */
    char * cmd = malloc( tam + 1 );

    /* Formata string */
    sprintf( cmd, fmt, one_rawreference );

    /* Executa comando */
    int ret = system(cmd);

    /* Libera a memoria ocupada */
    free(cmd);

    /* Retorna status da execucao do comando */
    return ret;
}


int main( void )
{
    int ret = executar_makeblastdb( "foobar" );

    if( ret < 0 )
    {
        printf("Erro executando comando.\n");
        return 1;
    }

    printf("Comando executado com sucesso.\n");
    return 0;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.