C:嵌套循环和数组的奇数行为

C:嵌套循环和数组的奇数行为,c,arrays,loops,C,Arrays,Loops,我有一个int数组,该数组以代码中其他地方创建的“\0”结尾。我知道它是空终止的,因为我已经测试过了 例如,在本例中,数组是[7,8,9,11,12',\0'] 当我将其输入到我的函数时: int edgesInCluster(Graph *g, int *nodes) { int count = 0; int i = 0; int j = 0; while(nodes[i] != '\0') { while(nodes[j] != '\0') {

我有一个int数组,该数组以代码中其他地方创建的“\0”结尾。我知道它是空终止的,因为我已经测试过了

例如,在本例中,数组是[7,8,9,11,12',\0']

当我将其输入到我的函数时:

int edgesInCluster(Graph *g, int *nodes) {
    int count = 0;
    int i = 0;
    int j = 0;
    while(nodes[i] != '\0') {
        while(nodes[j] != '\0') {
            if(i<j) {
                printf("%i %i\n", nodes[i], nodes[j]);
                count += isNeighbour(g, nodes[i], nodes[j]);
            }
            j++;
        }
        i++;
    }
    return count;
}
应在何时输出:

7 7
7 8
7 9
7 11
7 12
7 8
7 9
7 11
7 12
8 9
8 11
8 12
9 11
9 12
11 12
这意味着出于某种原因,“i”没有递增(但我们可以看到它是递增的)或者节点[0]='\0',我们知道这不是真的,因为带有“j”的循环工作正常

你知道怎么回事吗


另外,当我将whiles更改为for循环时,它可以工作,但前提是我知道“节点”的长度。

在内部循环之后,您不必重置
j

但为什么要编写如此冗长的代码呢?试试这个:

size_t count = 0;

for (size_t i = 0; nodes[i]; ++i)
{
  for (size_t j = i + 1;  nodes[j]; ++j)
  {
    printf("%i %i\n", nodes[i], nodes[j]);
    count += isNeighbour(g, nodes[i], nodes[j]);
  }
}

return count;
(如果您想要严格的ANSI C89,当然必须将
i
j
的声明从循环中拉出。)


还要注意,
'\0'
是值为0的
字符,因此您也可以更准确地说,
0
。而不是
if(x!=0)
你可以说
if(x)
,这就是我在for循环中所做的。

你没有在
j
循环的开始处重置
j
的值。这样,在第一个循环之后,
节点[j]
对于所有后续循环都是
'\0'
,立即中止
j
循环。

啊,我真傻!我写得很详细,直到我知道所有的工作,然后我可以减少它,如果必要的话。值得一提的是,我编译成c99,带有-Wall和-pedantic,而且我没有收到任何警告——似乎比不那么冗长更重要。谢谢你的帮助。@Griffin:但你的冗长实际上掩盖了逻辑。for循环非常适合表示范围循环的语义,因此通过“手动执行”,您所做的只是混淆自己。。。还要注意的是,我的循环从正确的值开始,而不必每次都进行
if(i
检查,因此效率更高。注意要点,谢谢。出于兴趣,为什么要使用size\u t而不是int?@Griffin:数组索引和计数的自然数据类型是
size\u t
。它是
sizeof
运算符的返回类型,通常将def'd键入
unsigned int
。因为您的值是无符号整数,所以最好使用最合适的数据类型。@Kerrek SB(很抱歉,没有意识到这是一种礼节)。注意到未签名的ints,再次感谢。干杯,Kerrek SB刚刚把你推到了岗位上!是啊,反正他的建议更好。