string が与えられた場合"filename.conf"
、拡張部分を確認するにはどうすればよいですか?
クロスプラットフォーム ソリューションが必要です。
string が与えられた場合"filename.conf"
、拡張部分を確認するにはどうすればよいですか?
クロスプラットフォーム ソリューションが必要です。
これは単純すぎる解決策ですか?
#include <iostream>
#include <string>
int main()
{
std::string fn = "filename.conf";
if(fn.substr(fn.find_last_of(".") + 1) == "conf") {
std::cout << "Yes..." << std::endl;
} else {
std::cout << "No..." << std::endl;
}
}
最善の方法は、それを行うコードを記述せず、既存のメソッドを呼び出すことです。Windows では、PathFindExtensionメソッドがおそらく最も単純です。
では、なぜ自分で書かないのでしょうか。
strrchr の例を見てみましょう。このメソッドを次の文字列 "c:\program files\AppleGate.Net\readme" に対して使用するとどうなりますか? 拡張子は「.Net\readme」ですか?いくつかの例のケースで機能するものを書くのは簡単ですが、すべてのケースで機能するものを書くのははるかに難しい場合があります.
複数のドットを含むファイル名に注意する必要があります。例:またはc:\.directoryname\file.name.with.too.many.dots.ext
では正しく処理されません。strchr
find.
私のお気に入りは、拡張子 (パス) 関数を持つブースト ファイルシステム ライブラリです。
STL にアクセスできると仮定します。
std::string filename("filename.conf");
std::string::size_type idx;
idx = filename.rfind('.');
if(idx != std::string::npos)
{
std::string extension = filename.substr(idx+1);
}
else
{
// No extension found
}
編集:プラットフォームについて言及していないため、これはクロスプラットフォームソリューションです。特にWindowsを使用している場合は、スレッドで他の人が言及したWindows固有の機能を活用したいと思うでしょう。
他の誰かがブーストについて言及しましたが、これを行うために実際のコードを追加したかっただけです:
#include <boost/filesystem.hpp>
using std::string;
string texture = foo->GetTextureFilename();
string file_extension = boost::filesystem::extension(texture);
cout << "attempting load texture named " << texture
<< " whose extensions seems to be "
<< file_extension << endl;
// Use JPEG or PNG loader function, or report invalid extension
実際、STL は多くのコードなしでこれを行うことができます。STL について少し学ぶことをお勧めします。STL を使用すると、面白いことができるからです。とにかく、これは私が使用するものです。
std::string GetFileExtension(const std::string& FileName)
{
if(FileName.find_last_of(".") != std::string::npos)
return FileName.substr(FileName.find_last_of(".")+1);
return "";
}
このソリューションは、「this.abcdesmp3」のような文字列であっても、拡張子が見つからない場合は常に拡張子を返し、「」を返します。
実は一番簡単な方法は
char* ext;
ext = strrchr(filename,'.')
覚えておくべきことの1つ'.'
は、ファイル名に存在しない場合、extはNULL
.
私は今日、この質問に出くわしました。すでに動作するコードを持っていたにもかかわらず、場合によっては動作しないことがわかりました。
いくつかの外部ライブラリを使用することを既に提案している人もいますが、私は学習目的で独自のコードを書くことを好みます。
一部の回答には、最初に使用していた方法 (最後の「.」を探す) が含まれていましたが、Linux では隠しファイル/フォルダーが「.」で始まることを思い出しました。そのため、ファイル file が非表示で拡張子がない場合、ファイル名全体が拡張子として使用されます。それを避けるために、私はこのコードを書きました:
bool getFileExtension(const char * dir_separator, const std::string & file, std::string & ext)
{
std::size_t ext_pos = file.rfind(".");
std::size_t dir_pos = file.rfind(dir_separator);
if(ext_pos>dir_pos+1)
{
ext.append(file.begin()+ext_pos,file.end());
return true;
}
return false;
}
これを完全にテストしたわけではありませんが、うまくいくはずです。
私はboost::filesystem::extension
(std::filesystem::path::extension
C++ 17で)行きますが、Boostを使用できず、拡張機能を確認するだけでよい場合、簡単な解決策は次のとおりです。
bool ends_with(const std::string &filename, const std::string &ext)
{
return ext.length() <= filename.length() &&
std::equal(ext.rbegin(), ext.rend(), filename.rbegin());
}
if (ends_with(filename, ".conf"))
{ /* ... */ }
char配列型の文字列の場合、これを使用できます。
#include <ctype.h>
#include <string.h>
int main()
{
char filename[] = "apples.bmp";
char extension[] = ".jpeg";
if(compare_extension(filename, extension) == true)
{
// .....
} else {
// .....
}
return 0;
}
bool compare_extension(char *filename, char *extension)
{
/* Sanity checks */
if(filename == NULL || extension == NULL)
return false;
if(strlen(filename) == 0 || strlen(extension) == 0)
return false;
if(strchr(filename, '.') == NULL || strchr(extension, '.') == NULL)
return false;
/* Iterate backwards through respective strings and compare each char one at a time */
for(int i = 0; i < strlen(filename); i++)
{
if(tolower(filename[strlen(filename) - i - 1]) == tolower(extension[strlen(extension) - i - 1]))
{
if(i == strlen(extension) - 1)
return true;
} else
break;
}
return false;
}
ファイル名に加えてファイルパスを処理できます。CとC++の両方で動作します。そしてクロスプラットフォーム。
std::stringのfind/rfindを使用すると、この問題は解決しますが、パスを頻繁に使用する場合は、boost :: filesystem :: pathを確認する必要があります。これにより、生の文字列インデックス/イテレータをいじるよりもコードがはるかにクリーンになります。
高品質で、十分にテストされた(オープンソースおよび商用の)無料で完全にポータブルなライブラリであるため、ブーストをお勧めします。
System::String を使用した NET/CLI バージョン
System::String^ GetFileExtension(System::String^ FileName)
{
int Ext=FileName->LastIndexOf('.');
if( Ext != -1 )
return FileName->Substring(Ext+1);
return "";
}
良い答えですが、それらのほとんどにはいくつかの問題があることがわかります。まず第一に、良い答えは、パス見出しを持つ完全なファイル名に対して機能するはずであり、LinuxまたはWindowsでも機能するか、前述のようにクロスプラットフォームである必要があると思います. ほとんどの回答について。ファイル名に拡張子がなく、パスにドットを含むフォルダー名が含まれている場合、関数は正しい拡張子を返すことができません。いくつかのテスト ケースの例を以下に示します。
const char filename1 = {"C:\\init.d\\doc"}; // => No extention
const char filename2 = {"..\\doc"}; //relative path name => No extention
const char filename3 = {""}; //emputy file name => No extention
const char filename4 = {"testing"}; //only single name => No extention
const char filename5 = {"tested/k.doc"}; // normal file name => doc
const char filename6 = {".."}; // parent folder => No extention
const char filename7 = {"/"}; // linux root => No extention
const char filename8 = {"/bin/test.d.config/lx.wize.str"}; // ordinary path! => str
" brian newman " の提案は filename1 と filename4 では失敗します。また、逆検索に基づく他の回答のほとんどは、filename1 に対して失敗します。ソースに次のメソッドを含めることをお勧めします。これは、拡張子の最初の文字のインデックス、または見つからない場合は指定された文字列の長さを返す関数です。
size_t find_ext_idx(const char* fileName)
{
size_t len = strlen(fileName);
size_t idx = len-1;
for(size_t i = 0; *(fileName+i); i++) {
if (*(fileName+i) == '.') {
idx = i;
} else if (*(fileName + i) == '/' || *(fileName + i) == '\\') {
idx = len - 1;
}
}
return idx+1;
}
以下のように、C++ アプリケーションで上記のコードを使用できます。
std::string get_file_ext(const char* fileName)
{
return std::string(fileName).substr(find_ext_idx(fileName));
}
場合によっては、フォルダーが引数としてファイル名に与えられ、フォルダー名にドットが含まれる場合の最後のポイントは、関数がフォルダーのドットの末尾を返すため、最初にユーザーが指定された名前がフォルダー名ではなくファイル名であることを確認することをお勧めします。
_splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w
これは Windows (プラットフォーム SDK) のみです。
これは私が思いついた解決策です。すると、@serengeor が投稿したものと似ていることに気付きました。
std::string
とで動作しますfind_last_of
が、基本的な考え方は、char
配列 とを使用するように変更しても機能しますstrrchr
。隠しファイルと、現在のディレクトリを表す余分なドットを処理します。プラットフォームに依存しません。
string PathGetExtension( string const & path )
{
string ext;
// Find the last dot, if any.
size_t dotIdx = path.find_last_of( "." );
if ( dotIdx != string::npos )
{
// Find the last directory separator, if any.
size_t dirSepIdx = path.find_last_of( "/\\" );
// If the dot is at the beginning of the file name, do not treat it as a file extension.
// e.g., a hidden file: ".alpha".
// This test also incidentally avoids a dot that is really a current directory indicator.
// e.g.: "alpha/./bravo"
if ( dotIdx > dirSepIdx + 1 )
{
ext = path.substr( dotIdx );
}
}
return ext;
}
単体テスト:
int TestPathGetExtension( void )
{
int errCount = 0;
string tests[][2] =
{
{ "/alpha/bravo.txt", ".txt" },
{ "/alpha/.bravo", "" },
{ ".alpha", "" },
{ "./alpha.txt", ".txt" },
{ "alpha/./bravo", "" },
{ "alpha/./bravo.txt", ".txt" },
{ "./alpha", "" },
{ "c:\\alpha\\bravo.net\\charlie.txt", ".txt" },
};
int n = sizeof( tests ) / sizeof( tests[0] );
for ( int i = 0; i < n; ++i )
{
string ext = PathGetExtension( tests[i][0] );
if ( ext != tests[i][1] )
{
++errCount;
}
}
return errCount;
}
これらの 2 つの関数を使用して、拡張子なしの拡張子とファイル名を取得します。
std::string fileExtension(std::string file){
std::size_t found = file.find_last_of(".");
return file.substr(found+1);
}
std::string fileNameWithoutExtension(std::string file){
std::size_t found = file.find_last_of(".");
return file.substr(0,found);
}
そしてregex
、特定の追加要件に対するこれらのアプローチ:
std::string fileExtension(std::string file){
std::regex re(".*[^\\.]+\\.([^\\.]+$)");
std::smatch result;
if(std::regex_match(file,result,re))return result[1];
else return "";
}
std::string fileNameWithoutExtension(std::string file){
std::regex re("(.*[^\\.]+)\\.[^\\.]+$");
std::smatch result;
if(std::regex_match(file,result,re))return result[1];
else return file;
}
regex メソッドによって満たされる追加の要件:
.config
ものである場合、拡張子は空の文字列になり、拡張子のないファイル名は.config
.編集:
追加の要件は、次の方法でも満たすことができます。
std::string fileExtension(const std::string& file){
std::string::size_type pos=file.find_last_of('.');
if(pos!=std::string::npos&&pos!=0)return file.substr(pos+1);
else return "";
}
std::string fileNameWithoutExtension(const std::string& file){
std::string::size_type pos=file.find_last_of('.');
if(pos!=std::string::npos&&pos!=0)return file.substr(0,pos);
else return file;
}
ノート:
上記の関数では、(パスではなく) ファイル名のみを渡します。
strstrを使用してみてください
char* lastSlash;
lastSlash = strstr(filename, ".");
パス/ファイル名を文字列として受け取り、拡張子を文字列として返す関数を次に示します。すべて標準の C++ であり、ほとんどのプラットフォームでクロスプラットフォームで動作するはずです。
ここでの他のいくつかの回答とは異なり、PathFindExtensions のドキュメントに基づいて、Windows の PathFindExtension が処理する奇妙なケースを処理します。
wstring get_file_extension( wstring filename )
{
size_t last_dot_offset = filename.rfind(L'.');
// This assumes your directory separators are either \ or /
size_t last_dirsep_offset = max( filename.rfind(L'\\'), filename.rfind(L'/') );
// no dot = no extension
if( last_dot_offset == wstring::npos )
return L"";
// directory separator after last dot = extension of directory, not file.
// for example, given C:\temp.old\file_that_has_no_extension we should return "" not "old"
if( (last_dirsep_offset != wstring::npos) && (last_dirsep_offset > last_dot_offset) )
return L"";
return filename.substr( last_dot_offset + 1 );
}
PathFindExtension() 関数を使用して、有効な tif ファイルかどうかを確認しました。
#include <Shlwapi.h>
bool A2iAWrapperUtility::isValidImageFile(string imageFile)
{
char * pStrExtension = ::PathFindExtension(imageFile.c_str());
if (pStrExtension != NULL && strcmp(pStrExtension, ".tif") == 0)
{
return true;
}
return false;
}
拡張子を最後のドットとその後の可能な文字と見なし、ディレクトリ区切り文字が含まれていない場合にのみ、次の関数は拡張子の開始インデックスを返します。拡張子が見つからない場合は -1 を返します。それができたら、拡張機能を削除したり、変更したり、チェックしたりなど、好きなことをすることができます。
long get_extension_index(string path, char dir_separator = '/') {
// Look from the end for the first '.',
// but give up if finding a dir separator char first
for(long i = path.length() - 1; i >= 0; --i) {
if(path[i] == '.') {
return i;
}
if(path[i] == dir_separator) {
return -1;
}
}
return -1;
}