2011-04-02 103 views
3

我想从一个const char *文件路径中提取一个const char *文件名。我试着用正则表达式,但未能:如何从路径中获取文件名的词干?

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

的问题是,“d:\文件\文件”将被退回,而不是想要的“文件”(注:没有“.lua”)

+3

[s | f] scanf不能做正则表达式 - 你必须自己编写它(例如strtok) – dialer 2011-04-02 12:08:39

+0

就像拨号器说的,但我也不明白你的正则表达式。匹配文件名就像是“[\\\\//(。+)$”(对用户输入非常宽容和不安全)。 – OlivierD 2011-04-02 13:56:26

+0

找到最后一个反斜杠(从头到尾),它后面是什么文件名 – 2011-04-02 20:16:04

回答

15

刚使用boost::filesystem

#include <boost/filesystem.hpp> 

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(); 

或另外,如果你想自己引入错误:

// 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; 
else 
    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(); 
+0

对不起,我只能使用默认的C++函数。 – luac 2011-04-02 12:18:16

+4

为什么?正则表达式不是标准C++的一部分,所以你将不得不使用非标准函数。重写现有的众所周知的好的免费代码正在浪费大家的时间。良好的编程能够充分利用资源 – Mark 2011-04-02 12:25:24

+1

@luac:boost :: filesystem是TR2的一个计划添加。 – ybungalobill 2011-04-02 12:32:59

0

Here你可以找到一个例子。我不是说这是最好的,我相信你可以改进,但它只使用标准的C++(至少现在认为是标准的)。 当然,你不会拥有boost :: filesystem的特性(例子中的那些函数和纯字符串一起玩,并不保证/检查你实际上使用真正的文件系统路径)。

15

如何使用std :: string? 例如

std::string path("d:\\dir\\subdir\\file.ext"); 
    std::string filename; 

    size_t pos = path.find_last_of("\\"); 
    if(pos != std::string::npos) 
    filename.assign(path.begin() + pos + 1, path.end()); 
    else 
    filename = path; 
+1

这将产生“file.ext”,而OP想要返回“文件”。而且这在UNIX上不起作用。 – BatchyX 2012-07-03 19:06:00

1

您可以轻松地提取该文件:

int main() 
{ 
    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"); 
    else 
    { 
     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 
+0

Hello Kushvendra,请将您的电子邮件地址放入您的个人资料页面。 – eeerahul 2011-11-24 10:15:16

+0

@ kushvendra - 在评论或聊天中,这里是讨论您的答案的适当地方。 – razlebe 2011-11-24 10:38:24

0
// Set short name: 
char *Filename; 
Filename = strrchr(svFilename, '\\'); 
if (Filename == NULL) 
    Filename = svFilename; 

if (Filename[0] == '\\') 
    ++Filename; 
if (!lstrlen(Filename)) 
{ 
    Filename = svFilename; 
} 
fprintf(m_FileOutput, ";\n; %s\n;\n", Filename); 
0

你可以使用_splitpath_s function to break a path name into its components。我不知道这是标准C还是Windows特定的。反正这是功能:

#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; 
    } 
} 

这是一个极大的方便,使用安全std::string但你可以修改此使用TCHAR*wcharchar)...

对于您的具体情况:

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; 
} 
1

您可以使用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()); 
} 

输出:

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

请注意,暂且您可能需要使用#include <experimental/fileystem>std::experimental::filesystem,而不是直到标准库完全符合沿。

欲了解更多有关std::filesystem的文档,请查看filesystem library reference

0

如果你打算给display给Windows上的用户一个文件名,你应该遵守他们的shell设置(显示/隐藏扩展名等)。

通过调用SHGetFileInfoSHGFI_DISPLAYNAME标志,您可以获得正确格式的文件名。