パスからファイル名を取得する


85

パスからファイル名を取得する最も簡単な方法は何ですか?

string filename = "C:\\MyDirectory\\MyFile.bat"

この例では、「MyFile」を取得する必要があります。拡張子なし。


1
バックスペースにぶつかるまで後ろから検索しますか?
Kerrek SB 2011

2
@KerrekSB、バックスラッシュを意味します;)
Nim

ファイル "c:\\ MyDirectory \\ Myfile.pdf"のパスを含むstd :: stringがあります。このファイルの名前をmyfile_md.pdfに変更する必要があるため、パスからファイル名を取得する必要があります。
nidhal 2011

1
ファイルパスで多くの作業を行う必要がある場合は、BoostFileSystemの
くださいboost.org/doc/libs/release/libs/filesystem/v3/doc/index.htm– edA-qa mort-ora-y

2
@ニム:はい!私は...アウト間隔されている必要があります
Kerrek SB

回答:


29

_splitpathは必要なことを実行する必要があります。もちろん手動で行うこともできますが、_splitpathすべての特殊なケースも処理します。

編集:

BillHoagが述べたように、より安全なバージョンを使用することをお勧めします_splitpathと呼ばれる_splitpath_sをするとき利用できます。

または、ポータブルなものが必要な場合は、このようなことを行うことができます

std::vector<std::string> splitpath(
  const std::string& str
  , const std::set<char> delimiters)
{
  std::vector<std::string> result;

  char const* pch = str.c_str();
  char const* start = pch;
  for(; *pch; ++pch)
  {
    if (delimiters.find(*pch) != delimiters.end())
    {
      if (start != pch)
      {
        std::string str(start, pch);
        result.push_back(str);
      }
      else
      {
        result.push_back("");
      }
      start = pch + 1;
    }
  }
  result.push_back(start);

  return result;
}

...
std::set<char> delims{'\\'};

std::vector<std::string> path = splitpath("C:\\MyDirectory\\MyFile.bat", delims);
cout << path.back() << endl;

2
_splitpath私のマシンのインクルードには何もありません。
James Kanze 2011

9
私は、Visual Studio、持っているG ++、およびSun CCを。完全に優れたポータブルソリューションがあるのに、なぜ非標準のものを使用する必要があるのですか。
James Kanze 2011

2
@James、にリンクされているページは、にあると言ってい<stdlib.h>ます。移植性については、「完璧に優れたポータブルソリューション」の例をいくつか挙げることができますか?
Synetech 2012

2
@Synetechにリンクされているページは、ではなくMicrosoft拡張機能について説明しています<stdlib.h>。そして、明らかなポータブルソリューションはboost::filesystemです。
James Kanze 2012

3
@James、あなたが持っていない_splitpathstdlib.hVSのコピーの?次に、VSの修復インストールを実行することをお勧めします。
Synetech 2012

63

考えられる解決策:

string filename = "C:\\MyDirectory\\MyFile.bat";

// Remove directory if present.
// Do this before extension removal incase directory has a period character.
const size_t last_slash_idx = filename.find_last_of("\\/");
if (std::string::npos != last_slash_idx)
{
    filename.erase(0, last_slash_idx + 1);
}

// Remove extension if present.
const size_t period_idx = filename.rfind('.');
if (std::string::npos != period_idx)
{
    filename.erase(period_idx);
}

最も単純なものが常に最高です!
ジャン=フランソワ・ファーブル

61

ベースファイル名はフォルダの最後の区切り文字で始まる文字列の一部であるため、タスクはかなり単純です。

std::string base_filename = path.substr(path.find_last_of("/\\") + 1)

拡張子が削除されるだけでなく実行する唯一のものは、最後を見つけている場合.と取るsubstrこの時点まで

std::string::size_type const p(base_filename.find_last_of('.'));
std::string file_without_extension = base_filename.substr(0, p);

おそらく、拡張子のみで構成されるファイルを処理するためのチェックが必要です(つまり.bashrc...)

これを個別の機能に分割すると、単一のタスクを柔軟に再利用できます。

template<class T>
T base_name(T const & path, T const & delims = "/\\")
{
  return path.substr(path.find_last_of(delims) + 1);
}
template<class T>
T remove_extension(T const & filename)
{
  typename T::size_type const p(filename.find_last_of('.'));
  return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
}

コードは、さまざまなstd::basic_stringインスタンスで使用できるようにテンプレート化されています(つまり、std::stringstd::wstring ...)

テンプレーションの欠点は、次の場合にテンプレートパラメータを指定する必要があることです。 const char *が関数に渡されるがあることです。

したがって、次のいずれかを行うことができます。

A)std::stringコードをテンプレート化する代わりにのみ使用する

std::string base_name(std::string const & path)
{
  return path.substr(path.find_last_of("/\\") + 1);
}

B)を使用してラッピング機能を提供しますstd::string(インライン化/最適化される可能性が高い中間体として)

inline std::string string_base_name(std::string const & path)
{
  return base_name(path);
}

C)で呼び出す場合は、テンプレートパラメータを指定しますconst char *

std::string base = base_name<std::string>("some/path/file.ext");

結果

std::string filepath = "C:\\MyDirectory\\MyFile.bat";
std::cout << remove_extension(base_name(filepath)) << std::endl;

プリント

MyFile

このユースケースでは、すべてがOKです(そして元の質問に答えられます)が、拡張リムーバーは完全ではありません-「/ home / user /
my.dir

@avtomaton拡張子削除機能は、パスではなくファイル名で使用する必要があります。(base_name最初に適用してください。)
Pixelchemist 2015

私はそれを理解しています(そのため、元の質問に回答し、このユースケースではすべてがOKであると書きました)。これらのスニペットを使おうとする人のために、この問題を指摘したかっただけです。
avtomaton 2015

とてもいい説明です。それは問題の構造的理解を高めます。ありがとう
hell_ical_vortex 2016年

38

最も簡単な解決策は、のようなものを使用することですboost::filesystem。何らかの理由でこれがオプションではない場合...

これを正しく行うには、システムに依存するコードが必要になります。Windowsでは、'\\'または'/'パス区切り文字にすることができます。Unixでは、動作するだけ'/'で、他のシステムでは、誰が知っていますか。明らかな解決策は次のようになります。

std::string
basename( std::string const& pathname )
{
    return std::string( 
        std::find_if( pathname.rbegin(), pathname.rend(),
                      MatchPathSeparator() ).base(),
        pathname.end() );
}

MatchPathSeparatorシステム依存ヘッダーで次のいずれかとして定義されています。

struct MatchPathSeparator
{
    bool operator()( char ch ) const
    {
        return ch == '/';
    }
};

Unixの場合、または:

struct MatchPathSeparator
{
    bool operator()( char ch ) const
    {
        return ch == '\\' || ch == '/';
    }
};

Windowsの場合(または他の未知のシステムの場合はまだ異なるもの)。

編集:私は彼がまた拡張を抑制したかったという事実を逃しました。そのために、同じことの詳細:

std::string
removeExtension( std::string const& filename )
{
    std::string::const_reverse_iterator
                        pivot
            = std::find( filename.rbegin(), filename.rend(), '.' );
    return pivot == filename.rend()
        ? filename
        : std::string( filename.begin(), pivot.base() - 1 );
}

この場合、逆イテレータのベースがカットしたい場所の反対側にあるため、コードはもう少し複雑です。(逆イテレータのベースは、イテレータが指す文字の後ろにあることを忘れないでください。)そして、これでも少し疑わしいです。たとえば、空の文字列を返すことができるという事実は好きではありません。('.'ファイル名の最初の文字のみである場合は、完全なファイル名を返す必要があると主張します。これには、特殊なケースをキャッチするために少し余分なコードが必要になります。)}


9
string::find_last_of逆イテレータを操作する代わりに使用するのはどうですか?
Luc Touraille 2011

@LucTourailleなぜ、2つの方法を学ぶのですか?を除くすべてのコンテナに逆イテレータが必要stringになるため、とにかくそれらを学習する必要があります。そしてそれらを学んだので、への肥大化したインターフェースのすべてをわざわざ学ぶ理由はありませんstd::string
James Kanze 2011

注:<filesystem>ヘッダーはVisual Studio 2015以降に付属しているため、使用するためにBoostへの依存関係を追加する必要はありません。
iInspectable 2017年

16

C ++ 17で最も簡単な方法は次のとおりです。

拡張子のあるファイル名と拡張子のないファイル名には、#include <filesystem>filename()を使用しますstem()

    #include <iostream>
    #include <filesystem>
    namespace fs = std::filesystem;

    int main()
    {
        string filename = "C:\\MyDirectory\\MyFile.bat";

    std::cout << fs::path(filename).filename() << '\n'
        << fs::path(filename).stem() << '\n'
        << fs::path("/foo/bar.txt").filename() << '\n'
        << fs::path("/foo/bar.txt").stem() << '\n'
        << fs::path("/foo/.bar").filename() << '\n'
        << fs::path("/foo/bar/").filename() << '\n'
        << fs::path("/foo/.").filename() << '\n'
        << fs::path("/foo/..").filename() << '\n'
        << fs::path(".").filename() << '\n'
        << fs::path("..").filename() << '\n'
        << fs::path("/").filename() << '\n';
    }

出力:

MyFile.bat
MyFile
"bar.txt"
".bar"
"."
"."
".."
"."
".."
"/"

参照:cppreference


それはもう、「実験的」ではない
ビタミン

15

シェルパスAPIPathFindFileName、PathRemoveExtensionを使用することもできます。この特定の問題については、おそらく_splitpathよりも悪いですが、これらのAPIは、あらゆる種類のパス解析ジョブに非常に役立ち、UNCパス、スラッシュ、その他の奇妙なものを考慮に入れます。

wstring filename = L"C:\\MyDirectory\\MyFile.bat";
wchar_t* filepart = PathFindFileName(filename.c_str());
PathRemoveExtension(filepart); 

http://msdn.microsoft.com/en-us/library/windows/desktop/bb773589(v=vs.85).aspx

欠点は、shlwapi.libにリンクする必要があることですが、なぜそれが欠点なのかよくわかりません。


パスからファイル名を取得するための私の好ましい解決策。
アンドレアス

15

ブーストが使えれば、

#include <boost/filesystem.hpp>
path p("C:\\MyDirectory\\MyFile.bat");
string basename = p.filename().string();
//or 
//string basename = path("C:\\MyDirectory\\MyFile.bat").filename().string();

これですべてです。

Boostライブラリの使用をお勧めします。Boostは、C ++で作業するときに多くの便利さを提供します。ほぼすべてのプラットフォームをサポートします。Ubuntuを使用している場合は、1行でBoostライブラリをインストールできますsudo apt-get install libboost-all-devUbuntuにBoostをインストールする方法を参照してください)。


12

関数:

#include <string>

std::string
basename(const std::string &filename)
{
    if (filename.empty()) {
        return {};
    }

    auto len = filename.length();
    auto index = filename.find_last_of("/\\");

    if (index == std::string::npos) {
        return filename;
    }

    if (index + 1 >= len) {

        len--;
        index = filename.substr(0, len).find_last_of("/\\");

        if (len == 0) {
            return filename;
        }

        if (index == 0) {
            return filename.substr(1, len - 1);
        }

        if (index == std::string::npos) {
            return filename.substr(0, len);
        }

        return filename.substr(index + 1, len - index - 1);
    }

    return filename.substr(index + 1, len - index);
}

テスト:

#define CATCH_CONFIG_MAIN
#include <catch/catch.hpp>

TEST_CASE("basename")
{
    CHECK(basename("") == "");
    CHECK(basename("no_path") == "no_path");
    CHECK(basename("with.ext") == "with.ext");
    CHECK(basename("/no_filename/") == "no_filename");
    CHECK(basename("no_filename/") == "no_filename");
    CHECK(basename("/no/filename/") == "filename");
    CHECK(basename("/absolute/file.ext") == "file.ext");
    CHECK(basename("../relative/file.ext") == "file.ext");
    CHECK(basename("/") == "/");
    CHECK(basename("c:\\windows\\path.ext") == "path.ext");
    CHECK(basename("c:\\windows\\no_filename\\") == "no_filename");
}

8

C ++ドキュメントから-string :: find_last_of

#include <iostream>       // std::cout
#include <string>         // std::string

void SplitFilename (const std::string& str) {
  std::cout << "Splitting: " << str << '\n';
  unsigned found = str.find_last_of("/\\");
  std::cout << " path: " << str.substr(0,found) << '\n';
  std::cout << " file: " << str.substr(found+1) << '\n';
}

int main () {
  std::string str1 ("/usr/bin/man");
  std::string str2 ("c:\\windows\\winhelp.exe");

  SplitFilename (str1);
  SplitFilename (str2);

  return 0;
}

出力:

Splitting: /usr/bin/man
 path: /usr/bin
 file: man
Splitting: c:\windows\winhelp.exe
 path: c:\windows
 file: winhelp.exe

何も見つからなかった場合にfind_last_of返さstring::nposれることを忘れないでください(そして処理すること)。
congusbongus 2016年

@congusbongus本当ですが、ファイル名(パスなし)だけの場合、ファイルパスを分割する意味はありません:)
jave.web 2016年

@ jave.webそれは理にかなっており、戻り値 'string :: npos'を処理する必要があります。このための関数を実装すると、「ファイル名だけ」を含むさまざまな入力を処理できるはずです。そうでなければ、実際の実装でバグがある場合は役に立たないでしょう。
winux 2016

@winuxこれはすでに考えて、有効な パスを使用すると、入力を信用していない場合、あなたは、もちろん、最初のパスを検証する必要があります...。
jave.web 2016

@winuxとにかくstring::nposこれとstring::substr実装方法のために、チェックを行う必要はありません。a)string::npos 「長さ」として渡されsubstrます=>最後まですべてを読み取る動作が文書化されています。b)substrstring::npos + 1」が指定され、長さstring::nposがない:の値が文書化されている-1ため、0=>文字列の先頭に評価され、長さのデフォルト値substrnpos=>「ファイル名だけ」でも機能し ますcplusplus.com/reference / string / string / substr cplusplus.com/reference/string/string/npos
jave.web

5

均一な初期化と匿名のインラインラムダを備えたC ++ 11バリアント(James Kanzeのバージョンに触発された)。

std::string basename(const std::string& pathname)
{
    return {std::find_if(pathname.rbegin(), pathname.rend(),
                         [](char c) { return c == '/'; }).base(),
            pathname.end()};
}

ただし、ファイル拡張子は削除されません。


Windows以外のパスでのみ機能しますが、短くて甘いです。
Volomike 2016年

いつでもラムダリターンをreturn c == '/' || c == '\\';に変更して、Windowsで機能するようにすることができます
ziomq1991 2016

以下のようなパスを処理するために「」、「///」、および「DIR1 / DIR2 /」、(参照:POSIXベース名())上記のreturnステートメントの前に次のコードを追加します if (pathname.size() == 0) return "."; auto iter = pathname.rbegin(); auto rend = pathname.rend(); while (iter != rend && *iter == '/') ++iter; if (iter == rend) /* pathname has only path separators */ return "/"; pathname = std::string(pathname.begin(), iter.base());
Gidfiddle

5

このboost filesystemライブラリはライブラリとしても利用できexperimental/filesystem、C ++ 17用のISOC ++に統合されました。次のように使用できます。

#include <iostream>
#include <experimental/filesystem>

namespace fs = std::experimental::filesystem;

int main () {
    std::cout << fs::path("/foo/bar.txt").filename() << '\n'
}

出力:

"bar.txt"

std::stringオブジェクトに対しても機能します。


4

これが実際に私のために実際に働いた唯一のものです:

#include "Shlwapi.h"

CString some_string = "c:\\path\\hello.txt";
LPCSTR file_path = some_string.GetString();
LPCSTR filepart_c = PathFindFileName(file_path);
LPSTR filepart = LPSTR(filepart_c);
PathRemoveExtension(filepart);

Skrymsliが提案したものとほぼ同じですが、wchar_t *、VS Enterprise2015では機能しません

_splitpathも同様に機能しましたが、必要なchar [?]文字の数を推測する必要はありません。おそらくこのコントロールが必要な人もいると思います。

CString c_model_name = "c:\\path\\hello.txt";
char drive[200];
char dir[200];
char name[200];
char ext[200];
_splitpath(c_model_name, drive, dir, name, ext);

_splitpathにインクルードが必要だったとは思いません。これらのソリューションのいずれにも、外部ライブラリ(ブーストなど)は必要ありませんでした。


4
std::string getfilename(std::string path)
{
    path = path.substr(path.find_last_of("/\\") + 1);
    size_t dot_i = path.find_last_of('.');
    return path.substr(0, dot_i);
}

3

私はそれをします...

最初のバックスラッシュ/フォワードスラッシュが見つかるまで、文字列の末尾から逆方向に検索します。

次に、最初のドット(。)が見つかるまで、文字列の末尾から逆方向に検索します。

これで、ファイル名の開始と終了がわかります。

シンプル...


これは、私が知っているどのシステムでも機能しません。('\\'パス区切り文字として受け入れる1つのシステムもを使用する'/'ため、どちらかを一致させる必要があります。)そして、何を期待しているのかわかりません。
James Kanze 2011

さて、どちらかに一致するように変更します。大したことはありません。そして最初のドットを楽しみにしています(。)
TomP89 2011

最初のドットではなく、最後のドットを見つける必要があります。(逆イテレータはあなたの友達です!)
James Kanze 2011

はい、良い点です。したがって、file.ext.extの場合は、file.extを抽出する必要があります。:)
TomP89 2011

おそらく。これは、いずれの場合も通常の規則です。たとえば、にmy.source.cppコンパイルさmy.source.objれます(拡張子はに.cpp置き換えられます.obj)。
James Kanze 2011

2
m_szFilePath.MakeLower();
CFileFind finder;
DWORD buffSize = MAX_PATH;
char longPath[MAX_PATH];
DWORD result = GetLongPathName(m_szFilePath, longPath, MAX_PATH );

if( result == 0)
{
    m_bExists = FALSE;
    return;
}
m_szFilePath = CString(longPath);
m_szFilePath.Replace("/","\\");
m_szFilePath.Trim();
//check if it does not ends in \ => remove it
int length = m_szFilePath.GetLength();
if( length > 0 && m_szFilePath[length - 1] == '\\' )
{
    m_szFilePath.Truncate( length - 1 );
}
BOOL bWorking = finder.FindFile(this->m_szFilePath);
if(bWorking){
    bWorking = finder.FindNextFile();
    finder.GetCreationTime(this->m_CreationTime);
    m_szFilePath = finder.GetFilePath();
    m_szFileName = finder.GetFileName();

    this->m_szFileExtension = this->GetExtension( m_szFileName );

    m_szFileTitle = finder.GetFileTitle();
    m_szFileURL = finder.GetFileURL();
    finder.GetLastAccessTime(this->m_LastAccesTime);
    finder.GetLastWriteTime(this->m_LastWriteTime);
    m_ulFileSize = static_cast<unsigned long>(finder.GetLength());
    m_szRootDirectory = finder.GetRoot();
    m_bIsArchive = finder.IsArchived();
    m_bIsCompressed = finder.IsCompressed();
    m_bIsDirectory = finder.IsDirectory();
    m_bIsHidden = finder.IsHidden();
    m_bIsNormal = finder.IsNormal();
    m_bIsReadOnly = finder.IsReadOnly();
    m_bIsSystem = finder.IsSystem();
    m_bIsTemporary = finder.IsTemporary();
    m_bExists = TRUE;
    finder.Close();
}else{
    m_bExists = FALSE;
}

変数m_szFileNameにはfileNameが含まれています。


3
うわー-それはパスから「ファイル名を取得」するためのたくさんのコードです... :)
Nim 2011

4
@Nim私の印象も。私自身のコードでは、ワンライナーを使用していますboost::filesystem::path( path ).filename()
James Kanze 2011

そのコードを持つCFileInfoクラスがあります。テスト済みで、何もリスクを冒したくなかったので、ここにコードをダンプしました...この例から約5行のコードを使用できます。
ルシアン2011

2

とを使用_splitpath()しないでください_wsplitpath()。それらは安全ではなく、時代遅れです!

代わりに、すなわち、彼らの安全なバージョンを使用_splitpath_s()し、_wsplitpath_s()


2

これも機能するはずです:

// strPath = "C:\\Dir\\File.bat" for example
std::string getFileName(const std::string& strPath)
{
    size_t iLastSeparator = 0;
    return strPath.substr((iLastSeparator = strPath.find_last_of("\\")) != std::string::npos ? iLastSeparator + 1 : 0, strPath.size() - strPath.find_last_of("."));
}

使用できる場合、QtはQString(split、trimなど)、QFile、QPath、QFileInfoなどを提供して、ファイル、ファイル名、およびディレクトリを操作します。そしてもちろん、それはクロスプラフトルムでもあります。


4
コードの将来の読者のために、すべてを1行のコードに詰め込むのではなく、意味のある名前の一時変数を使用してください(そして、その間に、これらすべてを関数getFilenameなどにカプセル化してください)。
Luc Touraille 2011

編集。しかし、いくつかの実用的な答えがすでに与えられているので、要点はそれを短くすることでした。
typedef 2011

1
間違っていると思います。最後の部分を置き換えないでください: "strPath.size()-strPath.find_last_of("。 ")"を "strPath.find_last_of("。 ")-iLastSeparator"
taktak004 2014年

@ taktak004正解です。`returnstrPath.substr((iLastSeparator = strPath.find_last_of( "/"))!= std :: string :: npos?iLastSeparator + 1:0、strPath.find_last_of( "。" )-iLastSeparator); `
phenmod 2015

2

std :: filesystemを使用して、これを非常にうまく行うことができます。

#include <filesystem>
namespace fs = std::experimental::filesystem;

fs::path myFilePath("C:\\MyDirectory\\MyFile.bat");
fs::path filename = myFilePath.stem();

0

長い間、ファイルパスを適切に分解できる関数を探していました。私にとって、このコードはLinuxとWindowsの両方で完全に機能しています。

void decomposePath(const char *filePath, char *fileDir, char *fileName, char *fileExt)
{
    #if defined _WIN32
        const char *lastSeparator = strrchr(filePath, '\\');
    #else
        const char *lastSeparator = strrchr(filePath, '/');
    #endif

    const char *lastDot = strrchr(filePath, '.');
    const char *endOfPath = filePath + strlen(filePath);
    const char *startOfName = lastSeparator ? lastSeparator + 1 : filePath;
    const char *startOfExt = lastDot > startOfName ? lastDot : endOfPath;

    if(fileDir)
        _snprintf(fileDir, MAX_PATH, "%.*s", startOfName - filePath, filePath);

    if(fileName)
        _snprintf(fileName, MAX_PATH, "%.*s", startOfExt - startOfName, startOfName);

    if(fileExt)
        _snprintf(fileExt, MAX_PATH, "%s", startOfExt);
}

結果の例は次のとおりです。

[]
  fileDir:  ''
  fileName: ''
  fileExt:  ''

[.htaccess]
  fileDir:  ''
  fileName: '.htaccess'
  fileExt:  ''

[a.exe]
  fileDir:  ''
  fileName: 'a'
  fileExt:  '.exe'

[a\b.c]
  fileDir:  'a\'
  fileName: 'b'
  fileExt:  '.c'

[git-archive]
  fileDir:  ''
  fileName: 'git-archive'
  fileExt:  ''

[git-archive.exe]
  fileDir:  ''
  fileName: 'git-archive'
  fileExt:  '.exe'

[D:\Git\mingw64\libexec\git-core\.htaccess]
  fileDir:  'D:\Git\mingw64\libexec\git-core\'
  fileName: '.htaccess'
  fileExt:  ''

[D:\Git\mingw64\libexec\git-core\a.exe]
  fileDir:  'D:\Git\mingw64\libexec\git-core\'
  fileName: 'a'
  fileExt:  '.exe'

[D:\Git\mingw64\libexec\git-core\git-archive.exe]
  fileDir:  'D:\Git\mingw64\libexec\git-core\'
  fileName: 'git-archive'
  fileExt:  '.exe'

[D:\Git\mingw64\libexec\git.core\git-archive.exe]
  fileDir:  'D:\Git\mingw64\libexec\git.core\'
  fileName: 'git-archive'
  fileExt:  '.exe'

[D:\Git\mingw64\libexec\git-core\git-archiveexe]
  fileDir:  'D:\Git\mingw64\libexec\git-core\'
  fileName: 'git-archiveexe'
  fileExt:  ''

[D:\Git\mingw64\libexec\git.core\git-archiveexe]
  fileDir:  'D:\Git\mingw64\libexec\git.core\'
  fileName: 'git-archiveexe'
  fileExt:  ''

これがあなたにも役立つことを願っています:)


0

shlwapi.lib/dll を使用します HKCUレジストリハイブを内部的にます。

リンクしないことをお勧めします shlwapi.libライブラリを作成している場合、または製品にUIがない場合ないことをお勧めします。libを作成している場合、コードはUIを持たないプロジェクトを含むすべてのプロジェクトで使用できます。

ユーザーがログインしていないときに実行されるコードを記述している場合(たとえば、サービス[またはその他]が起動時または起動時に開始するように設定されている場合)、はありませんHKCU。最後に、shlwapiは決済機能です。その結果、リストの上位にあり、それ以降のバージョンのWindowsでは非推奨になります。


0

遅いが簡単な正規表現ソリューション:

    std::string file = std::regex_replace(path, std::regex("(.*\\/)|(\\..*)"), "");

0

私はあなたのニーズを満たすかもしれない機能を実装しました。これは、コンパイル時に計算できるstring_viewのconstexpr関数find_last_of(c ++ 17以降)に基づいています。

constexpr const char* base_filename(const char* p) {
    const size_t i = std::string_view(p).find_last_of('/');
    return std::string_view::npos == i ? p : p + i + 1 ;
}

//in the file you used this function
base_filename(__FILE__);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.