문제

문자열이 주어지면 "filename.conf", 확장 부분을 어떻게 확인하나요?

크로스 플랫폼 솔루션이 필요합니다.

도움이 되었습니까?

해결책

점이 두 개 이상 포함된 파일 이름을 관리해야 합니다.예: c:\.directoryname\file.name.with.too.many.dots.ext 에 의해 올바르게 처리되지 않습니다 strchr 또는 find.

내가 가장 좋아하는 것은 파일 시스템 라이브러리 부스트 확장(경로) 기능이 있는 것

다른 팁

너무 간단한 해결책인가요?

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

가장 좋은 방법은 이를 수행하는 코드를 작성하지 않고 기존 메서드를 호출하는 것입니다.창문에서는 PathFind확장 방법이 아마도 가장 간단할 것입니다.

그렇다면 왜 직접 작성하지 않으시겠습니까?

strrchr 예를 들어 보겠습니다. "c:\program files\AppleGate.Net eadme" 문자열에 해당 메서드를 사용하면 어떻게 될까요?확장자는 ".Net eadme"입니까?몇 가지 예제 사례에 작동하는 것을 작성하는 것은 쉽지만 모든 경우에 작동하는 것을 작성하는 것은 훨씬 어려울 수 있습니다.

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.a.b.c.d.e.s.mp3"와 같은 문자열에서도 항상 확장자를 반환합니다.

사실 가장 쉬운 방법은

char* ext;
ext = strrchr(filename,'.') 

기억해야 할 한 가지:만약에 '.' 파일 이름에 존재하지 않습니다. ext는 다음과 같습니다. NULL.

나는 오늘 이 질문을 우연히 발견했습니다. 비록 이미 작동하는 코드가 있었지만 어떤 경우에는 작동하지 않을 것이라는 것을 알았습니다.

일부 사람들은 이미 일부 외부 라이브러리 사용을 제안했지만 저는 학습 목적으로 직접 코드를 작성하는 것을 선호합니다.

일부 답변에는 처음에 사용했던 방법(마지막 "." 찾기)이 포함되어 있었지만 Linux에서는 숨겨진 파일/폴더가 "."로 시작한다는 것을 기억했습니다.따라서 파일이 숨겨져 있고 확장자가 없으면 전체 파일 이름이 확장자로 사용됩니다.이를 방지하기 위해 다음 코드를 작성했습니다.

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

나는 이것을 완전히 테스트하지는 않았지만 작동해야한다고 생각합니다.

_splitpath, _wsplitpath, _splitpath_s, _wsplitpath_w

Windows(플랫폼 SDK)에만 해당되는 것 같은데요?

C++17과 그 std::filesystem::path::extension (라이브러리는 Boost::filesystem의 후속 버전입니다.) 예를 들어 다음을 사용하는 것보다 구문을 더 표현력 있게 만들 수 있습니다. std::string.

#include <iostream>
#include <filesystem> // C++17
namespace fs = std::filesystem;

int main()
{
    fs::path filePath = "my/path/to/myFile.conf";
    if (filePath.extension() == ".conf") // Heed the dot.
    {
        std::cout << filePath.stem() << " is a valid type."; // Output: "myFile is a valid type."
    }
    else
    {
        std::cout << filePath.filename() << " is an invalid type."; // Output: e.g. "myFile.cfg is an invalid type"
    }
}

또한보십시오 표준::파일 시스템::경로::줄기, 표준::파일 시스템::경로::파일 이름.

std::string의 find/rfind를 사용하면 이 문제가 해결되지만, 경로 관련 작업을 많이 한다면 Boost::filesystem::path를 살펴봐야 합니다. 왜냐하면 원시 문자열 인덱스/반복자를 조작하는 것보다 코드가 훨씬 깔끔해지기 때문입니다.

Boost는 고품질이고 잘 테스트되었으며 (오픈 소스 및 상업적으로) 무료이며 완전히 이식 가능한 라이브러리이므로 Boost를 제안합니다.

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++ 모두에서 작동합니다.그리고 크로스 플랫폼.

좋은 답변이지만 대부분 문제가 있습니다.우선 좋은 대답은 경로 제목이 있는 완전한 파일 이름에 대해 작동해야 하며 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

"브라이언 뉴먼" 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));
}

어떤 경우에는 폴더가 파일 이름에 인수로 제공되고 폴더 이름에 점이 포함되어 있는 경우 함수는 폴더의 점 뒤에 오는 점을 반환하므로 사용자가 먼저 지정된 이름이 폴더 이름이 아니라 파일 이름인지 확인하는 것이 좋습니다.

System::String을 사용하는 NET/CLI 버전

   System::String^ GetFileExtension(System::String^ FileName)
   {
       int Ext=FileName->LastIndexOf('.');
       if( Ext != -1 )
           return FileName->Substring(Ext+1);
       return "";
   }

나는 함께 갈 것이다 boost::filesystem::extension 하지만 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"))
{ /* ... */ }

나는이 두 가지 기능을 사용하여 확대 그리고 확장자가 없는 파일 이름:

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;

}

정규식 메서드가 충족하는 추가 요구 사항:

  1. 만약에 파일 이름 처럼 .config 아니면 이런 것, 확대 빈 문자열이 되고 확장자가 없는 파일 이름 될거야 .config.
  2. 파일 이름에 확장자가 없으면 확장자는 빈 문자열이 됩니다. 확장자가 없는 파일 이름 될 것이다 파일 이름 변하지 않은.

편집하다:

추가 요구 사항은 다음을 통해 충족될 수도 있습니다.

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, ".");

또는 다음을 사용할 수 있습니다.

    char *ExtractFileExt(char *FileName)
    {
        std::string s = FileName;
        int Len = s.length();
        while(TRUE)
        {
            if(FileName[Len] != '.')
                Len--;
            else
            {
                char *Ext = new char[s.length()-Len+1];
                for(int a=0; a<s.length()-Len; a++)
                    Ext[a] = FileName[s.length()-(s.length()-Len)+a];
                Ext[s.length()-Len] = '\0';
                return Ext;
            }
        }
    }

이 코드는 크로스 플랫폼입니다

Qt 라이브러리를 사용한다면 다음을 시도해 볼 수 있습니다. Q파일정보'에스 접미사()

다음은 경로/파일 이름을 문자열로 취하고 확장자를 문자열로 반환하는 함수입니다.이는 모두 표준 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 );
}

이것이 제가 생각해낸 해결책입니다.그러다가 @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;
}

혹시 사용하게 된다면 포코 당신이 할 수 있는 도서관:

#include <Poco/Path.h>

...

std::string fileExt = Poco::Path("/home/user/myFile.abc").getExtension(); // == "abc"

확장자를 마지막 점으로 간주하고 그 뒤에 가능한 문자를 고려하지만 디렉터리 구분 문자가 포함되지 않은 경우에만 다음 함수는 확장자 시작 인덱스를 반환하거나 확장자가 없으면 -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;
}

유효한 tif 파일인지 확인하기 위해 PathFindExtension() 함수를 사용했습니다.

#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;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top