2011-04-02 5 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標誌,您可以獲得正確格式的文件名。