C#中while循环中的两个语句

4
我正在编写一个程序,该程序从键盘接收输入并以以下螺旋方式打印正方形矩阵。
1 2 3 
8 9 4 
7 6 5 

我设法编写了这个程序,但遇到了一个奇怪的错误。在第26行它给了我一个数组越界异常。

while (matrix[row, col] == 0 && col < matrix.GetLength(0) )

然而,如果我在循环内切换两个语句的顺序,异常就会消失?这是否意味着while循环中两个语句的顺序很重要?如果是这样,为什么呢?难道不应该是当两个语句都为真时执行循环,只要其中一个为假,无论哪个,就停止执行吗?以下是我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SpiralMatrixN
{
    class Program
    {
        static void Main(string[] args)
        {
            //prompt the user to enter n
            Console.WriteLine("Enter the value of n");
            int n = int.Parse(Console.ReadLine());
            int[,] matrix = new int[n,n];
            Console.Clear();
            System.Console.SetWindowSize(100, 30);
            int value = 1;
            int col = 0;
            int row = 0;
            if (n>0 && n<21)
            {
                while(value <= n*n)
                {
                    while (matrix[row, col] == 0 && col < matrix.GetLength(0) )
                    {
                        matrix[row, col++] = value;
                        value++;
                    }
                    col--;
                    row++;
                    while (row < matrix.GetLength(1) && matrix[row, col] == 0)
                    {
                        matrix[row++, col] = value;
                        value++;
                    }

                    row--;
                    col--;
                    while (col >= 0 && matrix[row, col] == 0 )
                    {
                        matrix[row, col--] = value;
                        value++;
                    }
                    col++;
                    row--;
                    while (matrix[row, col] == 0 && row >= 0)
                    {
                        matrix[row--, col] = value;

                        value++;
                    }

                    col++;
                    row++;
                }

                for (int i = 0; i < matrix.GetLength(0); i++)
                {
                    for (int j = 0; j < matrix.GetLength(1); j++)
                    {
                        Console.SetCursorPosition(j * 5, i * 2);
                        Console.Write(matrix[i, j] + " ");
                    }
                    Console.WriteLine();
                }
            }
        }
    }
}

我会确保rowcol的值是你所期望的。在代码中设置断点,确保循环的行为符合你的预期。 - dub stylee
你应该在这里发布你的代码。 - demonplus
1
是的,因为短路。我相信有一个不错的副本在某个地方。 - harold
虽然与您的问题无关,但是您正在将“col”和“row”与错误的值进行比较。您应该使用col < matrix.GetLength(1)row < matrix.GetLength(0)。在您当前的代码中可以工作,因为两个维度都是“n”,但是如果您有一个不是正方形的矩阵,由于这个原因,您将会遇到问题。 - Erik
4个回答

14

是的,顺序很重要。在 && 子句中的条件会按照优先级顺序执行,如果其中一个失败,则不会执行另一个条件。目前你的代码因为 matrix[row, col] == 0 被首先执行,导致 col 越界。因此,你对于 col 的检查(顺便说一下,这个检查是绝对正确的)应该放在第一位:

while (col < matrix.GetLength(0) && matrix[row, col] == 0)
如果失败,第二个语句将不会被执行并且您将不会收到错误。这被称为“短路求值”。

5
是的,这被称为短路评估。由于您使用了"&&",第二个条件只有在第一个条件评估为true时才会被评估。

0

&&|| 运算符被称为“快捷短路运算符”;只有必要时才会评估第二个部分。这有两个好处:

  1. 在执行过程中更高效,因为运行的代码较少(通常不会比较多,但如果你正在进行IO或类似操作,情况可能会有所不同),以及
  2. 对于编程来说非常方便,因为你可以使用第一部分作为第二部分被评估的前提条件。例如,

    if (myObj != null && myObj.Name == "something")

    如果上面的两个部分都被评估了,那么当 myObj 为空时,就会从 myObj.Name 报错。

如果你确实需要无论如何都要评估表达式的两个部分,可以使用 &| 运算符。但我发现我很少这样做。

MSDN: && Operator (C# Reference)


0

&& 中的顺序很重要,它使用短路计算,而 & 则不是。在 && 表达式中,从左到右,如果一个条件为假,则不会评估其他条件。

条件逻辑运算符

&& 和 || 运算符被称为条件逻辑运算符,它们也被称为“短路”逻辑运算符。

条件与表达式:

包容或表达式   条件与表达式 && 包容或表达式

条件或表达式:

条件与表达式   条件或表达式 || 条件与表达式*

  • && 和 || 运算符是 & 和 | 运算符的条件版本:
  • x && y 的操作对应于 x & y 的操作,除非 x 为 true 才会评估 y。

x || y 的操作对应于 x | y 的操作,除非 x 为 false 才会评估 y。

形如 x && y 或 x || y 的操作通过按照重载解析(第7.2.4节)来处理,就好像操作是写成 x & y 或 x | y。然后,

  • 如果重载解析未能找到单个最佳运算符,或者如果重载解析选择预定义整数逻辑运算符之一,则会出现编译时错误。

  • 否则,如果所选的运算符是预定义布尔逻辑运算符之一(第7.10.2节),则按照第7.11.1节中描述的方式处理该操作。

  • 否则,所选的运算符是用户定义的运算符,并且按照第7.11.2节中描述的方式处理该操作。

无法直接重载条件逻辑运算符。但是,由于条件逻辑运算符是基于常规逻辑运算符进行评估的,因此常规逻辑运算符的重载,在某些限制条件下,也被认为是条件逻辑运算符的重载。这在第7.11.2节中进一步描述。

来自MSDN C# 条件运算符


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接