'如果' C中的语句即使满足条件也不执行

时间:2015-06-26 00:02:06

标签: c

我是第一次尝试完成一个简单的命令行程序的程序员,作为first assignment的一部分用于我正在进行的在线课程,但我似乎遇到了一个障碍,我可以'找出GDB或我自己的研究。

经过几个小时的重写和几个小时的调试,我终于得到了下面的代码来编译。该程序应该将信用卡号作为输入,然后根据分配的规范检查它是否有效。我在这里使用了一个测试号码:PayPal Test Credit Cards

奇怪的是,当我输入AMEX卡号时,它正确地生成了文本" AMEX",但是当我尝试签证或万事达卡时,它会打印" INVALID&#34 ;。

在GDB中我破坏了验证功能,它似乎错误地跳过了这两个if / else if语句而没有进入Checksum函数,即使条件似乎已经满足。

if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.

...

else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.

...

正确执行的AMEX代码行是:

else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0)  // checks for a valid American Express.

所有三行的参数似乎格式完全相同。这就像我可以进入GDB那样。我先在GDB中打印totalDigits,firstDigit和secondDigit,然后单步执行上述两条非执行行,一切看起来都正确。所以我很难过,为什么AMEX系列会执行,而不是其他系列?

先谢谢大家。这是我试过写的hello.c之后的第一个程序,所以如果看起来我做了一些奇怪/错误的话,我绝对会接受任何批评或建议。

完整代码:

checker.c
#include <stdio.h>
#include <stdlib.h>



int MAX = 16;

int* DigitSort(unsigned long long x, int* array);
int Verify(int* array);


int main (void)
{

int* output = malloc (sizeof(int) * (MAX + 2)); // creates a blank array for the individual digits of the card number.
unsigned long long userInput = 0;

do
{
    printf("Please enter a credit card number:\n");
    scanf("%lld", &userInput);
}
while (userInput <= 0); // checks to make sure the user entered a number.


switch(Verify(DigitSort(userInput, output))) // sorts the user's input into individual digits and verifies the card type and validity.
{
       case 1 :
           printf("VISA\n");
           break;
       case 2 :
           printf("MASTERCARD\n");
           break;
       case 3 :
           printf("AMEX\n");
           break;
       case 0 :
           printf("INVALID\n");
           break;
       default :
           printf("INVALID\n");
}

free(output);
return 0;

}


int Verify(int* array) // verifies whether or not a card number is valid. Must pass the function a sorted array of individual digits.
{

int* cardNumber = array;
int firstDigit = cardNumber[0];
int secondDigit = cardNumber[1];
int totalDigits = 0;
int Checksum(int* cardNumber, int totalDigits);
int i = 0;

while (firstDigit >= 1 && cardNumber[i] >= 0) // this step counts the number of digits in the array.
{
    totalDigits = totalDigits + 1;
    i++;
}

if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
{
    return 1;
}

else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
{
    return 2;
}

else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0)  // checks for a valid American Express.
{
    return 3;
}
else // if the card number doesn't match any of the above conditions or fails the checksum, an 'I' for Invalid is returned.
{
    return 0;
}

}
int* DigitSort(unsigned long long x, int* array) // takes a long long as input and sorts it into individual digits
{
int* arrayReversed = malloc (sizeof(int) * (MAX + 2)); // creates a new array to hold the reversed order of digits.


int i = 0;
arrayReversed[0] = 0;

if (i < (MAX - 1) && x >= 10)
{
    do
    {
        arrayReversed[i] =  x % 10;
        x = x / 10;
        i++;
    }
    while (i < (MAX -1) && x >= 10);
}

if (i < MAX && x >= 1 && x <= 9)
{
    arrayReversed[i] = (int) x;
    x = (x - x);
}

if (x == 0)
{
    int j = 0;

    do
    {
        array[j] = arrayReversed[i]; // sorts the digits from the reversed array and places them into the sorted array.
        j++;
        i--;
    }
    while (j < MAX && i >= 0);

    array[j] = -1;

}

free(arrayReversed);
return array;
}

int Checksum(int* cardNumber, int totalDigits)
{
int sum1 = 0;
int sum2 = 0;
int i = (totalDigits - 2);
int j = (totalDigits - 1);

while (i >= 0)
{
    sum1 = ((cardNumber[i] * 2)%10) + ((cardNumber[i] * 2)/10) + sum1;
    i -= 2;
}

while (j >= 0)
{
    sum2 = (cardNumber[j] + sum2);
    j -= 2;
}

if (((sum1 + sum2) % 10) == 0)
{
    return 0;
}
else
{
    return 1;
}
}

1 个答案:

答案 0 :(得分:5)

你的第一个问题是:

if (firstDigit == 4 && totalDigits == (13 | 16) && ...

你需要写:

if (firstDigit == 4 && (totalDigits == 13 || totalDigits == 16) && ...

您的第一次检查是寻找0x1D == 29作为位数(因为paisanco指出comment|运算符是按位OR运算符) ,并且没有信用卡需要29位数(但不是很长一段时间)。请注意额外的括号,以便清晰和准确。不要乱搞去除它们 - 代码再次无法正常工作。一般情况下,如果您的条件同时包含&&||运算符并使用括号明确地对术语进行分组,请明确说明。

你在其他地方也有类似的问题。碰巧,(4 | 7)7的值相同,因此当第二个数字为7时(但不是4时),条件才有效。但它并不意味着你的意思。

计算机语言与人类语言的工作方式不同。习惯于更冗长地写出条件。其他一些语言为这些条件提供了缩写; C不是这样的语言。