For doing string concatenation I've been doing basic strcpy,strncpy of char* buffers. Then I learned about the snprintf and friends.
Should I stick with my strcpy,strcpy + \0 terminiation. Or should I just use snprintf in the future?
thanks
For doing string concatenation I've been doing basic strcpy,strncpy of char* buffers. Then I learned about the snprintf and friends.
Should I stick with my strcpy,strcpy + \0 terminiation. Or should I just use snprintf in the future?
thanks
snprintf is more robust if you want to format your string. If you only want to concatenate, use strncpy (don't use strcpy) since it's more efficient.
All *printf functions check formatting and expand its corresponding argument, thus it is slower than a simple strcpy/strncpy, which only copy a given number of bytes from linear memory.
My rule of thumb is:
strcpy , strncpy etc only copies strings from one memory location to another. But, with snprint, you can do more stuff like formatting the string. Copying integers into buffer etc.
It purely depends on your requirement which one to use. If as per your logic, strcpy & strncpy is already working for you, no need to jump to snprintf.
Also, remember to use strncpy for better safety as suggested by others.
For most purposes I doubt the difference between using strncpy
and snprintf
is measurable.
If there's any formatting involved I tend to stick to only snprintf
rather than mixing in strncpy
as well.
I find this helps code clarity, and means you can use the following idiom to keep track of where you are in the buffer (thus avoiding creating a Shlemiel the Painter algorithm):
char sBuffer[iBufferSize];
char* pCursor = sBuffer;
pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer), "some stuff\n");
for(int i = 0; i < 10; i++)
{
pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer), " iter %d\n", i);
}
pCursor += snprintf(pCursor, sizeof(sBuffer) - (pCursor - sBuffer), "into a string\n");
sprintf
has an extremely useful return value that allows for efficient appending.
Here's the idiom:
char buffer[HUGE] = {0};
char *end_of_string = &buffer[0];
end_of_string += sprintf( /* whatever */ );
end_of_string += sprintf( /* whatever */ );
end_of_string += sprintf( /* whatever */ );
You get the idea. This works because sprintf
returns the number of characters it wrote to the buffer, so advancing your buffer by that many positions will leave you pointing to the '\0'
at the end of what's been written so far. So when you hand the updated position to the next sprintf
, it can start writing new characters right there.
Constrast with strcpy
, whose return value is required to be useless. It hands you back the same argument you passed it. So appending with strcpy
implies traversing the entire first string looking for the end of it. And then appending again with another strcpy call implies traversing the entire first string, followed by the 2nd string that now lives after it, looking for the '\0'
. A third strcpy
will re-traverse the strings that have already been written yet again. And so forth.
So for many small appends to a very large buffer, strcpy
approches (O^n) where n is the number of appends. Which is terrible.
Plus, as others mentioned, they do different things. sprintf
can be used to format numbers, pointer values, etc, into your buffer.