C++ Printing a string in reverse using a for loop

2019-08-08 22:53发布

问题:

I have a program that prints out the characters of a string using a for-loop. It must also print the same characters in reverse, which is where I'm having problems. Can someone help me figure out why the second for-loop isn't executing?

int main()
{
    string myAnimal;

    cout << "Please enter the name of your favorite animal.\n";
    cin >> myAnimal;

    // This loop works fine
    int i;
    for(i = 0; i < myAnimal.length(); i++){
        cout << myAnimal.at(i) << endl;
    }

    // This one isn't executing
    for(i = myAnimal.length(); i > -1; i--){
        cout << myAnimal.at(i) << endl;
    }
    return 0;
}

回答1:

You need to assign i initially to the length minus one, or the last index value in the array.

for(i = myAnimal.length()-1; i >= 0; i--){
    cout << myAnimal.at(i) << endl;
}


回答2:

Because the character positions start at 0, the last character of myAnimal is at position (myAnimal.length()-1) not myAnimal.length() so you want to start the second loop there.



回答3:

@Lokno already provided you with the correct answer. However, let me nitpick your code a bit more to show you some other alternatives and to correct some minor mistakes.

First, you didn't actually post a compiling example, because you forgot to show the included headers <iostream> and <string> and also didn't show the using namespace std; that was implicit in your code.

Second, for the regular for loop, prefer to keep the loop variable inside the loop, unless you actually need to use it as a return value. Also prefer pre-increment ++i over post-increment i++. Furthermore, because you have made sure of the correct loop indices, there is no reason to use the bounds-checked element access at() over the unchecked [] version.

In C++11, you have the range-for loop which allows for even shorter and more fool-proof code, where I also used auto where you could have used char. Unfortunately, there is no reverse range-for loop. The correct index-based reverse for loop is probably easier to read if you use i >= 0 rather than i > -1.

Then there is an algorithm based loop using std::copy where you use the iterator interface of std::string (in particular the reverse iterators rbegin() and rend()) to copy each character through an ostream_iterator that is bound to standard output.

BTW, I used the separator "|" rather than the newline to see stuff more easier, adapt to your taste. In any case, using std::endl can have performance implications because it flushes the output buffer every time.

#include <algorithm>
#include <iterator>
#include <iostream> // you forgot this
#include <string>   // you forgot this

int main()
{
    using namespace std;    // you forgot this

    // let's pretend this is the string
    string myAnimal = "Please enter the name of your favorite animal.";

    // keep the loop variable local, prefer pre-increment
    for (int i = 0; i < myAnimal.length(); ++i)
        cout << myAnimal[i] << "|";    // prefer [] over at()
    std::cout << "\n";

    // C++11 range-for
    for (auto c : myAnimal)
        std::cout << c << "|";
    std::cout << "\n";

    // index-based reverse loop
    for (int i = myAnimal.length() - 1; i >= 0; --i)
        cout << myAnimal[i] << "|";
    std::cout << "\n";

    // algorithm-based reverse loop
    std::copy(myAnimal.rbegin(), myAnimal.rend(), ostream_iterator<char>(cout, "|"));
    std::cout << "\n";

    // main implicitly return 0
}

Live Example. PS: main() implicitly returns 0 upon success.



回答4:

You could use reverse iterators

#include <iostream>
#include <string>

int main() {
  std::string myAnimal;

  std::cout << "Please enter the name of your favorite animal.\n";
  std::cin >> myAnimal;

  // Iterate in reverse order
  for(auto c = myAnimal.rbegin(); c != myAnimal.rend(); ++c) {
    std::cout << *c << std::endl;
  }
}

Note that you have to increment the variable 'c' (and not decrement it) since this is a reverse iterator.



回答5:

for(myAnimal.length(); i > -1; i--){
    ^

this doesn't do anything. you fetch the value and then throw it away.

Did you mean i = myAnimal.length() - 1 ?



回答6:

Instead of

int i;
for(i = 0; i < myAnimal.length(); i++){
    cout << myAnimal.at(i) << endl;
}

// This one isn't executing
for(i = myAnimal.length(); i > -1; i--){
    cout << myAnimal.at(i) << endl;
}

write

for ( string::size_type i = 0; i < myAnimal.length(); i++ ){
    cout << myAnimal.at(i) << endl;
}

// This one isn't executing
for ( string::size_type i = myAnimal.length(); i != 0; ){
    cout << myAnimal.at( --i) << endl;
}

In your code you try to access an element of the string that is beyond the acceptable range that is equal to [0, length() - 1]

Also instead of type int it is better to use the type that std::string provides for the return type of member function length that is std::string::size_type.