C++ 减少if-elseif语句的巧妙方法

C++ 减少if-elseif语句的巧妙方法,c++,string,if-statement,control-flow,C++,String,If Statement,Control Flow,我正在开发一个代码,将SpinBox限制为字母而不是整数。一切都很好,但如果有任何聪明的方法,我想减少if-elseif语句。这是密码 std::string AlphaSpinBox::textFromValue(int value) { // I feel the code is Ok but willing to change it if there is a better way. // value is restricted [0-25] inclusive.

我正在开发一个代码,将SpinBox限制为字母而不是整数。一切都很好,但如果有任何聪明的方法,我想减少if-elseif语句。这是密码

std::string AlphaSpinBox::textFromValue(int value) 
{
    // I feel the code is Ok but willing to change it if there is a better way.
    // value is restricted [0-25] inclusive. 
    std::string str("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    return std::string(str[value]);
}

int AlphaSpinBox::valueFromText(std::string &text) 
{
    // can I shorten the following?!
    // text is solely one letter (i.e. either upper or lower)
    if(text == 'A' || text == 'a')
        return 0;
    else if(text == 'B' || text == 'b' )
        return 1;
    else if(text == 'C' || text == 'c')
        return 2;
    else if(text == 'D' || text == 'd')
        return 3;
    ... to z letter
}

根据ASCII表,每个字母都有一个整数值。如果你查一下,你也会发现这些字母被方便地放在表格中:a到z都直接跟在一起,a到z也是一样

您可以先确定小写或大写,然后返回
text[0]-“a”
,或
text[0]-“b”

那么:

 if (text.size()>0 && std::isalpha(text[0]))
     return std::toupper(text[0])-'A'; 
 else return -1;    // or throw an exception 
这里有一个


工作原理:它首先检查字符串是否为空,以及第一个字符是否为字母。如果它是有效的,因为您不区分小写和大写,我们将转换字符。由于返回值是按字母顺序排列的,因此我们只需减去第一个字母

valueFromText
函数中,通过使用字符串的成员函数并稍微更改函数签名,可以消除多个
if
语句:

int valueFromText(const std::string& s, char c) {
    return s.find(std::toupper(static_cast<unsigned char>(c)));
}
int-valueFromText(const-std::string&s,char-c){
返回s.find(std::toupper(static_cast(c));
}

编写一个带有静态成员的小型类或结构(
std::map
-
查找表
)&某些充当包装器的静态方法在您的情况下肯定会起作用。代码的使用相当干净、可读、易于使用,应该是可移植和可重用的


注意:-如果系统的字符代码是按顺序定义的,则这将起作用;否则,您将需要一些其他机制来初始化静态映射


AlphaSpinBox.h

#ifndef ALPHA_SPIN_BOX_H
#define ALPHA_SPIN_BOX_H

#include <string>
#include <cctype>
#include <map>

struct AlphaSpinBox {    
    // static table
    static std::map<unsigned, std::string> table_;    
    // Must be called first
    static void initializeMap();    
    // helper function
    static std::string toUpper( const std::string& str );    
    // get string from value
    static std::string textFromValue( const unsigned& val );        
    // get value from string
    static unsigned valueFromText( const std::string& text );

    // other member's, functions etc. that you may have for this class
};

#endif // !ALPHA_SPIN_BOX_H
\ifndef ALPHA\u SPIN\u BOX\H
#定义阿尔法旋转盒
#包括
#包括
#包括
结构AlphaSpinBox{
//静态表
静态std::映射表;
//必须先打电话
静态无效初始化映射();
//辅助函数
静态std::string-toUpper(const-std::string&str);
//从值中获取字符串
静态标准::字符串textFromValue(const unsigned&val);
//从字符串中获取值
静态无符号值fromtext(const std::string和text);
//您可能拥有的该类的其他成员、函数等
};
#endif/!阿尔法旋转盒

AlphaSpinBox.cpp

#include "AlphaSpinBox.h"

// define static member
std::map<unsigned, std::string> AlphaSpinBox::table_;

void AlphaSpinBox::initializeMap() {
    // Could do some checks here to see if this function has not been called
    // then display a message to the user that this function needs to be called first;
    // and to check if it has already been called once before; warning the user
    // that this method should only initialize the map once per application run.
    static char c = 'A';
    static std::string str;
    for ( unsigned n = 0; n < 26; n++ ) {
        str.assign( &c );
        table_.insert( std::make_pair( n, str ) );
        c++;
    }
}

std::string AlphaSpinBox::toUpper( const std::string& str ) {
    std::string result = str;
    std::transform( str.begin(), str.end(), result.begin(), ::toupper );
    return result;
}

std::string AlphaSpinBox::textFromValue( const unsigned& val ) {
    // you could check to see if val is within range before returning...
    return table_[val];
}

unsigned AlphaSpinBox::valueFromText( const std::string& text ) {
    std::string upper = toUpper( text );
    for ( auto pair : table_ ) {
        if ( upper == pair.second ) {
            return pair.first;
        }
    }
    return -1;
}
#include <string>
#include <iostream>
#include "AlphaSpinBox.h"

int main() {

    // Must Be Called First
    AlphaSpinBox::initializeMap();

    // Remember that the map first entry's key starts at 0 and not 1
    std::cout << "The number 8 has letter: " 
              << AlphaSpinBox::textFromValue( 8 ) 
              << std::endl;

    std::cout << "The letter Q has value: " 
              << AlphaSpinBox::valueFromText( std::string( "Q" ) ) 
              << std::endl;

    // check case for lower cases being converted to upper case
    std::cout << "The letter j has value: " 
              << AlphaSpinBox::valueFromText( std::string( "j" ) ) 
              << std::endl;

    std::cout << "\nPress any key and enter to quit." << std::endl;
    char q;
    std::cin >> q;
    return 0;
}
#包括“AlphaSpinBox.h”
//定义静态成员
标准::映射AlphaSpinBox::表;
void AlphaSpinBox::initializeMap(){
//可以在此执行一些检查,以查看是否尚未调用此函数
//然后向用户显示需要首先调用此函数的消息;
//并检查之前是否已调用过一次;警告用户
//此方法在每次应用程序运行时只应初始化映射一次。
静态字符c='A';
静态std::字符串str;
for(无符号n=0;n<26;n++){
str.assign&c;
表1.插入(std::生成配对(n,str));
C++;
}
}
std::string AlphaSpinBox::toUpper(const std::string&str){
std::string result=str;
std::transform(str.begin()、str.end()、result.begin()、::toupper);
返回结果;
}
std::string AlphaSpinBox::textFromValue(const unsigned&val){
//您可以在返回之前检查val是否在范围内。。。
返回表_val];
}
无符号AlphaSpinBox::valueFromText(常量std::字符串和文本){
std::string upper=toUpper(文本);
用于(自动配对:表格){
如果(上限==成对秒){
返回对。第一;
}
}
返回-1;
}

main.cpp

#include "AlphaSpinBox.h"

// define static member
std::map<unsigned, std::string> AlphaSpinBox::table_;

void AlphaSpinBox::initializeMap() {
    // Could do some checks here to see if this function has not been called
    // then display a message to the user that this function needs to be called first;
    // and to check if it has already been called once before; warning the user
    // that this method should only initialize the map once per application run.
    static char c = 'A';
    static std::string str;
    for ( unsigned n = 0; n < 26; n++ ) {
        str.assign( &c );
        table_.insert( std::make_pair( n, str ) );
        c++;
    }
}

std::string AlphaSpinBox::toUpper( const std::string& str ) {
    std::string result = str;
    std::transform( str.begin(), str.end(), result.begin(), ::toupper );
    return result;
}

std::string AlphaSpinBox::textFromValue( const unsigned& val ) {
    // you could check to see if val is within range before returning...
    return table_[val];
}

unsigned AlphaSpinBox::valueFromText( const std::string& text ) {
    std::string upper = toUpper( text );
    for ( auto pair : table_ ) {
        if ( upper == pair.second ) {
            return pair.first;
        }
    }
    return -1;
}
#include <string>
#include <iostream>
#include "AlphaSpinBox.h"

int main() {

    // Must Be Called First
    AlphaSpinBox::initializeMap();

    // Remember that the map first entry's key starts at 0 and not 1
    std::cout << "The number 8 has letter: " 
              << AlphaSpinBox::textFromValue( 8 ) 
              << std::endl;

    std::cout << "The letter Q has value: " 
              << AlphaSpinBox::valueFromText( std::string( "Q" ) ) 
              << std::endl;

    // check case for lower cases being converted to upper case
    std::cout << "The letter j has value: " 
              << AlphaSpinBox::valueFromText( std::string( "j" ) ) 
              << std::endl;

    std::cout << "\nPress any key and enter to quit." << std::endl;
    char q;
    std::cin >> q;
    return 0;
}
#包括
#包括
#包括“AlphaSpinBox.h”
int main(){
//必须先打电话
AlphaSpinBox::initializeMap();
//请记住,映射第一个条目的键从0开始,而不是从1开始

下面可能是更容易理解的一个:

int AlphaToNumeric(string &value)
{
    return (value.front() >= 'A' && value.front() <= 'Z') ? value.front() - 'A' : (value.front() >= 'a' && value.front() <= 'z') ? value.front() - 'a' : -1;
}
int字母数字(字符串和值)
{

return(value.front()>='A'&&value.front()='A'&&value.front()=65&&value.front()=97&&value.front()不确定此限定符是否为“聪明”,但假设您只想查看
文本的第一个字符,您只需执行以下操作即可

#include <string>
#include <cctype>

int AlphaSpinBox::valueFromText(const std::string &text) 
{
     std::string str("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
     int retval = -2;
     if (text.size() > 0)
     {
         char c = std::toupper(text[0]);
         std::size_t index = str.find(c);
         retval = (index != std::string::npos) ? int(index) : -1;
     }
     return retval;
}

使用这些版本中的一个或另一个的选择取决于代码不会被移植到具有字母顺序的字符集的系统的置信度。

您可以考虑<代码> STD::ToWoW。注意,对于C库函数,参数必须不是负的(除了EOF)。因此,在实践中,将参数强制转换为
unsigned char
,以避免未定义的行为。可能会有帮助:(我怀疑这是最好的方法。)
int-valueFromText(std::string&text){std::string str(“abcdefghijklmnopqrstuvxyz”);返回str.find(std::toupper(text[0]);}
如果您认为您的字符集始终具有连续且有序的字母字符是合理的,那么您也可以只返回字符-第一个字母字符。
如果(text=='A'| text=='A')
无法编译,因为您正在将
std::string
与单个
char
进行比较。如果它是
char
类型,并且保证在a-z或a-z范围内,可以使用简单的
返回std::toupper(text)-'a';
。您可以预先填充一个查找表,然后说
返回表[text]
。OP没有说ASCII是有保证的。@KerrekSB使用EBCDIC是提问者倾向于在前面提到的那种东西。这可能不适用于像这样的所有字符集EBCDIC@NathanOliver事实上,假设大写字母是顺序的,ASCII、unicode、ISO 8859、Windows 125x和大多数ot都是这样她说。这不是EBCDIC的情况,据我所知,EBCDIC是唯一一个A-Z不按顺序排列的集合。幸运的是,它现在不太常见。