How to format strings and store them in a dynamic vector

2

In several parts of my code I just need to use bash commands to run programs on Ubuntu. To do this, format the command using sprintf and then run it 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 size of sprintfoutput varies according to the "one_rawreference" whose value is set by the user. How can I make the size of the sprintfoutput equal to the size of my formatted string?

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

    
asked by anonymous 30.06.2018 / 03:00

2 answers

2

Try the asprintf () function, which allocates and returns the buffer needed to accommodate the result. In addition to 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>
    
30.06.2018 / 04:53
1

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

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

Here's 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 required for formatting the string, see:

#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;
}
    
30.06.2018 / 12:52