当前位置:  开发笔记 > 编程语言 > 正文

在C/C#/ C++中进行向后循环的最佳方法是什么?

如何解决《在C/C#/C++中进行向后循环的最佳方法是什么?》经验,为你挑选了6个好方法。

我需要向后移动一个数组,所以我有这样的代码:

for (int i = myArray.Length - 1; i >= 0; i--)
{
    // Do something
    myArray[i] = 42;
}

有没有更好的方法呢?

更新:我希望C#可能有一些内置机制,如:

foreachbackwards (int i in myArray)
{
    // so easy
}

更新2:有更好的方法.符文获奖:

for (int i = myArray.Length; i-- > 0; )
{    
    //do something
}
//or
for (int i = myArray.Length; i --> 0; )
{
    // do something
}

在常规C中看起来更好(感谢Twotymz):

for (int i = lengthOfArray; i--; )
{    
    //do something
}

小智.. 134

虽然可以肯定有点模糊,但我会说这样做的印刷最令人愉悦的方式是

for (int i = myArray.Length; i --> 0; )
{
    //do something
}

当我第一次阅读你的答案时,看起来它甚至都不会编译,所以我认为你是一个疯狂的人.但这正是我所寻找的:一种更好的方式来编写一个向后循环. (29认同)

这太模糊和混淆了.我永远不会在生产代码中写这样的东西...... (24认同)

我发现它"印刷上令人困惑".对我来说," - "看起来不正确,除非它与它影响的变量相邻. (14认同)

啊[转到运营商( - >)](http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator?lq=1)就可以了! (9认同)

我想我 - > 0; 是故意的.这就是他所说的"印刷上令人愉悦"的意思 (3认同)

这很可爱,但可爱≠很好的风格.任何减慢阅读速度的东西都是个坏主意.而且,它的输入不仅仅是`for(int i = myArray.Length; i - ;){...}`. (3认同)


Johannes Sch.. 115

在C++中,您基本上可以选择迭代使用迭代器或索引.根据您是否具有普通数组或a std::vector,您使用不同的技术.

使用std :: vector

使用迭代器

C++允许您使用 std::reverse_iterator:

for(std::vector::reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
    /* std::cout << *it; ... */
}

使用指数

通过返回的无符号整型std::vector::size不是永远std::size_t.它可以更大或更小.这对于循环工作至关重要.

for(std::vector::size_type i = someVector.size() - 1; 
    i != (std::vector::size_type) -1; i--) {
    /* std::cout << someVector[i]; ... */
}

它起作用,因为无符号整数类型值是通过模数来计算它们的位数.因此,如果你正在设置-N,你最终会(2 ^ BIT_SIZE) -N

使用数组

使用迭代器

我们正在使用std::reverse_iterator迭代.

for(std::reverse_iterator it(a + sizeof a / sizeof *a), itb(a); 
    it != itb; 
    ++it) {
    /* std::cout << *it; .... */
}

使用指数

我们可以安全地使用std::size_t这里,而不是上面,因为sizeof总是std::size_t按定义返回.

for(std::size_t i = (sizeof a / sizeof *a) - 1; i != (std::size_t) -1; i--) {
   /* std::cout << a[i]; ... */
}

避免使用sizeof应用于指针的陷阱

实际上上面确定阵列大小的方法很糟糕.如果a实际上是一个指针而不是一个数组(这经常发生,并且初学者会混淆它),它将无声地失败.更好的方法是使用以下命令,如果给出指针,它将在编译时失败:

template char (& array_size(T(&)[N]) )[N];

它的工作原理是首先获取传递的数组的大小,然后声明返回对相同大小的char类型数组的引用.char被定义为具有sizeof:1.因此返回的数组将具有sizeof:N*1,这是我们正在寻找的,仅具有编译时评估和零运行时开销.

而不是做

(sizeof a / sizeof *a)

更改您的代码,以便它现在可以

(sizeof array_size(a))

是的,这是它的意图:) new int [7]返回一个指针.所以sizeof(new int [7])不返回7*sizeof(int),但会返回sizeof(int*).array_size导致该情况的编译错误,而不是静默工作. (2认同)


Jay Bazuzi.. 53

在C#中,使用Visual Studio 2005或更高版本,键入"forr"并单击[TAB] [TAB].这将扩展到一个for向后循环通过集合的循环.

这很容易出错(至少对我来说),我认为把这个片段放在一个好主意.

也就是说,我喜欢Array.Reverse()/ Enumerable.Reverse()然后更好地迭代前进 - 他们更清楚地说明意图.



1> 小智..:

虽然可以肯定有点模糊,但我会说这样做的印刷最令人愉悦的方式是

for (int i = myArray.Length; i --> 0; )
{
    //do something
}


当我第一次阅读你的答案时,看起来它甚至都不会编译,所以我认为你是一个疯狂的人.但这正是我所寻找的:一种更好的方式来编写一个向后循环.
这太模糊和混淆了.我永远不会在生产代码中写这样的东西......
我发现它"印刷上令人困惑".对我来说," - "看起来不正确,除非它与它影响的变量相邻.
啊[转到运营商( - >)](http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator?lq=1)就可以了!
我想我 - > 0; 是故意的.这就是他所说的"印刷上令人愉悦"的意思
这很可爱,但可爱≠很好的风格.任何减慢阅读速度的东西都是个坏主意.而且,它的输入不仅仅是`for(int i = myArray.Length; i - ;){...}`.

2> Johannes Sch..:

在C++中,您基本上可以选择迭代使用迭代器或索引.根据您是否具有普通数组或a std::vector,您使用不同的技术.

使用std :: vector

使用迭代器

C++允许您使用 std::reverse_iterator:

for(std::vector::reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
    /* std::cout << *it; ... */
}

使用指数

通过返回的无符号整型std::vector::size不是永远std::size_t.它可以更大或更小.这对于循环工作至关重要.

for(std::vector::size_type i = someVector.size() - 1; 
    i != (std::vector::size_type) -1; i--) {
    /* std::cout << someVector[i]; ... */
}

它起作用,因为无符号整数类型值是通过模数来计算它们的位数.因此,如果你正在设置-N,你最终会(2 ^ BIT_SIZE) -N

使用数组

使用迭代器

我们正在使用std::reverse_iterator迭代.

for(std::reverse_iterator it(a + sizeof a / sizeof *a), itb(a); 
    it != itb; 
    ++it) {
    /* std::cout << *it; .... */
}

使用指数

我们可以安全地使用std::size_t这里,而不是上面,因为sizeof总是std::size_t按定义返回.

for(std::size_t i = (sizeof a / sizeof *a) - 1; i != (std::size_t) -1; i--) {
   /* std::cout << a[i]; ... */
}

避免使用sizeof应用于指针的陷阱

实际上上面确定阵列大小的方法很糟糕.如果a实际上是一个指针而不是一个数组(这经常发生,并且初学者会混淆它),它将无声地失败.更好的方法是使用以下命令,如果给出指针,它将在编译时失败:

template char (& array_size(T(&)[N]) )[N];

它的工作原理是首先获取传递的数组的大小,然后声明返回对相同大小的char类型数组的引用.char被定义为具有sizeof:1.因此返回的数组将具有sizeof:N*1,这是我们正在寻找的,仅具有编译时评估和零运行时开销.

而不是做

(sizeof a / sizeof *a)

更改您的代码,以便它现在可以

(sizeof array_size(a))


是的,这是它的意图:) new int [7]返回一个指针.所以sizeof(new int [7])不返回7*sizeof(int),但会返回sizeof(int*).array_size导致该情况的编译错误,而不是静默工作.

3> Jay Bazuzi..:

在C#中,使用Visual Studio 2005或更高版本,键入"forr"并单击[TAB] [TAB].这将扩展到一个for向后循环通过集合的循环.

这很容易出错(至少对我来说),我认为把这个片段放在一个好主意.

也就是说,我喜欢Array.Reverse()/ Enumerable.Reverse()然后更好地迭代前进 - 他们更清楚地说明意图.


这给我带来了很多痛苦.谢谢.

4> Jack Griffin..:

总是喜欢清晰的代码来反对' 印刷上令人愉悦 '的代码.因此,我会一直使用:

for (int i = myArray.Length - 1; i >= 0; i--)  
{  
    // Do something ...  
}    

您可以将其视为向后循环的标准方法.
只是我的两分钱......



5> Keltex..:

C#中使用Linq:

foreach(var item in myArray.Reverse())
{
    // do something
}



6> Adam Rosenfi..:

对于任何长度为有符号整数类型的数组来说,这绝对是最好的方法.对于长度为无符号整数类型的数组(例如,std::vector在C++中),则需要稍微修改结束条件:

for(size_t i = myArray.size() - 1; i != (size_t)-1; i--)
    // blah

如果你刚才说i >= 0,对于无符号整数,这总是正确的,所以循环将是一个无限循环.

推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有