如何使C语言中的条件语句更加简洁?

6

我有一个代码片段,其中使用了if-else if-else块。我想知道是否有任何潜在方法可以缩短冗长的条件语句else if (cardLength == 16) && (numberArray[0] == 5 && (numberArray[1] == 1 || numberArray[1] == 2 || numberArray[1] == 3 || numberArray[1] == 4 || numberArray[1] == 5)),例如,在不改变逻辑的情况下。在Python中,我可以这样做:if (cardLength == 16) and (numberArray[0:2] in range(51,56))。在C语言中,有没有特定的语法糖可以用于此目的?

if (cardLength == 15) &&
   (numberArray[0] == 3 && (numberArray[1] == 4 || numberArray[1] == 7))
{
    printf("AMEX\n");
}
else if (cardLength == 16) &&
        (numberArray[0] == 5 && (numberArray[1] == 1 || numberArray[1] == 2 || numberArray[1] == 3 || numberArray[1] == 4 || numberArray[1] == 5))
{
    printf("MASTERCARD\n");
}
else if (cardLength == 13) && (numberArray[0] == 4)
{
    printf("VISA\n");
}
else
{
    printf("INVALID\n");
}

3
可以将 numberArray[1] == 1 || numberArray[1] == 2 || numberArray[1] == 3 || numberArray[1] == 4 || numberArray[1] == 5 改为 numberArray[1] >= 1 && numberArray[1] <= 5,意思相同但更简洁。 - Some programmer dude
4
另外,拥有更加“紧凑”的代码并不总是可取的,因为这往往会使得代码难以阅读和理解,并且维护起来也更加困难。编译器也非常智能,因此更加“紧凑”的代码经过编译器优化后,并不一定比其他代码更加有效。 - Some programmer dude
2
我认为你不能在不改变“技术”的情况下有效地压缩该代码。也就是说,你可以进行一些类似于正则表达式的验证或构建模式匹配DSL,但你现有的代码已经很好地工作并且非常简洁。 - Morten Jensen
2
我的 Visa 卡有 16 位数字。你确定这是正确的吗? - user253751
2
代码由于if语句中缺少括号而无法编译。 - Ian Abbott
显示剩余7条评论
4个回答

4

将其放入(静态)函数中。暂时不要考虑性能/优化。


static char *card_leng_type2string( unsigned len, int *arr)
{
if (len == 15 && arr[0] == 3 && arr[1] == 4 ) return "AMEX";
if (len == 15 && arr[0] == 3 && arr[1] == 7 ) return "AMEX";
 
if (len == 16 && arr[0] == 5 && arr[1] == 1 ) return "MASTERCARD";
if (len == 16 && arr[0] == 5 && arr[1] == 2 ) return "MASTERCARD";
if (len == 16 && arr[0] == 5 && arr[1] == 3 ) return "MASTERCARD";
if (len == 16 && arr[0] == 5 && arr[1] == 4 ) return "MASTERCARD";
if (len == 16 && arr[0] == 5 && arr[1] == 5 ) return "MASTERCARD";

if (len == 13 && arr[0] == 4) return "VISA";

return "INVALID";
}

现在你的调用代码只需要这样做:
printf("%s\n", card_leng_type2string(cardLength, numberArray) );

我实际上喜欢这种情况下的重复表达式——它们使一切更加清晰。起初,我误读了原始代码,认为需要像“347”这样的序列。 - Steve Summit
根据Wikipedia显示,VISA信用卡号码可能为13或16个字符。AMEX和Mastercard看起来没有问题。 - Luca Polito
@wildplasser 我也喜欢这种方法。至少在 C 语言中,这是使代码既易读又紧凑,而不需要长的if条件(也不需要为每个验证使用单独的函数)的唯一方法。虽然它仍然非常冗余,但这是 C 的一个缺陷,我想。P.S.: 关于数字,是的我知道,但我指出这一点是为了防止阅读答案的人复制错误的 VISA 验证。 - Luca Polito
应该返回 const char* - Lundin
2
将代码封装在一个函数中的建议几乎总是一个绝佳的建议。这不仅使调用代码更易读,而且一旦你拥有了一个封装好的函数,就可以很容易地为其编写单元测试,一旦你有了一个单元测试,你可以毫不顾虑地重新编写函数(也许以一种“更高效”但不太清晰的方式)。 - Steve Summit
显示剩余2条评论

3
你可以按以下方式将numberArray的前两个数字转换为一个新数字:
num = numberArray[0]*10 + numberArray[1]

然后将其用于条件语句中,以使它们更易于阅读

int num = numberArray[0]*10 + numberArray[1]

if ((cardLength == 15) && ((num == 37) || (num == 34)))
{
    printf("AMEX\n");
}
else if ((cardLength == 16) && ((num >= 51) && (num <= 55)))
{
    printf("MASTERCARD\n");
}
else if ((cardLength == 13) && ((num >= 40) && (num <= 49)))
{
    printf("VISA\n");
}
else
{
    printf("INVALID\n");
}
return 0;
}

好主意,尽管它会让读者感到困惑:为什么最后一个情况不是 if (cardLength == 13 && num == 4) - Steve Summit
1
此外,这个实现存在一些小错误:初始的 num 计算需要字符 → 数字转换;AMEX 子句不应该允许 35 和 36;Mastercard 子句不应该允许 56;VISA 子句需要检查 '4' 而不是 4,并且所有的 if 语句需要再加上一对括号。(我猜你在发布之前没有编译它。 :-)) - Steve Summit
@SteveSummit 你说的大多数都是对的。我纠正了你发现的语法错误(是的,我没有编译它; -)) - Vaggelis_Lazarakis
最后一个情况应该是 numberArray[0] == 4 而不是 num >= 40 - livemyaerodream
@hmhuang num 是一个双位数,因为它由 numberArray 的前两个元素组成。所以它的值必须在40到49之间。 - Vaggelis_Lazarakis

2
假设numberArray中的条目在0-9范围内,您可以使用strchr函数。如果给定字符串包含特定字符,则此函数返回非NULL值。
替换:
numberArray[1] == 4 || numberArray[1] == 7 || numberArray[1] == 9

使用

strchr("479", '0' + numberArray[1])

如果numberArray是一个字符数组,那么检查可以简化为strchr("479", numberArray[1])

-1
如果您想保持逻辑完整性,只是为了提高可读性而进行修改,可以尝试在全局添加预处理器指令。 这将替换程序中任何使用它的文本或内联函数。 例如:
#define AMEX_CONDITION (cardLength == 15) &&  (numberArray[0] == 3 && (numberArray[1] == 4 || numberArray[1] == 7))

并在您的if语句中使用它

if(AMEX_CONDITION){
    printf("AMEX");
}

4
这会降低可读性。我建议添加一些“static inline”函数。 - Basile Starynkevitch
4
自己发明一个秘密的宏语言是一个非常糟糕的主意,这比原帖中的情况更糟糕。 - Lundin
回复:关于宏的使用:根据我的经验,在软件工程(操作系统、实时系统和嵌入式系统)中,宏替换是常见且有效的。 - Martin Kuester
@MartinKuester 我几乎专门从事实时嵌入式系统的工作,根据我的经验,像这样的宏大多数情况下是在程序员对函数内联或现代编译器生成代码的方式毫不知情时使用的。或者当他们以某种其他方式感到困惑时,比如发明一些魔法宏语言来进行简单的GPIO位操作。 - Lundin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接