2013-04-27 90 views
-4

我的印象是,下面的代码会打印出“hello world”,但它根本不打印任何东西。为什么? 使用g ++ 4.2.1和cl ++ 3.2编译。向后迭代C++

void iterateBackwards(){ 
    std::string hiThere = "dlrow olleh"; 
    for (int i = hiThere.length(); i == 0; i--) { 
     std::cout << hiThere[i]; 
    } 
} 
+1

一个for循环在退出条件('i == 0')为假时立即退出。 – Mat 2013-04-27 18:37:10

+2

如果您想向后打印字符串,请使用:'std :: copy(hiThere.rbegin(),hiThere.rend(),std :: ostream_iterator (std :: cout,“”));' – 2013-04-27 18:38:10

回答

5

你的条件应该是i >= 0,不i == 0(一for循环的条件是false,这立即在你的榜样的情况下尽快退出)。因为下标运算符接受从零开始的索引,所以一旦你解决了这个问题,你也应该修改这个赋值为i。这意味着当您要访问字符串的终止符字符时,您可能对输出不感兴趣。

这应该更好地工作:

void iterateBackwards(){ 
    std::string hiThere = "dlrow olleh"; 
    for (int i = hiThere.length() - 1; i >= 0; i--) { 
     std::cout << hiThere[i]; 
    } 
} 

这里是一个live example

+0

程序没有未定义的行为。他根本不会访问任何元素,更不用说超出范围的元素。 – 2013-04-27 18:39:42

+0

@BenjaminLindley:对,我编辑了答案。谢谢 – 2013-04-27 18:41:34

+0

好的。但是,尽管行为可能不是OP后的行为,但在第一次修复之后不会出现未定义的行为。 'basic_string'对'operator []'有一个特殊的规定,以便与常见的c-string使用兼容。访问'hiThere [hiThere.size()]'是合法的,并且返回一个char值的引用,其值可以是字符串的末尾,也可以不是。见标准:'21.4.5/1&2'。如果您尝试修改该值,那是未定义的行为,但这不是在这里完成的。 – 2013-04-27 18:51:31

0

此外,您在for循环条件应该是

i >= 0 

,而不是

i == 0 

这是因为for循环会,只要是真正的迭代,这将是为FALSE你使用i == 0。

2
  1. 循环中的条件必须是i >= 0。否则,程序将永远不会进入循环体 - 只要i == 0为真,并且您将i设置为字符串的长度,它将循环。
  2. i应该用hiThere.length() - 1进行初始化。否则,你将会有未定义的行为 - C++中的字符串和数组是0索引的,即第一个索引是0,最后一个是size - 1(所以hiThere[hiThere.length() - 1]hiThere的最后一个元素)。
  3. 你应该看看C++迭代器:

    void iterateBackwards(){ 
        std::string hiThere = "dlrow olleh"; 
        for (auto it = hiThere.crbegin(); it != hiThere.crend() ; ++it) { 
         std::cout << *it; 
        } 
    } 
    
1

@AndyProwl已经给了,我会在这里复制与煤矿相比,更容易的解决方案:

std::string hiThere = "dlrow olleh"; 
for (int i = hiThere.length() - 1; i >= 0; i--) { 
    std::cout << hiThere[i]; 
} 

为求的完整性,你也可以这样写(这是值得知道的形式,因为你可能会遇到它 - 请注意,它是正好相当于安迪的溶胶ution):

std::string hiThere = "dlrow olleh"; 
for (size_t i = hiThere.length(); i--;) { 
    std::cout << hiThere[i]; 
} 

几点意见:

  • 现在我们可以用一个无符号(为size_t)指数,因为我们不需要负值了。这很有趣,因为如果你的字符串比INT_MAX更长,安迪的解决方案会发生什么? (这是不太可能发生的,我会授予你的,但仍然......)这种形式解决了这个小的(实际上是迂腐的)困境。
  • 终止条件和事后的想法合并在一起,所以事后留空。
  • 与我们习惯的大多数for循环不同,这里使用后递减运算符而非通常的预递减运算符非常重要,整个事情依赖它。

但老实说,我更喜欢@ woytaz的迭代器解决方案,只是因为它与STL的其余部分更加一致。