sprintf () без завершающего нулевого пробела в C

есть ли способ использовать функцию C sprintf () без добавления символа "\0 " в конце ее вывода? Мне нужно написать форматированный текст в середине строки фиксированной ширины.

7 ответов


нет никакого способа, чтобы сказать sprintf() не писать конечное значение null. Что вы можете сделать, это использовать sprintf() писать во временную строку, а затем что-то вроде strncpy() скопировать только те байты, которые вы хотите.


sprintf возвращает длину строки, написанной (не включая нулевой терминал), вы можете использовать это, чтобы знать, где был нулевой терминал, и изменить символ нулевого терминала на что-то другое (т. е. пробел). Это было бы более эффективно, чем использование strncpy.

 unsigned int len = sprintf(str, ...);
 str[len] = '<your char here>';

вы не можете сделать это с sprintf (), но вы мая иметь возможность с snprintf (), в зависимости от вашей платформы.

вам нужно знать, сколько символов вы заменяете (но поскольку вы помещаете их в середину строки, вы, вероятно, знаете это в любом случае).

это работает, потому что некоторые реализации snprintf() не гарантируют, что будет записан завершающий символ - предположительно для совместимости с такими функциями, как stncpy ().

char message[32] = "Hello 123, it's good to see you.";

snprintf(&message[6],3,"Joe");

после этого "123 "заменяется на"Joe".

в реализациях, где snprintf () гарантирует нулевое завершение, даже если строка усечена, это не сработает. Поэтому, если вас беспокоит переносимость кода, Вы должны избегать этого.

большинство версии на базе Windows snprintf () демонстрируют это поведение.

а, в macOS и BSD (и, возможно, linux), как представляется, всегда null-terminate.


вы также можете использовать строку фиксированной ширины в качестве строки формата, например:

char my_fixed_width_string_format[] = "need 10 chars starting here: %10s";
char my_fixed_width_string[40];
char string_to_print[] = "abcdefghijklmnop";
sprintf(my_fixed_width_string, my_fixed_width_string_format, string_to_print;
printf(my_fixed_width_string);

должна принести

нужно 10 символов, начиная здесь: abcdefghij


поскольку вы пишете в фиксированную область, вы можете сделать это следующим образом:

// pointer to fixed area we want to write to
char* s;

// number of bytes needed, not including the null
int r = snprintf(0, 0, <your va_args here>);

// char following the last char we will write - null goes here
char c = s[r + 1];

// do the formatted write
snprintf(s, r + 1, <your_va_args here>);

// replace what was overwritten
s[r + 1] = c;

на самом деле этот пример не добавит null, если вы используете snprintf:

char name[9] = "QQ40dude";  
unsigned int i0To100 = 63;  
_snprintf(&name[2],2,"%d",i0To100);  
printf(name);// output will be: QQ63dude  

смотрите сюда:http://en.wikipedia.org/wiki/Printf

printf ("%.*s", 3, "abcdef") приведет к печати" abc"