strcat () для форматированных строк

Я строю строку по частям в своей программе, и в настоящее время я использую сочетание strcat (), когда добавляю простую строку в конец, но когда я добавляю форматированную строку, я использую sprintf (), например:

int one = 1; sprintf(instruction + strlen(instruction), " number %d", one); 

возможно ли объединить форматированную строку с помощью strcat () или какой из них является предпочтительным?

Ваше решение будет работать. Вызов strlen немного неудобен (особенно если строка довольно длинная). sprintf () вернет длину, которую вы использовали [strcat не будет], поэтому одна вещь, которую вы можете сделать, это примерно так:

  char str[MAX_SIZE]; char *target = str; target += sprintf(target, "%s", str_value); target += sprintf(target, "somestuff %d", number); if (something) { target += sprintf(target, "%s", str_value2); } else { target += sprintf(target, "%08x", num2); } 

Я не уверен, что strcat намного эффективнее, чем sprintf (), когда используется таким образом.

Изменить: следует писать меньшие примеры …

нет, это невозможно, но вы можете использовать sprintf() для этих простых строк и избегать вызова strlen() каждый раз:

 len = 0; len += sprintf(buf+len, "%s", str); len += sprintf(buf+len, " number %d", one); 

Чтобы ответить на прямой вопрос, конечно, можно использовать strcat для добавления форматированных строк. Сначала вам нужно сначала создать форматированную строку, а затем вы можете использовать strcat для добавления:

 #include  #include  int main(void) { char s[100]; char s1[20]; char s2[30]; int n = 42; double x = 22.0/7.0; strcpy(s, "n = "); sprintf(s1, "%d", n); strcat(s, s1); strcat(s, ", x = "); sprintf(s2, "%.6f", x); strcat(s, s2); puts(s); return 0; } 

Выход:

 n = 42, x = 3.142857 

Но это не очень хороший подход.

sprintf работает так же хорошо, как запись в конец существующей строки. См . Ответ Маца и ответ мух на примерах. Отдельные массивы, используемые для хранения отдельных полей, не нужны, по крайней мере, в этом случае.

И поскольку этот код не отслеживает конец строки, производительность, вероятно, будет низкой. strcat(s1, s2) сначала должен сканировать s1 чтобы найти завершающий '\0' , а затем скопировать содержимое s2 в него. Другие ответы избегают этого, продвигая индекс или указатель, чтобы отслеживать конец строки, не перепробивая ее.

Кроме того, код не прилагает никаких усилий, чтобы избежать переполнения буфера. strncat() может это сделать, но он просто strncat() строку; он не говорит вам, что он был усечен. snprintf() – хороший выбор; он возвращает количество символов, которые он написал бы, если бы было достаточно свободного места. Если это превышает указанный вами размер, строка была усечена.

 /* other declarations as above */ size_t count; count = snprintf(s, sizeof s, "n = %d, x = %.6f", n, x); if (count > sizeof s) { /* the string was truncated */ } 

И добавить несколько строк (например, если некоторые из них добавлены условно или неоднократно), вы можете использовать методы в других ответах для отслеживания конца целевой строки.

Так что да, можно добавить форматированные строки с помощью strcat() . Это вряд ли будет хорошей идеей.

Какой предпочтительный метод, зависит от того, что вы готовы использовать. Вместо того, чтобы выполнять все эти ручные (и потенциально опасные) строковые операции, я бы использовал GString данных g_strdup_print функции GString из GLib или GLib. Для вашей проблемы GString предоставляет функцию g_string_append_printf .

Напишите свою собственную упаковку для ваших нужд.

Призыв к этому будет выглядеть так:

 result = universal_concatenator(4,result,"numbers are %d %f\n",5,16.045); result = universal_concatenator(2,result,"tail_string"); 

Вы можете определить одну функцию, которая позаботится о том, чтобы беспокоиться, если вам нужно использовать sprintf () или strcat (). Это будет выглядеть так:

 /* you should pass the number of arguments * make sure the second argument is a pointer to the result always * if non formatted concatenation: * call function with number_of_args = 2 * else * call function with number of args according to format * that is, if five inputs to sprintf(), then 5. * * NOTE : Here you make an assumption that result has been allocated enough memory to * hold your concatenated string. This assumption holds true for strcat() or * sprintf() of your previous implementation */ char* universal_concaternator(int number_of_args,...) { va_list args_list; va_start(args_list,number_of_args); int counter = number_of_args; char *result = va_arg(args_list, char*); char *format; if(counter == 2) /* it is a non-formatted concatenation */ { result = strcat(result,va_arg(args_list,char*)); va_end(args_list); return result; } /* else part - here you perform formatted concatenation using sprintf*/ format = va_arg(args_list,char*); vsprintf(result + strlen(result),format,args_list); va_end(args_list); return result; } /* dont forget to include the header *  #FOR-ANSI * or  #FOR-UNIX */ 

Сначала нужно определить, какой из двух он должен назвать (strcat или sprintf), тогда он должен сделать вызов и упростить для вас сосредоточиться на фактической логике того, над чем вы работаете! Только код ctrl + c выше и ctrl + v в базу кода.

Примечание. Ответ Мэтта является хорошей альтернативой для длинных строк. Но для коротких строк (<250) это должно быть сделано.