0

I'm trying to remove the file extension from a file so I can rename the file with the substring "opt.s". I do this with following simple example program:

 char in[5] = "hel.s";
 char test[40];
 strncpy(test,in,strlen(in)-2);
 char result[50];
 strcpy(result,strcat(test,"opt.s"));
 printf(" %s ",result);

The output i get differs but usually looks something like the following:

 helþ(opt.s 

So basically random numbers appear in between "hel" and "opt.s". What is the cause of this? Did I use strcpy wrong or is strcat causing the problem?

John
  • 317
  • 4
  • 19

2 Answers2

2
char in[5] = "hel.s";

in is NOT a string: it does not have a terminating '\0' char. You cannot use in with string functions.

strncpy(test, in, strlen(in) - 2); // invalid use of strlen

However, strncpy() is not a string function (it doesn't need a terminating NUL in the src array; it doesn't necessarily write terminating NUL in the dst array).
If it worked as I think you expected, the resulting test array is also NOT a string ... and you cannot use it with string functions.

strcpy(result, strcat(test, "opt.s")); // invalid use of strcat
BenMorel
  • 34,448
  • 50
  • 182
  • 322
pmg
  • 106,608
  • 13
  • 126
  • 198
2

This is incorrect:

char in[5] = "hel.s";

The string takes six, not five, characters (the sixths one is for null terminator). Without it the string is unterminated, causing strlen, strcat, and other functions that work on terminated strings to fail with undefined behavior.

To fix, remove 5 from the declaration, and let the compiler decide on the length for you:

char in[] = "hel.s";

In addition, your use of strncpy is invalid: it does not implicitly append null terminators

No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).

This line

strncpy(test,in,strlen(in)-2);

always produces an unterminated string, causing subsequent call of strcat to fail. To fix this, you need to add a terminator yourself:

size_t len = strlen(in)-2;
memcpy(test, in, len); // Do not use strncpy
test[len] = '\0';
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thank you, this was exactly what I was looking for. Helped on multiple levels – John May 01 '14 at 10:32
  • What happens in the case where you need to take a part of a string and not the last / first part? Then you need to use strncpy(test,input+4,5), if you want to extract the substring from char 4 until char 9, I suppose. – John May 01 '14 at 10:40
  • 1
    @John `strncpy` is for strings of fixed length - something that is not common any longer (and hasn't been common for quite a while now). Since you know for sure that the part you are taking is within the body of the string (i.e. does not cross the end of the string) you are better off with plain `memcpy`. – Sergey Kalinichenko May 01 '14 at 10:48