有没有更好的方法来确定多个角色范围?

时间:2016-07-13 04:55:25

标签: c range ascii

我目前正在用C编写代码,它从整个ASCII可用字符中选择符号和数字。 作为程序员的初学者,我经常做

if ((i > 25 && i < 50) || (i > 100 && i < 200)) { contents } 

变量i在25~50,100~200(不包括)之间,以适应条件。

如果我想设置多个范围,如32~64(! to @)和91~96([ to `)和123~126({ to ~)那么会有更好的范围(意思是更短或更简单的代码)或者我应该坚持使用这种方法,继续按照上面的代码添加每个范围?

7 个答案:

答案 0 :(得分:14)

对于您的具体情况,<ctype.h> collection of functions会执行

if (isprint(i) && !isalpha(i))

额外奖励:它甚至适用于非ascii系统。

答案 1 :(得分:2)

您可以编写一个函数来检查该值是否属于任何给定范围:

struct Range {
        int min;
        int max;
};

bool in_ranges(int character, struct Range *ranges, size_t num_ranges) {
        for(size_t i = 0; i < num_ranges; ++i) {
                if(ranges[i].min < character && character < ranges[i].max)
                        return true;
        }
        return false;
}

int main() {
        struct Range rngs[] = {{25,50}, {100,200}};
        bool at_sign_si_in_range = in_ranges('@', rngs, 2);
        return 0;
}

它使编辑范围更加简单并提高了可读性。 此外,如果您继续在条件子句中编写所有范围,如示例所示,请考虑检查范围,如

lower_bound < value && value < upper_bound

它看起来像数学符号(x < a < y),看起来也更容易阅读。

答案 2 :(得分:1)

如果使用单字节字符,则可以使用标志数组获得更好的性能,设置单个位或整个字节以指示其中一个范围内的字符值。

如果您正在为支持SSE 4.2指令的Intel处理器编写代码,您可能需要考虑使用PCMPISTRI或类似代码,它可以在一条指令中将多达16个单字节字符与多达8个不同的范围进行比较。

答案 3 :(得分:1)

我的回答是&#34;它取决于&#34;。 :)

如果var defaultBounds = new google.maps.LatLngBounds(new google.maps.LatLng(south, west), new google.maps.LatLng(north, east)); 和来自isalpha()的朋友做了你想做的事,那么绝对使用它们。

但如果不是......

如果你只有两个范围,就像你的示例代码段一样,我觉得它看起来太乱了。如果还有更多,可以将范围测试放在(内联)函数中,以减少一次可见的布尔值:

ctype.h

(如果您认为需要保存屏幕区域,请将其命名为if (in_range(val, a1, b1) || in_range(val, a2, b2) || ... ) 。)

如果范围可能在运行时更改,或者有很多范围,请将限制放在B(n,a,b)中并循环显示其中的数组。如果真的有很多,请对列表进行排序,并使用它做一些聪明的事情,比如在下限(或其他)上进行二元搜索。但是对于少数人来说,我不会打扰。

如果允许值的总范围很小(如值为0..255的无符号字符),但是单独的&#34;范围的数量&#34;很大(&#34;所有那些具有素数值&#34;),然后制作值的表(位图),并对其进行测试。以您喜欢的方式生成表格。 (struct可能就像这样实现)

isalpha()

答案 4 :(得分:0)

你可以在宏或内联函数中隐藏l<x && x<h的重复,但我发现它很少值得 - 它不像Python l<x<h语法那样可读,并且很快就会失控一旦你开始拥有所有包容性边界可能性的宏。要么最终得到一个可笑的长命名约定(between_inc_incbetween_inc_exc,......哪一种方法可以将检查放在首位)或者让读者想知道你的范围检查(“{ {1}} ...它是between(i, 50, 100)范围吗?一个[,)一个?(检查代码)nope它是[,]“),如果你正在寻找它,这很可怕一个错误。

OTOH,我知道滥用“单字母宏”,我确切地定义了它们需要的位置和方式,并且在之后立即未定义。虽然它们可能看起来很难看,但关键在于它们非常本地并完全按需要做,所以没有浪费时间查找它们,没有神秘的参数,它们可以分解出大量重复计算

在你的情况下,如果列表很长,我可以

(,)

(永远不要在标题中这样做!)

可读性的一个好处就是使用字符文字而不是ASCII数字:例如,如果你想要a-z范围,请#define B(l, h) ((l)<i) && (i<(h)) || if(B(25,50) B(100,200) B(220, 240) 0) ... #undef B

您似乎想要排除按字母顺序排列和不可打印的字符:您可以使用

执行此操作
'a'<=i && i<='z'

答案 5 :(得分:0)

您可以编写如下函数:

  public class MainActivity extends Activity {

     Button button,btnAdd,btnSub;
     EditText val1,val2;

    double num1,num2,res;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        val1 = (EditText) findViewById(R.id.txtVal1);
        val2 = (EditText) findViewById(R.id.txtVal2);
        btnAdd = (Button) findViewById(R.id.btnSum);
        btnSub = (Button) findViewById(R.id.btnDiff);

        btnAdd.setOnClickListener(new OnClickListener(){

          public void onClick(View view) {
              num1 = Double.parseDouble(val1.getText().toString());
              num2 = Double.parseDouble(val2.getText().toString());
              res = num1 + num2;
              Toast.makeText(MainActivity.this, String.valueOf(res), Toast.LENGTH_SHORT).show();
              }
          });
       }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

然后您可以使用此功能并保持代码清洁和简单。

答案 6 :(得分:0)

class RangeCollection
{
    std::vector<int> ranges;
public:
    void AddRange(int lowerBound, int upperBound)
    {
        vector.push_back(lowerBound);
        vector.push_back(upperBound);
    }

    bool IsInRange(int num)
    {
        for(int i=0; i<ranges.size()-1; i+=2)
        {
            if(num>ranges[i] && num<ranges[i+1])return true;
        }
     return false;
    }
};

您可以调用AddRange添加任意数量的范围,然后您可以检查数字是否在范围内。

RangeCollection rc;
rc.AddRange(20,25);
rc.IsInRange(22);//returns true