Search code examples
cfile-extension

how to remove extension from file name?


I want to throw the last three character from file name and get the rest?

I have this code:

char* remove(char* mystr) {

    char tmp[] = {0};
    unsigned int x;

    for (x = 0; x < (strlen(mystr) - 3); x++)
        tmp[x] = mystr[x];

    return tmp;
}

Solution

  • Try:

    char *remove(char* myStr) {
        char *retStr;
        char *lastExt;
        if (myStr == NULL) return NULL;
        if ((retStr = malloc (strlen (myStr) + 1)) == NULL) return NULL;
        strcpy (retStr, myStr);
        lastExt = strrchr (retStr, '.');
        if (lastExt != NULL)
            *lastExt = '\0';
        return retStr;
    }
    

    You'll have to free the returned string yourself. It simply finds the last . in the string and replaces it with a null terminator character. It will handle errors (passing NULL or running out of memory) by returning NULL.

    It won't work with things like /this.path/is_bad since it will find the . in the non-file portion but you could handle this by also doing a strrchr of /, or whatever your path separator is, and ensuring it's position is NULL or before the . position.


    A more general purpose solution to this problem could be:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    // remove_ext: removes the "extension" from a file spec.
    //   myStr is the string to process.
    //   extSep is the extension separator.
    //   pathSep is the path separator (0 means to ignore).
    // Returns an allocated string identical to the original but
    //   with the extension removed. It must be freed when you're
    //   finished with it.
    // If you pass in NULL or the new string can't be allocated,
    //   it returns NULL.
    
    char *remove_ext (char* myStr, char extSep, char pathSep) {
        char *retStr, *lastExt, *lastPath;
    
        // Error checks and allocate string.
    
        if (myStr == NULL) return NULL;
        if ((retStr = malloc (strlen (myStr) + 1)) == NULL) return NULL;
    
        // Make a copy and find the relevant characters.
    
        strcpy (retStr, myStr);
        lastExt = strrchr (retStr, extSep);
        lastPath = (pathSep == 0) ? NULL : strrchr (retStr, pathSep);
    
        // If it has an extension separator.
    
        if (lastExt != NULL) {
            // and it's to the right of the path separator.
    
            if (lastPath != NULL) {
                if (lastPath < lastExt) {
                    // then remove it.
    
                    *lastExt = '\0';
                }
            } else {
                // Has extension separator with no path separator.
    
                *lastExt = '\0';
            }
        }
    
        // Return the modified string.
    
        return retStr;
    }
    
    int main (int c, char *v[]) {
        char *s;
        printf ("[%s]\n", (s = remove_ext ("hello", '.', '/'))); free (s);
        printf ("[%s]\n", (s = remove_ext ("hello.", '.', '/'))); free (s);
        printf ("[%s]\n", (s = remove_ext ("hello.txt", '.', '/'))); free (s);
        printf ("[%s]\n", (s = remove_ext ("hello.txt.txt", '.', '/'))); free (s);
        printf ("[%s]\n", (s = remove_ext ("/no.dot/in_path", '.', '/'))); free (s);
        printf ("[%s]\n", (s = remove_ext ("/has.dot/in.path", '.', '/'))); free (s);
        printf ("[%s]\n", (s = remove_ext ("/no.dot/in_path", '.', 0))); free (s);
    
        return 0;
    }
    

    and this produces:

    [hello]
    [hello]
    [hello]
    [hello.txt]
    [/no.dot/in_path]
    [/has.dot/in]
    [/no]