1

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 should not use int to store the length of the string the length of the string may exceed the integer range. Commented Nov 9, 2017 at 15:24

6 Answers 6

6

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Addendum: this is what the runtime error message "terminate called after throwing an instance of 'std::out_of_range'", or similar, that you should have gotten, was trying to tell you.
1

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.

Comments

1

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.

Comments

0

@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.

Comments

-1
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 ?

1 Comment

Sorry, did a quick edit. Should have been i = myAnimal.length().
-3

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.

1 Comment

You should at least try to explain why your change helps. Also, moving the loop increment into the cout operation is clever, but generally considered bad style.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.