File Paths in C

The <string.h> library provides functions to manipulate strings in C. We’ll use it along with <stdio.h> for input/output operations and <stdlib.h> for memory allocation.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    // Join should be used to construct paths in a portable way.
    // In C, we'll create a simple function to join paths.
    char* join_path(const char* path1, const char* path2) {
        char* result = malloc(strlen(path1) + strlen(path2) + 2);
        strcpy(result, path1);
        strcat(result, "/");
        strcat(result, path2);
        return result;
    }

    char* p = join_path("dir1", join_path("dir2", "filename"));
    printf("p: %s\n", p);

    // In C, we need to be careful about memory management
    free(p);

    // Joining paths with superfluous separators
    printf("%s\n", join_path("dir1/", "filename"));

    // Dir and Base can be simulated using string manipulation
    char* dir(const char* path) {
        char* last_slash = strrchr(path, '/');
        if (last_slash == NULL) {
            return strdup(".");
        }
        return strndup(path, last_slash - path);
    }

    char* base(const char* path) {
        char* last_slash = strrchr(path, '/');
        if (last_slash == NULL) {
            return strdup(path);
        }
        return strdup(last_slash + 1);
    }

    printf("Dir(p): %s\n", dir(p));
    printf("Base(p): %s\n", base(p));

    // Check if a path is absolute
    int is_abs(const char* path) {
        return path[0] == '/';
    }

    printf("%d\n", is_abs("dir/file"));
    printf("%d\n", is_abs("/dir/file"));

    const char* filename = "config.json";

    // Get file extension
    char* ext(const char* filename) {
        char* dot = strrchr(filename, '.');
        if (dot == NULL) {
            return strdup("");
        }
        return strdup(dot);
    }

    char* extension = ext(filename);
    printf("%s\n", extension);

    // Remove extension from filename
    char* trim_suffix(const char* str, const char* suffix) {
        size_t str_len = strlen(str);
        size_t suffix_len = strlen(suffix);

        if (str_len >= suffix_len && 
            strcmp(str + str_len - suffix_len, suffix) == 0) {
            return strndup(str, str_len - suffix_len);
        }
        return strdup(str);
    }

    char* name_without_ext = trim_suffix(filename, extension);
    printf("%s\n", name_without_ext);

    // Free allocated memory
    free(extension);
    free(name_without_ext);

    return 0;
}

This C code demonstrates similar functionality to the original example, with some adjustments due to C’s different approach to string handling and memory management:

  1. We create a simple join_path function to concatenate path components.
  2. String manipulation is used to simulate Dir and Base functions.
  3. The is_abs function checks if a path is absolute by examining the first character.
  4. We implement an ext function to get file extensions.
  5. The trim_suffix function removes the extension from a filename.

Note that in C, we need to be careful about memory management. We use malloc and free to allocate and deallocate memory for strings.

To compile and run this program:

$ gcc file_paths.c -o file_paths
$ ./file_paths
p: dir1/dir2/filename
dir1/filename
Dir(p): dir1/dir2
Base(p): filename
0
1
.json
config

Remember to handle error checking and memory management carefully when working with file paths in C.