【问题标题】:How do i fix the infinite loop that this code gets itself into?如何修复此代码进入的无限循环?
【发布时间】:2019-06-16 21:29:21
【问题描述】:

使用方法制作一个允许您选择不同搜索/排序方法的程序。对于冒泡排序,当我尝试在代码底部输出数组时,它会打印“System.Int32[]”。此外,代码实际上永远不会结束,它只是打印出'System.Int32[]'和'End of pass _'。我如何阻止这种情况发生? 谢谢

我尝试将 {0} 换成实际的变量名,并在 for 循环中更改 'b

        int pass_count = 0;
        bool sorted = false;
        int[] changing_array = new int[5];
        int[] final_array = new int[5];
        int[] starting_array = new int[5];
        for (int a = 0; a < 5; a++)
        {
            Console.WriteLine("Input number {0}", (a + 1));
            changing_array[a] = Convert.ToInt32(Console.ReadLine());
        }
        Array.Copy(changing_array, final_array, 5);
        Array.Copy(changing_array, starting_array, 5);
        Array.Sort(final_array);



        while (sorted == false)
        {
            for (int b = 0; b < 4; b++)
            {
                int c = b++;
                int temp;
                if (changing_array[b] > changing_array[c])
                {
                    temp = changing_array[b];
                    changing_array[b] = changing_array[c];
                    changing_array[c] = temp;
                }
                else
                {
                    continue;
                }
            }
            pass_count++;
            if (changing_array == final_array)
            {
                Console.WriteLine("It took {0} passes to sort \n{1} \ninto \n{2} ",pass_count,starting_array,final_array);
                sorted = true;
            }
            else
            {
                Console.WriteLine("End of pass {0}. \n{1} \nis now \n{2} ",pass_count,starting_array,changing_array);
            }
        }

假设最后的数字是“65,34,23,87,30”,我希望它打印“它需要 {0} 次通过排序 \n'65,34,23,87,30' \ ninto \n'23,30,34,65,87'",但它只打印 'System.Int32[]' 和 'End of pass _'。

【问题讨论】:

  • 如果数组“相等”,则比较方式存在问题。数组是基于引用的,因此只有两个引用指针都指向同一个数组时它们才相等。查看stackoverflow.com/questions/3232744/… 以了解如何检查 2 个数组的值是否相同。所以简而言之,`if (changeing_array == final_array) 将始终评估为 false,因为它不检查值是否相同,但它会检查它们是否是同一个数组对象。因此 sorted 永远不会是真的并且循环是无限的

标签: c# arrays sorting bubble-sort


【解决方案1】:

您的代码中有几个问题。

在你正在做的for循环中:

int c = b++;

但是,这不会达到您的预期。它首先将b 的值分配给c,然后将b 加一。这意味着这会增加for-loop 变量,并且您实际上是在跳过迭代,此外cb 的值现在已经“交换”了。

相反,您需要这样做:

int c = b+1;

这会将c 分配为比b 大一并且保持b 不变。

最后你是在比较两个数组实例:

if (changing_array == final_array)

这行不通。数组是 C# 中的引用类型,这只是检查两个变量是否指向内存中的同一位置(它们没有)。相反,您可能想要SequenceEqual

if (changing_array.SequenceEqual(final_array))

此方法将两个数组中的项目一一进行比较,并且仅当两者具有相同的内容时才返回 true。

在这些更改之后,while 循环结束。

对于输出,您不能将数组直接传递给Console.WriteLine。该方法只能处理简单的数据类型,不知道如何输出数组,所以它只是写出类型名称。相反,您应该将数组转换为整数。最简单的解决方案是string.Join 方法:

string.Join(",",starting_array)

这将创建一个字符串,其中包含用逗号分隔的数组项。

这些更改后您的代码的完整版本:

int pass_count = 0;
bool sorted = false;
int[] changing_array = new int[5];
int[] final_array = new int[5];
int[] starting_array = new int[5];
for (int a = 0; a < 5; a++)
{
    Console.WriteLine("Input number {0}", (a + 1));
    changing_array[a] = Convert.ToInt32(Console.ReadLine());
}
Array.Copy(changing_array, final_array, 5);
Array.Copy(changing_array, starting_array, 5);
Array.Sort(final_array);

while (!sorted)
{
    for (int b = 0; b < 4; b++)
    {
        int c = b+1;
        int temp;
        if (changing_array[b] > changing_array[c])
        {
            temp = changing_array[b];
            changing_array[b] = changing_array[c];
            changing_array[c] = temp;
        }
        else
        {
            continue;
        }
    }
    pass_count++;
    if (changing_array.SequenceEqual(final_array))
    {
        Console.WriteLine("It took {0} passes to sort \n{1} \ninto \n{2} ", pass_count, string.Join(",",starting_array), string.Join(",", final_array));
        sorted = true;
    }
    else
    {
        Console.WriteLine("End of pass {0}. \n{1} \nis now \n{2} ", pass_count, string.Join(",", starting_array), string.Join(",", final_array));
    }
}

另外请注意,我使用了!solved 而不是solved == false。两者是等价的,但第一个版本更常用,更简洁。

【讨论】:

  • 太棒了,谢谢。我已经进行了更改,程序现在可以运行了。
  • 很高兴它有帮助。下次请尝试将变量名称写得更清楚(abc 描述性不太强)。还要尽量避免像 4 这样的“魔术常量” - 并改用changing_array.Length - 1。这样以后数组长度的变化就不会给你带来麻烦了。
【解决方案2】:

使用string.Join 方法:

string.Join(",", yourArray)

...而不是尝试输出数组对象本身。

【讨论】:

    【解决方案3】:

    您进入无限循环的原因是因为您的应用程序中的控制权将转移到 if within sorted == false 循环的 else 部分;在这个 else 部分中 sorted 仍然是 false ,所以循环继续。

    因此,您必须在循环的 else 部分中 break 退出循环,如下所示,通过使用如下代码所示的 break 语句来防止无限循环。此外,您可以设置 sorted = true; 而不是使用 break 语句,这也将防止无限循环。

    if (changing_array == final_array)
    {
        Console.WriteLine("It took {0} passes to sort \n{1} \ninto \n{2} ", pass_count, starting_array, final_array);
        sorted = true;
    }
    else
    {
        Console.WriteLine("End of pass {0}. \n{1} \nis now \n{2} ", pass_count, starting_array, changing_array);
        break;//this is what will prevent infinite loop
    }
    

    【讨论】:

      【解决方案4】:

      浏览您的代码并添加一些 cmets 可能是最简单的:

          int pass_count = 0;
          bool sorted = false;
          int[] changing_array = new int[5];
          int[] final_array = new int[5];
          int[] starting_array = new int[5];
          for (int a = 0; a < 5; a++)
          {
              Console.WriteLine("Input number {0}", (a + 1));
              changing_array[a] = Convert.ToInt32(Console.ReadLine());
          }
          Array.Copy(changing_array, final_array, 5);
          Array.Copy(changing_array, starting_array, 5);
          Array.Sort(final_array);
      
      
      
          while (sorted == false)
          {
              //you should consider having a bool here to track whether a change was made to the array
              //if the for loop runs without making a change, the array is sorted
              for (int b = 0; b < 4; b++) //don't use 4, use changing_array.Length - 1
              {
                  int c = b++; //i'd avoid this, because it's potentially confusing as to what b and c values are after it runs. remove use of C and just use b+1 instead
                  int temp; //move this into the if, it doesn't need to be out here
                  if (changing_array[b] > changing_array[c])
                  {
                      temp = changing_array[b];
                      changing_array[b] = changing_array[c];
                      changing_array[c] = temp;
                      //you made a change, so set your changeMade bool to true here
                  }
                  else //this else is totally redundant - the only thing it instructs is to continue looping, which will happen anyway
                  {
                      continue;
                  }
              }
              //test your changeMade Boolean here - if it is false, then set sorted = true
              pass_count++;
      
              //this isn't how you compare if all the elements of array 1 are in the same order as array 2
              //this is how you compare whether two array variables refer to the same object in memory
              //they don't, so this is always false
              if (changing_array == final_array)
              {
                  //this prints Int32[] because when you pass an object into something that
                  //needs a string, the runtime calls ToString() on it to make it into a string
                  //ToString() isn't anything special for an array, it doesn't print the elements
                  //so the default object.ToString() is used, which just prints the type of the object
                  //one way to turn an array into a string representation is to say
                  //string.Join(",", starting_array)
                  //The join method will visit each element, adding them to a comma separated string
                  Console.WriteLine("It took {0} passes to sort \n{1} \ninto \n{2} ",pass_count,starting_array,final_array);
                  sorted = true;
              }
              else //the reason your loop runs forever is because this else always runs, and sorted is never made true
              {
                  Console.WriteLine("End of pass {0}. \n{1} \nis now \n{2} ",pass_count,starting_array,changing_array);
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-30
        • 2014-05-14
        • 1970-01-01
        • 1970-01-01
        • 2017-03-09
        • 2012-04-19
        • 1970-01-01
        相关资源
        最近更新 更多