Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I want to extract a const char* filename from a const char* filepath. I tried with regex but failed:

const char* currentLoadedFile = "D:\files\file.lua";
char fileName[256];
if (sscanf(currentLoadedFile, "%*[^\\]\\%[^.].lua", fileName)) {
return (const char*)fileName; // WILL RETURN "D:\files\file!!

The issue is that "D:\files\file" will be returned and not the wanted "file"(note: without ".lua")

Like dialer said, but also I don't understand your regex. To match the filename would be something like "[\\\\/](.+)$" (very permissive and unsafe on user input). – OlivierD Apr 2, 2011 at 13:56 find the last backslash (first from the end to beginning), and what is after it is the filename – Marius Bancila Apr 2, 2011 at 20:16 This question is a partial dupe of this one. You just need to then lop the .lua extension off the filename to get the stem. – razlebe Nov 24, 2011 at 10:44 @razlebe: Tell me how a C# question is remotely a "partial dupe" of a pure C++ question, that doesn't even ask for the same thing and isn't solved the same way. – BatchyX Jul 3, 2012 at 19:10 size_t pos = path.find_last_of("\\"); if(pos != std::string::npos) filename.assign(path.begin() + pos + 1, path.end()); filename = path; This will yield "file.ext", while the OP wanted to return "file". Also this won't work on UNIX. – BatchyX Jul 3, 2012 at 19:06 std::string filename_noext; filename_noext = boost::filesystem::path("D:\\files\\file.lua").stem().string(). const char* result_as_const_char = filename_noext.c_str();

or alternatively, if you want to introduce bugs yourself :

// have fun defining that to the separator of the target OS.
#define PLATFORM_DIRECTORY_SEPARATOR '\\'
// the following code is guaranteed to have bugs.
std::string input = "D:\\files\\file.lua";
std::string::size_type filename_begin = input.find_last_of(PLATFORM_DIRECTORY_SEPERATOR);
if (filename_begin == std::string::npos)
    filename_begin = 0;
    filename_begin++;
std::string::size_type filename_length = input.find_last_of('.');
if (filename_length != std::string::npos)
    filename_length = filename_length - filename_begin;
std::string result = input.substr(filename_begin, filename_length);
const char* bugy_result_as_const_char = result.c_str();
                Why? regex is not part of standard C++ so you will have to use non standard functions. rewriting existing well known good free code is wasting everyone's time. Good programming is making good use of resources
– mmmmmm
                Apr 2, 2011 at 12:25
                @luac What stops you adding includes but allows you to add code - this seems a very artificial restriction. What happens if you need a new class?
– mmmmmm
                Apr 2, 2011 at 14:23

You can do this portably and easily using the new filesystem library in C++17.

#include <cstdint>
#include <cstdio>
#include <filesystem>
int main()
    std::filesystem::path my_path("D:/files/file.lua");
    std::printf("filename: %s\n", my_path.filename().u8string().c_str());
    std::printf("stem: %s\n", my_path.stem().u8string().c_str());
    std::printf("extension: %s\n", my_path.extension().u8string().c_str());

Output:

filename: file.lua
stem: file
extension: .lua

Do note that for the time being you may need to use #include <experimental/fileystem> along with std::experimental::filesystem instead until standard libraries are fully conforming.

For more documentation on std::filesystem check out the filesystem library reference.

char pscL_Dir[]="/home/srfuser/kush/folder/kushvendra.txt"; char pscL_FileName[50]; char pscL_FilePath[100]; char *pscL; pscL=strrchr(pscL_Dir,'/'); if(pscL==NULL) printf("\n ERROR :INvalid DIr"); strncpy(pscL_FilePath,pscL_Dir,(pscL-pscL_Dir)); strcpy(pscL_FileName,pscL+1); printf("LENTH [%d}\n pscL_FilePath[%s]\n pscL_FileName[%s]",(pscL-pscL_Dir),pscL_FilePath,pscL_FileName); return 0; output: LENTH [25} pscL_FilePath[/home/srfuser/kush/folder] pscL_FileName[kushvendra.txt @kushvendra - here in the comments, or in chat, are the appropriate places to discuss your answer. – razlebe Nov 24, 2011 at 10:38

Here you can find an example. I'm not saying it's the best and I'm sure you could improve on that but it uses only standard C++ (anyway at least what's now considered standard). Of course you won't have the features of the boost::filesystem (those functions in the example play along with plain strings and do not guarantee/check you'll actually working with a real filesystem path).

You could use the _splitpath_s function to break a path name into its components. I don't know if this is standard C or is Windows specific. Anyway this is the function:

#include <stdlib.h>
#include <string>
using std::string;
bool splitPath(string const &path, string &drive, string &directory, string &filename, string &extension) {
    // validate path
    drive.resize(_MAX_DRIVE);
    directory.resize(_MAX_DIR);
    filename.resize(_MAX_FNAME);
    extension.resize(_MAX_EXT);
    errno_t result;
    result = _splitpath_s(path.c_str(), &drive[0], drive.size(), &directory[0], directory.size(), &filename[0], filename.size(), &extension[0], extension.size()); 
    //_splitpath(path.c_str(), &drive[0], &directory[0], &filename[0], &extension[0]); //WindowsXp compatibility
    _get_errno(&result);
    if (result != 0) {
        return false;
    } else {
        //delete the blank spaces at the end
        drive = drive.c_str();
        directory = directory.c_str();
        filename = filename.c_str();
        extension = extension.c_str();
        return true;

It is a lot easier and safe to use std::string but you could modify this to use TCHAR* (wchar, char)...

For your specific case:

int main(int argc, char *argv[]) {
    string path = argv[0];
    string drive, directory, filename, extension;
    splitPath(path, drive, directory, filename, extension);
    printf("FILE = %s%s", filename.c_str(), extension.c_str());
    return 0;

If you are going to display a filename to the user on Windows you should respect their shell settings (show/hide extension etc).

You can get a filename in the correct format by calling SHGetFileInfo with the SHGFI_DISPLAYNAME flag.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.