【问题标题】:Same code works on Linux but not on windows相同的代码适用于 Linux,但不适用于 Windows
【发布时间】:2022-10-01 07:31:35
【问题描述】:

这是 CS50x 的信用问题 我在 Windows 上编写了这段代码,但它在那里不起作用。在 Windows 上输入 15 位数的卡号后,它不接受该号码,并一次又一次地提示我。 但是,当我在 Linux 上的 VSCode 中的 CS50\'s cloudspace 上粘贴相同的代码时,代码在那里运行得非常好。 问题似乎出在 get_long 函数中,它不允许我在 Windows 上输入 15 位数的卡号。

#include <stdio.h>
#include \"cs50.h\"

int main()
{
   long number;
   
    number = get_long(\"Enter your card number: \");
   
   //Check length of number
   int i = 0;
   long length = number;
   while (length > 0 )
   {
    length = length / 10;
    i++;
   }

    if (i != 16 && i != 15 && i!= 13)
    {
        printf (\"INVALID\");
    }
    else
    {
        int sum1 = 0;
        int sum2 = 0;
        long x = number;
        int mod1 = 0;
        int mod2 = 0;
        int d1 = 0;
        int d2 = 0;
        int final_sum = 0;

        do
        {
            //Remove last digit and add to sum1
            mod1 = x % 10;
            x = x / 10;
            sum1 = sum1 + mod1;
            
            //Remove second last digit
            mod2 = x % 10;
            x = x / 10;

            //Multiply second last digit by two 
            mod2 = mod2 * 2;

            //Extract the digits
            d1 = mod2 % 10;
            d2 = mod2 / 10;

            //Add to sum2
            sum2 = sum2 + d1 + d2;

        } while (x > 0 );

        final_sum = sum1 + sum2;
        
        //Check Luhns Algorithm
        if (final_sum % 10 != 0)
        {
            printf(\"INVALID\\n\");
        }
        else
        {
            long y = number;
            int j = 0;
            do
            {
                y = y / 10;
                j++;

            } while (y > 100 );

            if ( y / 10 == 4)
            {
                printf (\"VISA\");
            }
            else if ((y / 10 == 5) && (0 < y % 10 && y % 10 < 6))
            {
                printf(\"MASTERCARD\");
            }
            else if ((y / 10 == 3) && (y % 10 ==4 || y % 10 == 7) )
            {
                printf(\"AMEX\");
            }
        }
    }

}
  • 由于您正在调用get_long_long,因此您还应该使用long long 数据类型,而不仅仅是long
  • 可能是因为long 只有 32 位。请更改曲目:使用字符串作为 \"number\"。它不是整数。没有人使用整数来存储卡、电话或房子的“号码”。无论如何,拥有数字字符串可以很容易地挑选出单个数字,你不觉得吗?
  • @AndrewHenle,对不起,我以为那是我写的。不是“也许”是 32 位,而是失败的原因。
  • @WeatherVane 我没有那样读。对我来说是漫长的一天。 :-/
  • @风向标没有人使用好吧,当然,除了大批 CS50 程序员...

标签: c cs50 long-integer


【解决方案1】:

您的代码有效,因为在您的 Linux 平台上,键入 long 恰好是 8 字节、64 位类型,可以轻松处理匹配甚至 15 位或 16 位信用卡号的整数。

您的代码在 Windows 上失败,因为在那里,类型 long 是 32 位类型,无法处理大于 2,147,483,647 或 4,294,967,295 的数字(取决于有符号或无符号)。

两个平台之间的这种差异不是错误:C 的shortintlong 类型的定义总是有些松散。 long 类型的要求实际上是它具有至少32 位,在两个平台上都可以。

你的作业说“最好使用 CS50 库中的get_long 来获取用户的输入”是相当不公平和误导的。对于此任务,这是一种不可移植的编程实践。

在可移植的 C 中,long long 类型保证至少有 64 位长,因此它可以在这里可靠地工作。不知道CS50的库有没有get_long_long函数。 (更新:根据下面的 cmets,确实如此。)

从长远来看,处理信用卡号码通常更容易,因为字符串,而不是整数。但是在 CS50 的第 1 周,学生们还没有学过弦乐。

【讨论】:

  • 显然 CS50 确实有 get_long_long 但该页面显示:此函数将被弃用,取而代之的是 get_long.
  • 我正要说“欺负!” (我一直在寻找来自Arsenic and Old Lace 的正确剪辑来配合它),但后来你更新了你对弃用的评论,现在我只能说,Sheesh。
  • @SteveSummit 欢迎来到 CS50。我想说的是,他们已经弃用了 Windows 用户从用户那里读取 64 位整数值的唯一方法...... :-/
【解决方案2】:

instructions for your task 声明如下:

但不要假设用户的输入适合int!最好使用 CS50 库中的get_long 来获取用户的输入。

在使用 Microsoft Windows platform 时,此建议具有误导性。

在 Microsoft Windows 上,数据类型long 的宽度仅为 32 位,而在大多数其他常见平台上,如 Linux 和 MacOS,它的宽度为 64 位。 ISO C standard 只要求long 的最小宽度为 32 位,因此所有提到的操作系统都符合这方面的标准。

一个 32 位的signed 整数能够表示最大为2,147,483,647 的数字,而一个64 位的signed 整数能够表示最大为9,223,372,036,854,775,807 的数字。因此,32 位整数数据类型不足以表示信用卡号;您需要 64 位整数数据类型。

long 相比,long long 数据类型保证在所有平台上至少为 64 位宽。

由于上述原因,如果您希望您的程序在 Microsoft Windows 上运行,则必须使用 long long 数据类型来表示信用卡号,而不是 long。您还必须使用函数get_long_long 而不是get_long

【讨论】:

  • 这是源代码,对于任何如此倾向的人:github.com/cs50/libcs50/blob/main/src/cs50.c
  • 请参阅我链接的来源。它有一个get_long_long 函数。
  • @RobertHarvey 感谢您提供该链接。快速浏览一下,看起来他们确实在假设一个具有 64 位长的平台——get_intget_long 都包含该假设的各个方面。
【解决方案3】:

cmets 中关于 32 位与 64 位的讨论应该对您具有教育意义,我希望您可以将这些信息集成到您的程序中。

赞美你的布局和逻辑初学者代码。非常清晰且易于阅读和遵循(包括适当的 cmets。)坚持下去,您将成为一名优秀的程序员!

我已经修改了你的代码(没有明显改变它的任何逻辑)以建议如何稍微改进它。以下内容供您参考。这是您的代码仅稍作修改。是否要将这些“更改”中的任何一个应用于您的代码,由您自己决定。

#include <stdio.h>
#include "cs50.h"

int main()
{
    long number = get_long("Enter a card number: ");
    long x = number; // will reload and reuse x several times
    int i = 0; // handy to have around

    // Check length of number
    while (x > 0 )
    {
        x = x / 10;
        i++;
    }

    if (i != 16 && i != 15 && i!= 13)
    {
        printf ("INVALID");
        return 1; // early termination saves one level of indentation
    }

    int sum1 = 0;
    int sum2 = 0;
    int mod1 = 0;
    int mod2 = 0;
    int d1 = 0;
    int d2 = 0;
    int final_sum = 0;

    x = number; // reload
    while ( x > 0 )
    {
        //Remove last digit and add to sum1
        mod1 = x % 10;
        x = x / 10;
        sum1 = sum1 + mod1;

        //Remove second last digit
        mod2 = x % 10;
        x = x / 10;

        //Multiply second last digit by two
        mod2 = mod2 * 2;

        //Extract the digits
        d1 = mod2 % 10;
        d2 = mod2 / 10;

        //Add to sum2
        sum2 = sum2 + d1 + d2;
    }

    final_sum = sum1 + sum2;

    //Check Luhns Algorithm
    if (final_sum % 10 != 0)
    {
        printf("INVALID\n");
        return 1;  // early termination
    }

    x = number; // reload
    while ( x > 99 ) // NB! subtle change!!
    {
        x = x / 10; // shrink until 10 <= x <= 99
    }

    if ( 40 <= x && x <= 49 ) // check this
    {
        printf ("VISA");
    }
    else if ( 50 <= x && x < 56 ) // check this
    {
        printf("MASTERCARD");
    }
    else if ( x == 34 || x == 37 ) // check this
    {
        printf("AMEX");
    }
    else
    {
        printf("INVALID\n");
        return 1; // early termination
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 2022-11-21
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多