%i/%i is two arguments. but you only provide one. the first number printed have the value, but the second will be pseudo-random (whatever value was in memory at the time).
sprintf does not bound the string, thus (C console program):
char buf1[64];
char buf2[64];
puts("Please enter your name!\n");
fgets(buf1, sizeof(buf1), stdin);
sprintf(buf2, "Hello there %s, I hope you are well\n", buf1);
puts(buf2);
will write past the end of buf2. At the end of buf2 you will presumably find the return address of your function. If the values are carefully crafted, you can insert some exploit code into those 63 bytes that are writable in buf1 and overwrite the return address to point to that data. you just have to avoid nulls.
Now admittedly if you'd used snprintf instead, it wouldn't have been formatted properly (no trailing part of the string, including the newline), but at least it wouldn't be exploitable (normally).
if you're unable to compile code that uses snprintf, you must be using windows. Sorry, but microsoft are morons.
On windows, you'll need to use _snprintf instead. Be warned that unlike linux's snprintf function, it does not guarentee null termination. Which means you need to reduce the number of bytes by 1, and unconditionally write the last byte of the buffer as 0. Which is a bit of a pain. It sucks to use windows. You can fairly easily write a wrapper function for it, but its annoying to have to do that. If you're lazy you can #ifdef _WIN32 #define snprintf sprintf_s #endif but your program will safely abort if its too long (which can be a major issue in server code, yay for denial of service attacks). So really, there's no choice but to validate all string lengths carefully... Programming can be a real pain some times.
In your original case, truncation is fine and dandy. Yay for snprintf.