首页 > 解决方案 > 有没有办法让我的 do-while 条件在间隔之间起作用?

问题描述

我正在尝试使用 long 获得一个必须介于 13 到 16 之间的数字,然后我需要将 long 转换为字符串,用 strlen 测量它并验证它是否是 13 到 16 之间的数字。

我的问题是,无论我输入哪个数字,都无法满足 while 的条件

我试图改变 while 的条件,试图通过使用 for 循环将它除以 10 来测量 long 的长度......没有任何效果。

long card;
char str[17];
int len;

    do
        {
            card = get_long("Number: ");
            snprintf(str, 17, "%ld", card);
            len = strlen(str)-1;
        } 
        while (len >= 13 || len <=16);

标签: ccs50

解决方案


正如其他人指出的那样,along只能保证包含最多 32 位或 +/- 2,147,483,647。它可能更适合,但不能保证。要适合 10**17,您需要 64 位或long long. 或者,您可以使用固定宽度的整数类型,例如int64_t将映射到适当的整数类型。

您使用的方法有点折磨。get_long正在将输入读取为字符串,将其转换为 a long,然后将其转换回字符串以检查长度。

相反,读取该行、将其更改为一个数字sscanf并检查它是否在 1e13 和 1e17 之间更简单、更快捷。

更新@user3629249 在评论中指出我们必须考虑负数。为此,我们采用 的绝对值llabs

我没有CS50,也不是粉丝;我发现它的抽象对学习 C 是有害的。所以这里是传统的 C,这get_long_long基本上就是在做的事情。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define DIGITS13 10000000000000LL
#define DIGITS17 100000000000000000LL

long long card;
long long abs_card;
char line[1024];

do {
    printf("Number: ");
    if( !fgets(line, sizeof(line), stdin) ) {
        break;
    }
    if( sscanf(line, "%lld", &card) != 1 ) {
        printf("Not a number.\n");
        continue;
    }

    abs_card = llabs(card);
}
while( abs_card < DIGITS13 || DIGITS17 <= abs_card);

我添加了一些宏,以便更轻松地了解正在发生的事情。

在 CS50 中,它可能看起来像……

long long card;
long long abs_card;

#define DIGITS13 10000000000000LL
#define DIGITS17 100000000000000000LL

do {
    card = get_long_long("Number: ");
    abs_card = llabs(card);
} 
while(abs_card < DIGITS13 || DIGITS17 <= abs_card);

推荐阅读