Было бы довольно просто построить структуру строкового буфера, которая будет отслеживать текущую позицию в вашем буфере, и объединить ее с vsprintf
, чтобы получить catf()
. Функция vsnprintf()
(при условии, что она доступна) аналогична printf
, за исключением того, что она принимает va_list
вместо ...
после строки форматирования.
Этот подход имеет преимущество перед другими ответами, заключающееся в том, что он позволяет вам 'cat' из любого места в вашем коде, у которого есть доступ к структуре, без явного переноса текущей длины или пересчета каждый раз, как это делает strcat
.
Вот примерный набросок бесплатно .....
/* Note: the typedef is for the pointer, not the struct. */
typedef struct StrBufStruct {
char * buffer,
size_t size,
size_t pos
} * StrBuf;
/* Create a new StrBuf. NOTE: Could statically allocate too. */
StrBuf newStrBuf(size_t size){
StrBuf sb;
sb = malloc( sizeof(struct StrBufStruct) );
sb->size = size;
sb->pos = 0;
sb->buffer = malloc( size );
/* TODO: ALWAYS CHECK YOUR MALLOC!!! */
}
int sbcatf( StrBuf b, char * fmt, ... )
{
va_list ap;
int res;
if( b->pos < b->size )
{
va_start(ap,fmt);
res = vsnprintf( b->buffer[b->pos], b->size - b->pos, fmt, ap );
b->pos += res;
va_end();
} else {
/* If you want to get really fancy, use realloc so you don't have to worry
about buffer size at all. But be careful, you can run out of memory. */
}
}
/* TODO: Write a free/delete function */
int main(int argc, char **argv){
int i;
/* initialize your structure */
StrBuf sb = newStrBuf(10000);
/* concatenate numbers 0-999 */
for(i=0; i < 1000; i++){
sbcatf(sb, "I=%d\n", i);
}
/* TODO: whatever needs to be done with sb->buffer */
/* free your structure */
deleteStrBuf(sb);
}
Также обратите внимание, что если все, что вы пытаетесь сделать, это сделать действительно длинную строку, но хотите иметь возможность иметь разрывы строк в своем коде, это обычно приемлемо, хотя я лично не гарантирую переносимость. Я также использую эту технику для разделения строк на "\n"
разрывов строк, чтобы код выглядел так, как будет выглядеть результирующая строка.
const char * someString = "this is one really really really really"
"long stttttttttrrrrrrrrrrrrrrrrrrrriiiiiiiiiiinnnnnnngggggg"
" because the compiler will automatically concatenate string"
" literals until we reach a ';' after a \" character";