I'm bored, and instead of pointing out problems in the original code, I wrote my own. I tried to keep it clear for instructive purposes.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Replace the last suffix in a filename with a new suffix. Copy the new
name to a new string, allocated with malloc. Return new string.
Caller MUST free new string.
If old name has no suffix, a period and the new suffix is appended
to it. The new suffix MUST include a period it one is desired.
Slashes are interepreted to separate directories in the filename.
Suffixes are only looked after the last slash, if any.
*/
char *replace_filename_suffix(const char *pathname, const char *new_suffix)
{
size_t new_size;
size_t pathname_len;
size_t suffix_len;
size_t before_suffix;
char *last_slash;
char *last_period;
char *new_name;
/* Allocate enough memory for the resulting string. We allocate enough
for the worst case, for simplicity. */
pathname_len = strlen(pathname);
suffix_len = strlen(new_suffix);
new_size = pathname_len + suffix_len + 1;
new_name = malloc(new_size);
if (new_name == NULL)
return NULL;
/* Compute the number of characters to copy from the old name. */
last_slash = strrchr(pathname, '/');
last_period = strrchr(pathname, '.');
if (last_period && (!last_slash || last_period > last_slash))
before_suffix = last_period - pathname;
else
before_suffix = pathname_len;
/* Copy over the stuff before the old suffix. Then append a period
and the new suffix. */
#if USE_SPRINTF
/* This uses snprintf, which is how I would normally do this. The
%.*s formatting directive is used to copy a specific amount
of text from pathname. Note that this has the theoretical
problem with filenames larger than will fit into an integer. */
snprintf(new_name, new_size, "%.*s%s", (int) before_suffix, pathname,
new_suffix);
#else
/* This uses memcpy and strcpy, to demonstrate how they might be
used instead. Much C string processing needs to be done with
these low-level tools. */
memcpy(new_name, pathname, before_suffix);
strcpy(new_name + before_suffix, new_suffix);
#endif
/* All done. */
return new_name;
}
int main(int argc, char **argv)
{
int i;
char *new_name;
for (i = 1; i + 1 < argc; ++i) {
new_name = replace_filename_suffix(argv[i], argv[i+1]);
if (new_name == NULL) {
perror("replace_filename_suffix");
return EXIT_FAILURE;
}
printf("original: %s\nsuffix: %s\nnew name: %s\n",
argv[i], argv[i+1], new_name);
free(new_name);
}
return 0;
}