2015-10-29 2 views
0

Я хочу, чтобы вставить переменную строку в заранее определенную строку .... вот это упрощенная версию того, что я до сих пор (я пропущенные проверки ошибок и т.д.):C ... лучший способ вставки в строку?

void insertPath(char *path) 
{ 
    char *cmd; 
    cmd = (char *)malloc(50); 
    strcpy(cmd, "CREATE VIRTUAL TABLE temp.tablename USING CSVFILE("); 

    int new_size = (strlen(cmd) + strlen(path) + 2); 
    cmd = (char *)realloc(cmd, new_size); 

    strcat(cmd, path); 
    strcat(cmd, ");"); 

    // Do other stuff here and finally free(cmd); 



} 

Есть ли лучше способ сделать это?

Было бы неплохо не использовать mallocrealloc, но я не хочу создавать экземпляр переменной cmd с фиксированной длиной.

(Первоначально я думал, что я мог бы сделать это, то realloc..ie char cmd[50] = "CREATE... " или char *cmd = "CREATE...", но realloc работает только на переменных, которые были ранее malloc «d)

Единственный способ, которым я могу думать (и я не уверен, что это работает) будет:

void insertPath(char *path) 
{ 
    char *cmd; 
    cmd = (char *)malloc(55); 
    strcpy(cmd, "CREATE VIRTUAL TABLE temp.tablename USING CSVFILE(%s);"); 

    int new_size = (strlen(cmd) + strlen(path)); 
    cmd = (char *)realloc(cmd, new_size); 

    sprintf(cmd, path); 

    // Do other stuff here and finally free(cmd); 
} 
+0

«Было бы хорошо, чтобы не использовать таНос перераспределить». Инкапсулируйте их. –

+1

Как вы можете думать, что делать? И в общем, каков ваш вопрос? –

+0

Мой вопрос прямо там ... «Есть ли лучший способ сделать это?». Я дал две попытки вставить неизвестную строку в известную. Я спрашиваю, какой из них (или третий я не знаю) - лучший способ – jramm

ответ

2

Почему бы не забыть о malloc и таким образом избежать утечки памяти в коде?

т.е.

size_t len = 55 + strlen(path); 
char cmd[len]; 

Затем используйте

snprintf(cmd, len, "CREATE VIRTUAL TABLE temp.tablename USING CSVFILE(%s);", path); 
+0

является «PATH_MAX» стандартом или что-то, что мне нужно определить? – jramm

+0

Он находится в 'limits.h'. #include lthat –

+0

Также проверьте, достаточно ли 50. –

4

EDIT (в ответ на комментарии): sizeof(char) => 1, +1 для прекращения \0

Как насчет snprintf?

size_t size = baseSize + strlen(path) + 1; 
char *cmd = malloc(size); 
snprintf(cmd, size, "CREATE VIRTUAL TABLE temp.tablename USING CSVFILE(%s);", path); 

Здесь baseSize есть длина «предопределенной» строки и path переменная строка, которую вы получите в качестве аргумента в функции. В конце cmd должен содержать предопределенный текст с указанием пути вместо %s.

+2

sizeof (char) = 1 по стандарту – fghj

0

Почему не ?:

void insertPath(char *path) { 
    char const *tmp = "CREATE VIRTUAL TABLE temp.tablename USING CSVFILE("; 
    char  *cmd = (char*) malloc(strlen(path) + strlen(tmp) + 3); 
    strcpy(cmd, tmp); 
    strcat(cmd, path); 
    strcat(cmd, ");"); 
} 
+0

Лучше объявить 'tmp' как' const char * 'или' char [] '. Некоторые компиляторы на самом деле скажут вам, выпустив предупреждение. –

+0

@JohnBollinger. Кроме того, еще лучше сделать его статическим. –

+0

@JohnBollinger исправил thnx. – 101010

0

Игнорирование неблагоразумие создания unsanitized statments SQL вручную, вы можете использовать функцию sprintf, но правильно. Аргументами являются output, format, args. Например:

char *insertPath(const char *path) 
{ 
    static const char *cmd = "CREATE VIRTUAL TABLE temp.tablename USING CSVFILE(%s);"; 
    char *output = malloc(strlen(cmd) + strlen(path)); // Strictly this should be ... - 1 since it includes the the length of '%s' 
    sprintf(output, cmd, path); 
    return output; 
} 

Старайтесь избегать выделения памяти без необходимости. Здесь строка шаблона cmd никогда не изменяется, поэтому ее можно объявить static и const. Выходной буфер гарантированно достаточно длинный, если вы просто добавляете длины двух строк вместе. Кроме того, помните, что если вам нужно использовать значение новой строки вне функции, вам придется как можно скорее вернуть указатель. В вашем примере вы вызываете realloc, но никогда не позволяете вызывающему абоненту знать, что блок памяти изменился. Это часто приводит к segfault, поскольку realloc может или не может изменить местоположение памяти при ее расширении.

+0

У меня уже неявно есть +2, потому что '% s' исчезает в конечном результате. –

1

Что с

void insertPath(char *path) 
{ 
    const char cmd[] = "CREATE VIRTUAL TABLE temp.tablename USING CSVFILE(%s);"; 
    int size = strlen(cmd) + strlen(path) + 1; // *sizeof(char) if it makes you happy 
    char *newcmd = malloc(size); 
    snprintf(newcmd, size, cmd, path);  
} 
+0

Ничего. Это почти точная копия моего ответа, но более снисходительная и без объяснения. –

+0

Также вы можете сделать 'cmd'' static'. –

+0

@MadPhysicist кажется, что мы разместили примерно то же самое время. – vogomatix

Смежные вопросы