C++;-如何提取字符串中的有效字符串? 强>问题:我试图用C++从游戏名中提取一个有效的游戏模式,遗迹保卫战。

C++;-如何提取字符串中的有效字符串? 强>问题:我试图用C++从游戏名中提取一个有效的游戏模式,遗迹保卫战。,c++,string,parsing,extraction,C++,String,Parsing,Extraction,详细信息: #include <cstdarg> #include <algorithm> #include <iostream> #include <string> #include <sstream> #include <map> #include <vector> std::map<std::string, std::vector<std::string> > ModeCompat

详细信息:

#include <cstdarg>
#include <algorithm>
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <vector>

std::map<std::string, std::vector<std::string> > ModeCompatibilityMap;

static const unsigned int PrimaryModesCount = 11;
static char *PrimaryModes[] = { 
    "ap", "ar", "tr", "mr", "lm", "rd", "vr", "el", "sd", "cm", "cd"
};

static const unsigned int SecondaryModesCounts = 19;
static char *SecondaryModes[] = {
    "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np",
    "sc", "om", "nt", "nm", "nb", "ro", "mo", "sp"
};

static const unsigned int MiscModesCount = 8;
static char *MiscModes[] = {
    "ns", "nr", "ts", "pm", "oi", "mi", "fr", "so" 
};

std::vector<std::string> Vectorize( int count, ... ) {
    std::vector<std::string> result;

    va_list vl;
    va_start( vl, count );

    for ( int i = 0; i < count; ++i ) {
        char *buffer = va_arg( vl, char * );
        result.push_back( buffer );
    }

    va_end( vl );

    return result;
}

void InitializeModeCompatibilityMap() {
    // Primary
    ModeCompatibilityMap["ar"] = Vectorize( 1, "rv" );
    ModeCompatibilityMap["tr"] = Vectorize( 2, "dm", "rv" );
    ModeCompatibilityMap["mr"] = Vectorize( 8, "dm", "rv", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["lm"] = Vectorize( 18, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo" );
    ModeCompatibilityMap["rd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["vr"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["el"] = Vectorize( 18, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo" );
    ModeCompatibilityMap["sd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["cm"] = Vectorize( 19, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo", "sp" );
    ModeCompatibilityMap["cd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );   
    // Secondary
    ModeCompatibilityMap["dm"] = Vectorize( 8, "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["rv"] = Vectorize( 2, "dm", "sh" );
    ModeCompatibilityMap["mm"] = Vectorize( 2, "dm", "sh" );
    ModeCompatibilityMap["sh"] = Vectorize( 3, "dm", "rv", "mm" );
    ModeCompatibilityMap["aa"] = Vectorize( 3, "dm", "ai", "as" );
    ModeCompatibilityMap["ai"] = Vectorize( 3, "dm", "aa", "as" );
    ModeCompatibilityMap["as"] = Vectorize( 3, "dm", "aa", "ai" );
    ModeCompatibilityMap["ro"] = Vectorize( 2, "dm", "mo" );
    ModeCompatibilityMap["mo"] = Vectorize( 2, "dm", "ro" );
}

std::vector<std::string> Tokenize( const std::string &string ) {
    std::vector<std::string> tokens;
    std::string token;
    std::stringstream ss( string );

    while ( ss >> token ) {
        tokens.push_back( token );
    }

    return tokens;
}

void SanitizeString( std::string &in ) {
    std::transform( in.begin(), in.end(), in.begin(), tolower );

    for ( size_t i = 0; i < in.size(); ++i ) {
        if ( in[i] < 'a' || in[i] > 'z' ) {
            in.erase( i--, 1 );
        }
    }
}

std::vector<std::string> SplitString( const std::string &in, int count ) {
    std::vector<std::string> result;

    if ( in.length() % count != 0 ) {
        return result;
    }

    for ( std::string::const_iterator i = in.begin(); i != in.end(); i += count ) {
        result.push_back( std::string( i, i + count ) );
    }

    return result;
}

bool IsPrimaryGameMode( const std::string &in ) {
    for ( int i = 0; i < PrimaryModesCount; ++i ) {
        if ( strcmp( PrimaryModes[i], in.c_str() ) == 0 ) {
            return true;
        }
    }

    return false;
}

bool IsSecondaryGameMode( const std::string &in ) {
    for ( int i = 0; i < SecondaryModesCounts; ++i ) {
        if ( strcmp( SecondaryModes[i], in.c_str() ) == 0 ) {
            return true;
        }
    }

    return false;
}

bool IsMiscGameMode( const std::string &in ) {
    for ( int i = 0; i < MiscModesCount; ++i ) {
        if ( strcmp( MiscModes[i], in.c_str() ) == 0 ) {
            return true;
        }
    }

    return false;
}

bool IsValidGameMode( std::string in, std::string &out ) {
    // 1. Strip all non-letters from the string and convert it to lower-case
    SanitizeString( in );

    // 2. Confirm that it is a multiple of 2
    if ( in.length() == 0 || in.length() % 2 != 0 ) {
        return false;
    }

    // 3. Split the string further into strings of 2 characters
    std::vector<std::string> modes = SplitString( in, 2 );

    // 4. Verify that each game mode is a valid game mode and is compatible with the others
    bool primaryModeSet = false;

    for ( size_t i = 0; i < modes.size(); ++i ) {
        if ( IsPrimaryGameMode( modes[i] ) || IsSecondaryGameMode( modes[i] ) ) {
            if ( IsPrimaryGameMode( modes[i] ) ) {
                if ( primaryModeSet ) {
                    return false;
                }

                primaryModeSet = true;
            }

            if ( ModeCompatibilityMap.count( modes[i] ) > 0 ) {
                std::vector<std::string> badModes = ModeCompatibilityMap[modes[i]];

                for ( size_t j = 0; j < badModes.size(); ++j ) {
                    for ( size_t k = 0; k < modes.size(); ++k ) {
                        if ( badModes[j] == modes[k] ) {
                            return false;
                        }
                    }
                }
            }
        } else if ( !IsMiscGameMode( modes[i] ) ) {
            return false;
        }
    }

    // 5. Assign the output variable with the game mode and return true
    out = in;

    return true;
}

std::string ExtractGameMode( const std::string &gameName ) {
    std::vector<std::string> tokens = Tokenize( gameName );

    std::string gameMode;

    for ( size_t i = 0; i < tokens.size(); ++i ) {
        if ( IsValidGameMode( tokens[i], gameMode ) ) {
            return gameMode;
        }
    }

    return "";
}

int main( int argc, char *argv[] ) {
    InitializeModeCompatibilityMap();

    std::string gameName = "DotA v6.60 -RDEM USA/CA LC";
    std::string gameMode = ExtractGameMode( gameName );

    std::cout << "Name: " << gameName << std::endl;
    std::cout << "Mode: " << gameMode << std::endl;

    return 0;
}
  • 游戏名称最多可包含31个字符
  • 有三种游戏模式类别:主要、次要和杂项
    • 只能选择1个主要游戏模式
    • 某些主要游戏模式与某些次要游戏模式不兼容
    • 某些辅助游戏模式与其他辅助游戏模式不兼容
    • 其他游戏模式可与所有其他游戏模式组合
以下是各种游戏模式的列表,图表显示了每种模式与哪些次要模式兼容(X表示不兼容):

示例:以下是一些示例输入,以及所需的输出:

“DotA v6.60-RDSOSP USA/CA LC!”->“RDSOSP”

“DOTA AREMDM USA LC”->“AREMDM”

“DotA v6.60-ApEmDuSpId USA BL”->“ApEmDuSpId”

注意:解决方案不一定要提供实际代码、伪代码,甚至只是解释如何处理它,这是可以接受的,也是首选的。此外,解决方案需要足够灵活,我可以添加另一个游戏模式相当容易。同样可以安全地假设,在游戏名称中,游戏模式始终以主游戏模式开始


结果:

#include <cstdarg>
#include <algorithm>
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <vector>

std::map<std::string, std::vector<std::string> > ModeCompatibilityMap;

static const unsigned int PrimaryModesCount = 11;
static char *PrimaryModes[] = { 
    "ap", "ar", "tr", "mr", "lm", "rd", "vr", "el", "sd", "cm", "cd"
};

static const unsigned int SecondaryModesCounts = 19;
static char *SecondaryModes[] = {
    "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np",
    "sc", "om", "nt", "nm", "nb", "ro", "mo", "sp"
};

static const unsigned int MiscModesCount = 8;
static char *MiscModes[] = {
    "ns", "nr", "ts", "pm", "oi", "mi", "fr", "so" 
};

std::vector<std::string> Vectorize( int count, ... ) {
    std::vector<std::string> result;

    va_list vl;
    va_start( vl, count );

    for ( int i = 0; i < count; ++i ) {
        char *buffer = va_arg( vl, char * );
        result.push_back( buffer );
    }

    va_end( vl );

    return result;
}

void InitializeModeCompatibilityMap() {
    // Primary
    ModeCompatibilityMap["ar"] = Vectorize( 1, "rv" );
    ModeCompatibilityMap["tr"] = Vectorize( 2, "dm", "rv" );
    ModeCompatibilityMap["mr"] = Vectorize( 8, "dm", "rv", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["lm"] = Vectorize( 18, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo" );
    ModeCompatibilityMap["rd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["vr"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["el"] = Vectorize( 18, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo" );
    ModeCompatibilityMap["sd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["cm"] = Vectorize( 19, "dm", "rv", "mm", "du", "sh", "aa", "ai", "as", "id", "em", "np", "sc", "om", "nt", "nm", "nb", "ro", "mo", "sp" );
    ModeCompatibilityMap["cd"] = Vectorize( 9, "dm", "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );   
    // Secondary
    ModeCompatibilityMap["dm"] = Vectorize( 8, "rv", "mm", "sh", "aa", "ai", "as", "ro", "mo" );
    ModeCompatibilityMap["rv"] = Vectorize( 2, "dm", "sh" );
    ModeCompatibilityMap["mm"] = Vectorize( 2, "dm", "sh" );
    ModeCompatibilityMap["sh"] = Vectorize( 3, "dm", "rv", "mm" );
    ModeCompatibilityMap["aa"] = Vectorize( 3, "dm", "ai", "as" );
    ModeCompatibilityMap["ai"] = Vectorize( 3, "dm", "aa", "as" );
    ModeCompatibilityMap["as"] = Vectorize( 3, "dm", "aa", "ai" );
    ModeCompatibilityMap["ro"] = Vectorize( 2, "dm", "mo" );
    ModeCompatibilityMap["mo"] = Vectorize( 2, "dm", "ro" );
}

std::vector<std::string> Tokenize( const std::string &string ) {
    std::vector<std::string> tokens;
    std::string token;
    std::stringstream ss( string );

    while ( ss >> token ) {
        tokens.push_back( token );
    }

    return tokens;
}

void SanitizeString( std::string &in ) {
    std::transform( in.begin(), in.end(), in.begin(), tolower );

    for ( size_t i = 0; i < in.size(); ++i ) {
        if ( in[i] < 'a' || in[i] > 'z' ) {
            in.erase( i--, 1 );
        }
    }
}

std::vector<std::string> SplitString( const std::string &in, int count ) {
    std::vector<std::string> result;

    if ( in.length() % count != 0 ) {
        return result;
    }

    for ( std::string::const_iterator i = in.begin(); i != in.end(); i += count ) {
        result.push_back( std::string( i, i + count ) );
    }

    return result;
}

bool IsPrimaryGameMode( const std::string &in ) {
    for ( int i = 0; i < PrimaryModesCount; ++i ) {
        if ( strcmp( PrimaryModes[i], in.c_str() ) == 0 ) {
            return true;
        }
    }

    return false;
}

bool IsSecondaryGameMode( const std::string &in ) {
    for ( int i = 0; i < SecondaryModesCounts; ++i ) {
        if ( strcmp( SecondaryModes[i], in.c_str() ) == 0 ) {
            return true;
        }
    }

    return false;
}

bool IsMiscGameMode( const std::string &in ) {
    for ( int i = 0; i < MiscModesCount; ++i ) {
        if ( strcmp( MiscModes[i], in.c_str() ) == 0 ) {
            return true;
        }
    }

    return false;
}

bool IsValidGameMode( std::string in, std::string &out ) {
    // 1. Strip all non-letters from the string and convert it to lower-case
    SanitizeString( in );

    // 2. Confirm that it is a multiple of 2
    if ( in.length() == 0 || in.length() % 2 != 0 ) {
        return false;
    }

    // 3. Split the string further into strings of 2 characters
    std::vector<std::string> modes = SplitString( in, 2 );

    // 4. Verify that each game mode is a valid game mode and is compatible with the others
    bool primaryModeSet = false;

    for ( size_t i = 0; i < modes.size(); ++i ) {
        if ( IsPrimaryGameMode( modes[i] ) || IsSecondaryGameMode( modes[i] ) ) {
            if ( IsPrimaryGameMode( modes[i] ) ) {
                if ( primaryModeSet ) {
                    return false;
                }

                primaryModeSet = true;
            }

            if ( ModeCompatibilityMap.count( modes[i] ) > 0 ) {
                std::vector<std::string> badModes = ModeCompatibilityMap[modes[i]];

                for ( size_t j = 0; j < badModes.size(); ++j ) {
                    for ( size_t k = 0; k < modes.size(); ++k ) {
                        if ( badModes[j] == modes[k] ) {
                            return false;
                        }
                    }
                }
            }
        } else if ( !IsMiscGameMode( modes[i] ) ) {
            return false;
        }
    }

    // 5. Assign the output variable with the game mode and return true
    out = in;

    return true;
}

std::string ExtractGameMode( const std::string &gameName ) {
    std::vector<std::string> tokens = Tokenize( gameName );

    std::string gameMode;

    for ( size_t i = 0; i < tokens.size(); ++i ) {
        if ( IsValidGameMode( tokens[i], gameMode ) ) {
            return gameMode;
        }
    }

    return "";
}

int main( int argc, char *argv[] ) {
    InitializeModeCompatibilityMap();

    std::string gameName = "DotA v6.60 -RDEM USA/CA LC";
    std::string gameMode = ExtractGameMode( gameName );

    std::cout << "Name: " << gameName << std::endl;
    std::cout << "Mode: " << gameMode << std::endl;

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
映射模式兼容性映射;
静态常数unsigned int primarymodescont=11;
静态字符*主模式[]={
“ap”、“ar”、“tr”、“mr”、“lm”、“rd”、“vr”、“el”、“sd”、“cm”、“cd”
};
静态常量unsigned int secondary modesconts=19;
静态字符*二次模式[]={
“dm”、“rv”、“mm”、“du”、“sh”、“aa”、“ai”、“as”、“id”、“em”、“np”,
“sc”、“om”、“nt”、“nm”、“nb”、“ro”、“mo”、“sp”
};
静态常量unsigned int miscmodescont=8;
静态字符*MiscModes[]={
“ns”、“nr”、“ts”、“pm”、“oi”、“mi”、“fr”、“so”
};
向量向量化(整数计数,…){
std::向量结果;
va_列表vl;
va_启动(vl,计数);
对于(int i=0;i>令牌){
代币。推回(代币);
}
归还代币;
}
void SanitizeString(标准::字符串和输入){
std::transform(in.begin()、in.end()、in.begin()、tolower);
对于(大小i=0;i'z'中){
in.擦除(i--,1);
}
}
}
std::vector SplitString(常量std::string&in,int count){
std::向量结果;
如果(in.length()%count!=0){
返回结果;
}
for(std::string::const_迭代器i=in.begin();i!=in.end();i+=count){
result.push_back(std::string(i,i+count));
}
返回结果;
}
bool isprimary游戏模式(const std::string&in){
对于(int i=0;i bool IsSecondaryValidWithPrimary(unsigned int primaryIndex, unsigned int secondaryIndex)
 {
     static bool secondaryValidWithPrimary[numPrimaryModes][numSecondaryModes] = {...}

     if (primaryIndex < numPrimaryModes && secondaryIndex < numSecondaryModes)
     {
         return secondaryValidWithPrimary[primaryIndex][secondaryIndex]
     }
     else
     {
         //... this should never happen, throw your favorite exception
     }
 }
map<const char*, bool> mapSecondaryCompatibility;

struct tGameType
{
    char szName[3];
    mapSecondaryCompatibility m_compat;
}