嵌套很多while循环有问题吗?

时间:2012-04-25 22:47:13

标签: c while-loop nested-loops

我正在做一些功课,想知道是否存在太多嵌套while循环的东西。嵌套几个while循环有缺点吗?如果是这样,我将如何重构下面的代码片段?

下面是一次读取一行文件的代码,解析由某些定义的分隔符分隔的字段,并在打印到控制台之前删除前导空格。

// Read the file one line at a time
while (fgets(lineStr, MAXLINELENGTH, fp) != NULL)
{
    charPtr = strtok(lineStr, DELIMITERS);

    // Loop until line is parsed
    while (charPtr != NULL)
    {
        // Skip past leading whitespace
        while (isspace(*charPtr))
            charPtr++;

        puts(charPtr);
        charPtr = strtok(NULL, DELIMITERS);
    }
}

3 个答案:

答案 0 :(得分:7)

这确实是一个相当主观的话题。在我看来,三个嵌套的while循环没有任何根本性的错误,但是你达到了可接受的极限。如果您要添加一个或两个更多级别的嵌套,那么在我看来,您将跨越合理的边界,期望读者理解。人脑在任何一个时间点都只能处理如此复杂的事情。

有些人认为,与我的观点相反,函数中嵌套的级别不应超过一级,并且函数不应包含超过10行代码。反驳的论点是,这样的政策可能导致更加分散,不相交的代码。我的经验法则是,如果你不能为一大块代码想出一个好的函数名,那么也许那段代码实际上不是单独作为一个函数。

看看你可以打破这个功能的方法,有几个明显的选择。

  1. 将最外面的while的主体提取到一个单独的函数中。提取的函数将处理单行。这很容易命名和清楚阅读。
  2. 提取跳过空格的while循环到一个单独的函数中。这也很容易命名,并使您的代码更容易阅读。您将删除空白注释,因为提取的函数的名称将使其不必要。这可能值得做。
  3. 如果你应用了这些想法,那么你的代码可能看起来像这样:

    char* skipWhitespace(char* str)
    {
        while (isspace(*str))
            str++;
        return str;
    }
    
    void parseLine(char *lineStr)
    {
        charPtr = strtok(lineStr, DELIMITERS);
        while (charPtr != NULL)
        {
            charPtr = skipWhitespace(charPtr);
            puts(charPtr);
            charPtr = strtok(NULL, DELIMITERS);
        }
    }
    ......
    while (fgets(lineStr, MAXLINELENGTH, fp) != NULL)
        parseLine(lineStr);
    

    请注意,提取的方法的重构和命名使得注释有点多余,我删除了它们。另一个好的经验法则是,如果你需要过多地评论代码,那么它可能还没有得到很好的考虑。

    最终,确实没有严格的规则,而且归结为判断和个人偏好。在我看来,问题中的代码非常清晰易读,但在我看来,重构版本更加清晰。

    免责声明:我对代码的正确性或其他方面不做任何评论。我只是忽略了那个方面。

答案 1 :(得分:3)

唯一真正的缺点是可读性,对此没有任何硬性和快速的规则......虽然超过3个巢穴通常会刺激你正在使用的任何其他人。正如另一张海报所说,有时通过将循环移动到另一个功能来打破巢更好,但是你在这里拥有的东西对我来说是完全可读的 - 那是唯一真正的衡量指标;纯主观意见:))

答案 2 :(得分:0)

如前所述,这是相对主观的。但是,嵌套循环的方式会对代码产生直接的性能影响。考虑缓存感知编程。也就是说,您希望以这样的方式排列代码,即处理器可以在需要之前将下一个数据块预取(即预测)到高速缓冲存储器中。这将允许更多的缓存命中和更快的内存访问时间。

请注意,这对您的示例并不是特别重要,但是,如果要进行大量内存访问,则可能会显着提高或降低性能。如果您在行主体架构上以列方式遍历多维数组,则可能会出现许多缓存未命中(请注意,就实时而言,缓存未命中成本非常高。)

所以嵌套循环不一定是坏的,但它肯定会对性能产生明显的影响,特别是在一些任意数量的 n 循环之后。