Reputation:
How do I strip a file extension from a string in C?
For example,
If I have the filenames with the file extensions
hello.txt
hello.c
hello.java
should all result in just the filename without the extension as
hello
the length of the file extension shouldn't matter.
the function should also be portable and not system dependent.
I know how to get the file extension using strchr
or strrchr
. I've done this in Bash and in Python, but I've never had to do this in C.
Note: This is for a personal exercise to help strengthen my understanding of the C programming language.
Upvotes: 0
Views: 9269
Reputation: 11
const char * s_name // pointing to ex "myString.ext"
char * s_atext = strstr(s_name, ".ext");
if (s_atext != NULL) {
/* Extract the filename without extension in case only */
size_t name_only_size = s_atext - s_name;
char * s_name_only = strndup(s_name, name_only_size);
// use your s_name_only
printf("FileName w/o ext: %s\n", s_name_only);
if (s_name_only) free(s_name_only);
}
Upvotes: 0
Reputation: 21323
I don't know that there is a best way, but here is one way. Presumably you don't want to strip the name from dot files. Also, you probably only want to remove the characters from the last dot to the end of the string. Note that in the code below, the input string is modified, so the filename can't be a string literal, but must be a null-terminated character array.
#include <stdio.h>
#include <string.h>
void strip_ext(char *);
int main(void)
{
char filename1[] = "myfile.txt";
char filename2[] = ".emacs";
char filename3[] = "anotherfile.";
char filename4[] = "nodot";
char filename5[] = "";
char filename6[] = "dot.dot.dot";
strip_ext(filename1);
strip_ext(filename2);
strip_ext(filename3);
strip_ext(filename4);
strip_ext(filename5);
strip_ext(filename6);
printf("file1: %s\n", filename1);
printf("file2: %s\n", filename2);
printf("file3: %s\n", filename3);
printf("file4: %s\n", filename4);
printf("file5: %s\n", filename5);
printf("file6: %s\n", filename6);
return 0;
}
void strip_ext(char *fname)
{
char *end = fname + strlen(fname);
while (end > fname && *end != '.') {
--end;
}
if (end > fname) {
*end = '\0';
}
}
Program output:
file1: myfile
file2: .emacs
file3: anotherfile
file4: nodot
file5:
file6: dot.dot
@David C. Rankin has pointed out that more complex filepaths may complicate matters. Below is a modification to the strip_ext()
function that stops looking for a dot when either a forward or back slash is encountered, in which case the filename string remains unchanged:
void strip_ext(char *fname)
{
char *end = fname + strlen(fname);
while (end > fname && *end != '.' && *end != '\\' && *end != '/') {
--end;
}
if ((end > fname && *end == '.') &&
(*(end - 1) != '\\' && *(end - 1) != '/')) {
*end = '\0';
}
}
Running this function with the same test strings, and the additional test strings:
char filename7[] = "/my.dir/myfile";
char filename8[] = "/dir/.filename";
generates this output:
file1: myfile
file2: .emacs
file3: anotherfile
file4: nodot
file5:
file6: dot.dot
file7: /my.dir/myfile
file8: /dir/.filename
Upvotes: 9
Reputation: 338
It may not be the best way, but a possible solution is putting a NULL terminator in the place of the dot, which can be achieved by the following code.
char *filename_dot = strchr(filename, '.');
int offset = filename_dot - filename;
filename[offset] = '\0';
Upvotes: 0
Reputation: 10184
There could be many ways of doing it. One way could be replace the first dot with a null character (\0
).
char [] filename = "Hello.java";
for(int i=0;i<strlen(filename);i++) {
if(filename[i] == '.') {
filename[i]='\0';
break;
}
}
Upvotes: 1