在c中调用索引0时,long long数组不返回预期值

时间:2017-04-19 20:56:24

标签: c arrays

为什么printf("the value of str is \"%llu\"\n", str[0]);不返回数组str中第一个数字的值?

当我尝试其他索引值(1,2,3)时,会返回预期值吗?

提供任何帮助。刚开始学习c。

#include <stdio.h>


int main()
{
    // a will hold the number
    unsigned long long int a=548763,i=0;
    // str will hold the result which is the array
    unsigned long long int str[20]= {};
    // first we need to see the length of the number a
    unsigned long long int b=a;
    while(b>=10)
    {
        b=b/10;
        i++;
    }
    // the length of the number a will be stored in variable i 
    // the while loop below will store the digit from the end of str to the 
    // the beginning 
    while(i>0)
    {
        str[i]=a%10;
        a=a/10;
        i--;
    }
    // only for test 
    printf("the value of str is \"%llu\"\n", str[0]); //[0]

    return 0;
}

3 个答案:

答案 0 :(得分:3)

你忘了处理最后(最不重要)的数字:

while(i>0)
{
    str[i]=a%10;
    a=a/10;
    i--;
}

str[i] = a;  // <---- last digit (here i == 0 and a < 10)

答案 1 :(得分:3)

while(i>0)
{
    str[i]=a%10;
    a=a/10;
    i--;
}

此循环不会一直计数到0,它会倒计时到1.如果i从不为0,则永远不会设置str[i]

我怀疑发生了什么是你写的while(i>=0)并且编译器告诉你,因为i因为无符号而永远不会是负面的,因此无法工作。这就是发生在我身上的事。奇怪的是迭代器是无符号的,可能是因为i实际上是数字的位数,但也没有真正的理由让它无符号。 i永远不会超过20,可能是short

最小的修复方法是将i存储为有符号整数并切换到while(i>=0)

我会更进一步并建议:

  • 存储num_digits
  • 中的位数
  • 使i只是迭代器以避免混淆。

i通常用作循环迭代器,将其用于其他任何事情或将其值保留在下一个循环中是一个坏习惯。如果你必须这样做,请将其命名为其他内容。

这也意味着在填充str的过程中会破坏位数,而无法打印所有str。因此,请将其单独存储在num_digits中,并根据需要将其复制到i

  • 使用for循环。

对于简单的迭代,for循环非常清楚它是如何初始化的,它是如何递增的,以及结束条件是什么。你的第一个循环不适合for循环,但你的第二个循环是。

  • 根据需要声明变量。

这可以避免遗忘类型,他们初始化的内容以及所有内容。它还可以更容易地看到应该拆分成函数的内容。

  • str更改为digits

它不是一个字符串。

  • digits的类型更改为short

digits是一个单独的数字数组,没有一个会大于9.为每个数字分配64位是过度的。

  • unsigned long long int可能会溢出str[20]

这是代码中的另一个实际错误。 unsigned long long int保证至少 64位,但可能更多。如果是,那将会溢出str,其固定为20.您必须基于malloc str num_digits的{​​{1}}内存,或使用{ {1}}从stdint.h显式获取无符号的64位整数。

全部放在一起......

uint64_t

我们正在使用#include <stdio.h> #include <stdint.h> #include <inttypes.h> int main() { // a will hold the number uint64_t a=548763; 而不是uint64_t malloc。 YMMV,只要str不能溢出。我选择了固定大小以避免引入内存分配,你可能还没有学到这一点。我保持不受约束,不必处理这个标志。

str

我把它留作// first we need to see the length of the number a int num_digits = 0; uint64_t b = a; while( b>=10 ) { b=b/10; num_digits++; } 循环,因为它不是一个简单的迭代器。根据需要声明变量(这将产生一个很好的小函数)。它将while中的位数存储为一个简单的整数。

num_digits

这已被重写为short digits[20]= {0}; for( int i = num_digits; i >= 0; i-- ) { digits[i]=a%10; a=a/10; } 循环,以明确这是一个简单的迭代器。 for已复制到num_digits,因此我们稍后可以使用i。它下降到0. num_digits现在是digits s的数组,1个字节的整数;它只需要存储0到9之间的数字列表。

请注意,short的初始化程序是非标准的。应该{}将所有元素初始化为0。

{0}

我们仍然需要for( int i = 0; i <= num_digits; i++ ) { printf("the value of str is \"%d\"\n", digits[i]); } 来回顾num_digits

这可能是一项练习。在生产代码中,您可以使用digits完成相同的操作。这也将处理负数,不需要无符号。

sprintf

请注意the types from stdint.h have their own printf format specifiersint64_t a=548763; char str[22] = {0}; // 1 extra for the possible sign, 1 for the null byte. sprintf(str, "%"PRId64, a); for( int i = 0; str[i] != '\0'; i++ ) { printf("the value of str is \"%c\"\n", str[i]); } 是64位数字的PRIntf格式。它是一个宏,必须在引号之外才能扩展为自己的字符串。它利用了相邻的C字符串在编译时自动连接。

PRId64

答案 2 :(得分:0)

这是我最终按预期工作的最终代码。 我从来没有写过零指数。

我将str[i]=a%10;更改为str[i-1]=a%10;

进行了一些其他的小改动,以使循环正常运行,因为它没有进行最后一次循环。谢谢大家的帮助。

#include <stdio.h>


int main()
{
    // a will hold the number
    unsigned long long int a=123456,i=0;
    // str will hold the result which is the array
    unsigned long long int str[20]= {0};
    // first we need to see the length of the number a
    long long int b=a;
    while(b>0)
    {
        b=b/10;
        i++;
    }
    // the length of the number a will be stored in variable i 
    // the while loop below will store the digit from the end of str to the 
    // the beginning 
    while(i>0)
    {
        str[i-1]=a%10;
        a=a/10;
        i--;
    }
    // only for test 
    printf("the value of str is \"%llu\"\n", str[1]); //[0]

    return 0;
}