1

在 C/C++ 中,如何从c:\Blabla - dsf\blup\AAA - BBB\blabla.bmp子字符串中提取AAABBB

-即在文件名的最后一个文件夹中提取之前和之后的部分。

提前致谢。

(PS:如果可能的话,没有框架 .net 或类似的东西,我很容易迷路)

4

5 回答 5

2

使用 std::string rfind rfind (char c, size_t pos = npos)

  1. 使用 rfind (pos1) 从末尾查找字符“\”
  2. 使用 rfind (pos2) 查找下一个字符 '\'
  3. 获取位置 pos2 和 pos1 之间的子字符串。为此使用子字符串函数。
  4. 查找字符 '-' (pos3)
  5. 提取 pos3 和 pos1、pos3 和 pos2 之间的 2 个子串
  6. 删除子字符串中的空格。

生成的子字符串将是 AAA 和 BBB

于 2013-05-17T08:24:26.033 回答
2
#include <iostream>
using namespace std;

#include <windows.h>
#include <Shlwapi.h> // link with shlwapi.lib

int main()
{
    char buffer_1[ ] = "c:\\Blabla - dsf\\blup\\AAA - BBB\\blabla.bmp"; 
    char *lpStr1 = buffer_1;

    // Remove the file name from the string
    PathRemoveFileSpec(lpStr1);
    string s(lpStr1);

    // Find the last directory name
    stringstream ss(s.substr(s.rfind('\\') + 1));

   // Split the last directory name into tokens separated by '-'
    while (getline(ss, s, '-')) 
        cout << s << endl;
}

评论中的解释。

这不会修剪前导空格 - 在输出中 - 如果你也想这样做 - 检查这个

于 2013-05-17T08:39:39.973 回答
2

这可以通过正则表达式相对容易地完成: std::regex如果你有 C++11;boost::regex如果您不这样做:

static std::regex( R"(.*\\(\w+)\s*-\s*(\w+)\\[^\\]*$" );
smatch results;
if ( std::regex_match( path, results, regex ) ) {
    std::string firstMatch = results[1];
    std::string secondMatch = results[2];
    //  ...
}

此外,您绝对应该拥有这些功能splittrim在工具包中:

template <std::ctype_base::mask test>
class IsNot
{
    std::locale ensureLifetime;
    std::ctype<char> const* ctype;  //  Pointer to allow assignment
public:
    Is( std::locale const& loc = std::locale() )
        : ensureLifetime( loc )
        , ctype( &std::use_facet<std::ctype<char>>( loc ) )
    {
    }
    bool operator()( char ch ) const
    {
        return !ctype->is( test, ch );
    }
};
typedef IsNot<std::ctype_base::space> IsNotSpace;

std::vector<std::string>
split( std::string const& original, char separator )
{
    std::vector<std::string> results;
    std::string::const_iterator current = original.begin();
    std::string::const_iterator end = original.end();
    std::string::const_iterator next = std::find( current, end, separator );
    while ( next != end ) {
        results.push_back( std::string( current, next ) );
        current = next + 1;
        next = std::find( current, end, separator );
    }
    results.push_back( std::string( current, next ) );
    return results;
}

std::string
trim( std::string const& original )
{
    std::string::const_iterator end
        = std::find_if( original.rbegin(), original.rend(), IsNotSpace() ).base();
    std::string::const_iterator begin
        = std::find_if( original.begin(), end, IsNotSpace() );
    return std::string( begin, end );
}

(这些只是您在这里需要的。您显然需要 IsXxx 和 IsNotXxx 谓词的完整补充,可以根据正则表达式拆分的拆分,可以传递谓词对象的修剪,指定要修剪的内容, ETC。)

无论如何,应用splittrim应该是显而易见的给你你想要的。

于 2013-05-17T09:11:35.743 回答
2

这在纯 C 中完成了所有工作和验证:

int FindParts(const char* source, char** firstOut, char** secondOut)
{
const char* last        = NULL;
const char* previous    = NULL;
const char* middle      = NULL;
const char* middle1     = NULL;
const char* middle2     = NULL;
char* first;
char* second;

last = strrchr(source, '\\');
if (!last || (last  == source))
    return -1;
--last;
if (last == source)
    return -1;

previous = last;
for (; (previous != source) && (*previous != '\\'); --previous);
++previous;

{
    middle = strchr(previous, '-');
    if (!middle || (middle > last))
        return -1;

    middle1 = middle-1;
    middle2 = middle+1;
}

//  now skip spaces

for (; (previous != middle1) && (*previous == ' '); ++previous);
if (previous == middle1)
    return -1;
for (; (middle1 != previous) && (*middle1 == ' '); --middle1);
if (middle1 == previous)
    return -1;
for (; (middle2 != last) && (*middle2 == ' '); ++middle2);
if (middle2 == last)
    return -1;
for (; (middle2 != last) && (*last == ' '); --last);
if (middle2 == last)
    return -1;

first   = (char*)malloc(middle1-previous+1 + 1);
second  = (char*)malloc(last-middle2+1 + 1);
if (!first || !second)
{
    free(first);
    free(second);
    return -1;
}

strncpy(first, previous, middle1-previous+1);
first[middle1-previous+1] = '\0';
strncpy(second, middle2, last-middle2+1);
second[last-middle2+1] = '\0';

*firstOut   = first;
*secondOut  = second;

return 1;
}
于 2013-05-17T08:53:18.273 回答
1

普通的 C++ 解决方案(没有 boost,也没有 C++11),仍然是 James Kanze 的正则表达式解决方案(https://stackoverflow.com/a/16605408/1032277)是最通用和优雅的:

inline void Trim(std::string& source)
{
size_t position = source.find_first_not_of(" ");
if (std::string::npos != position)
    source = source.substr(position);
position = source.find_last_not_of(" ");
if (std::string::npos != position)
    source = source.substr(0, position+1);
}

inline bool FindParts(const std::string& source, std::string& first, std::string& second)
{
size_t last = source.find_last_of('\\');
if ((std::string::npos == last) || !last)
    return false;

size_t previous = source.find_last_of('\\', last-1);
if (std::string::npos == last)
    previous = -1;

size_t middle = source.find_first_of('-',1+previous);
if ((std::string::npos == middle) || (middle > last))
    return false;

first   = source.substr(1+previous, (middle-1)-(1+previous)+1);
second  = source.substr(1+middle, (last-1)-(1+middle)+1);

Trim(first);
Trim(second);

return true;
}
于 2013-05-17T15:06:25.950 回答