我正在阅读《 C#播放器指南》这本书,然后进入“尝试一下!”。关于数组的章节。
说明如下:
“创建3种方法:一种用于创建数组,一种用于反转数组,另一种用于在最后打印数组。您的main方法将如下所示:
static void Main(string[] args)
{
int[] numbers = GenerateNumbers();
Reverse(numbers);
PrintNumbers(numbers);
}
GenerateNumbers
方法应返回10个数字的数组。
PrintNumbers
方法应仅使用for或foreach循环一次向下遍历该数组,然后打印出其中的项目。
Reverse
方法将是最困难的。尝试一下,看看可以实现什么。如果您遇到困难,这里有一些提示:
提示1:要交换2个值,您需要将一个变量的值放在一个临时位置进行交换:
//Swapping a and b.
int a = 3;
int b = 5;
int temp = a;
int a = b;
int b = temp;
提示2:获取正确的索引进行交换可能是一个挑战。使用for循环,从0开始,一直到数组的长度/2。在for循环中使用的数字将是要交换的第一个数字的索引,而另一个将是数组的长度。减去索引减去1。这是为了说明数组基于0的事实。因此,基本上,您将用array [arrayLength-index-1]交换array [index]。“
话虽如此,到目前为止,这是我的代码:
static void Main(string[] args)
{
int[] numbers = GenerateNumbers();
Reverse(numbers);
PrintNumbers(numbers);
}
// Generates array of numbers and returns array
static int[] GenerateNumbers()
{
int[] numbers = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
return numbers;
}
// Reverses array to print backwards from 10 to 1
static void Reverse(int[] numbers)
{
for (int index = 0; index < numbers.Length; index++)
{
//swapping array indexes
int a = numbers[index];
int b = numbers.Length - index - 1;
//temp array temporarily holds value while swapping indexes
int temp = a;
a = b;
b = temp;
}
}
// Prints numbers in array after order has been reversed
static void PrintNumbers(int[] numbers)
{
for (int index = 0; index < numbers.Length; index++)
{
Console.WriteLine(numbers[index]);
}
Console.WriteLine();
}
再次,我的代码继续按数字顺序而不是反向打印数组。这是本书中反向方法的解决方案:
static void Reverse(int[] numbers)
{
// Initialize one index at the start of the array, and another
// at the end of the array. The index of the last item in the
// array is the length of the array - 1.
int firstIndex = 0;
int secondIndex = numbers.Length - 1;
while (firstIndex < secondIndex)
{
// To swap two numbers, we need to copy one value out
// to a safe place so that it doesn't get overwritten.
int temp = numbers[firstIndex];
numbers[firstIndex] = numbers[secondIndex];
numbers[secondIndex] = temp;
// Move on to the next pair.
firstIndex++;
secondIndex--;
}
}
奇怪的是,他们使用while循环而不是for循环作为指令状态。
有人可以帮助我了解我的代码出了什么问题和/或如何转换其while语句用作for循环?
答案 0 :(得分:4)
在您的代码中:
int a = numbers[index];
int b = numbers.Length - index - 1;
//temp array temporarily holds value while swapping indexes
int temp = a;
a = b;
b = temp;
您将数字本身放入a,同时将最后一个索引放入b(而不是最后一个索引的数字)。应该是这样的:
int tmp = numbers[index];
numbers[index] = numbers[numbers.Length - index - 1];
numbers[numbers.Length - index - 1] = tmp;
}
您的for循环还必须遍历数组的一半,然后再将它们交换到其原始位置:
for(int i=0;i<number.Length/2; i++)
{
int tmp = numbers[index];
numbers[index] = numbers[numbers.Length - index - 1];
numbers[numbers.Length - index - 1] = tmp;
}
如果将它们分配给a
和b
,则应像分配它们一样将它们放回(numbers[numbers.Length-index-1]=a; numbers[index]=b;
),将数组中的值复制到a
并b
,而不是引用(它们在内存中的地址)
答案 1 :(得分:1)
如果我要反转数组,我会这样做,因为我认为它更简单,更干净:
//new array to hold reverse
int[] rev = new int[fwd.Length];
//establish an indexer variable for fwd and reverse
//variable f starts at 0 and goes to length -1
//variable r goes the other way
for(int f = 0, r = rev.Length - 1; f < fwd.Length; f++, r--)
rev[r] = fwd[f];
return rev;
我感谢您的算法,将早期的条目与以后的条目交换,沿数组的一半返回,但是它的数学运算和变量赋值很繁重,似乎造成了混淆,例如“位置2处的数组值”和“计算位置2处的对应位置”
我个人认为,声明另一个相同大小的数组并将其复制到其中,并在向前读取源数组时向后工作是更简单的-这种方法在实现时可能更加无缺陷。
通常必须考虑代码的可读性,可理解性和可维护性以及其他因素。即使付出绝对的性能代价,也要始终努力编写简单且易于解释的代码。通过优化少量代码而获得的微秒数,很容易在几小时或几天内就迷失在脑海中,并说“为什么这个复杂的意大利面不起作用?”,或者更糟的是,对于其他人来说代码并说“这应该做什么,为什么不起作用?”
您还询问了它们的while循环如何转换为for循环。这是一个for循环:
for(setup; test; post-loop-actions)
在他们的代码中:
static void Reverse(int[] numbers)
{
// setup
int firstIndex = 0;
int secondIndex = numbers.Length - 1;
// test
while (firstIndex < secondIndex)
{
//post-loop-actions
firstIndex++;
secondIndex--;
}
}
启用其while循环,将其翻译为for循环:
static void Reverse(int[] numbers)
{
// setup
for(
int firstIndex = 0, secondIndex = numbers.Length - 1; //setup
firstIndex < secondIndex; //test
firstIndex++, secondIndex-- //post-loop-actions
)
{
...
}
}
我将for循环花括号部分分成3行;如果while循环示例中的变量名称较短,则可能更适合在线
您可以通过用逗号分隔语句来为循环设置/循环后操作执行多个分配。
这两种形式之间存在实际差异-在while循环形式中,变量是在循环结构外部声明的,并且在循环结束后仍可用于编码。