简体   繁体   中英

Code complete, but creates an infinite loop?

I am trying to print a pattern like this below, I have the code running with no errors but it generates an infinite loop and I am not certain why;

*
**
***
****
****
***
**
*

Any guidance or help would be great! Thanks

#include <iostream>
#include <string>
using namespace std;

// function member
void star(int amountStars, char starShape);

// function
void star(int amountStars, char starShape)
{
    int i;
    string shape = "*"; 
    for (i = 0; i < starShape; i++)
        // loop to increment through 
        cout << shape;

    cout << endl;

    if (starShape == amountStars)
        // if * is equal to the amount of stars (30)
        return; //**************
    star(amountStars, ++starShape); // increase * by one ***********

    for (i = 0; i < starShape; i++)
        cout << shape;
        cout << endl;


}
int main()
{
    int amountStars = 30; // variable to store the amount of stars

    star(amountStars, '*'); // function print for the amount of stars and the shape

    return 0;
}//end main

Your star() function is calling itself on the line with the comment "increase * by one", which means it is a recursive function. But the termination condition is broken

You intialise the starShape parameter, which is of type char , with a literal '*' which has an ASCII value of 42. But rather than using this as the symbol, you actually use the local string variable shape to do the printing. And you treat starShape as a counter, which you try to use to end the loop. But it starts at 42 and only goes up from there, so it will never be equal to the value of 30 that you pass in.

The simplest (but not best) way to fix this is to change starShape to an int and pass in 0 from main .

#include <iostream>
#include <string>
using namespace std;

// function member
void star(int amountStars, char starShape);

// function
void star(int amountStars, char starShape)
{
    int i;
    string shape = "*"; 
    for (i = 0; i < starShape; i++)
        // loop to increment through 
        cout << shape;

    cout << endl;

    if (starShape == amountStars)
        // if * is equal to the amount of stars (30)
        return; //**************
    star(amountStars, ++starShape); // increase * by one ***********

    for (i = 0; i < starShape; i++)
        cout << shape;
        cout << endl;


}
int main()
{
    int amountStars = 30; // variable to store the amount of stars

    star(amountStars, 0); // function print for the amount of stars and the shape

    return 0;
}//end main

Then go and read up on recursive functions and termination conditions. :)

you make the value of starShape to be *, the ascii value of * is 42, so your code never meet the code:

 if (starShape == amountStars)
        // if * is equal to the amount of stars (30)
        return; //**************

because 42 is larger than 30, that is why your loop is infinite.

Your variable usage is incorrect. Also, the placement of your recursive termination point is questionable (and in this case, ineffective because of the former, incorrect variable usage). Finally, you're increasing the local starShape directly by using pre-increment. There is no need to do so, and in-fact reasons not to.

The specific shape you're describing is an ascending (uphill) count of chars per line until a threshold is reached, then repeating that same sequence descending (downhill) in reverse. The algorithm to do that is:

void func(const int limit, const int current)
{
    // termination case (note >)
    if (current > limit)
        return;

    // TODO: perform task

    // recurse
    func(limit, current+1);

    // TODO: perform task
}

Notice this will, per your given example, contain a repetition in the center of the figure if the same task is done both before, and after, the recursion. In the case of a ascending, then descending line pattern, it would look like this:

*
**
***
****
****
***
**
*

If you do not want the center line repeated, you simply move the location of the recursion and change the condition to matching rather than exceeding:

void func(int limit, int current)
{
    // TODO: perform task

    // termination case (note ==)
    if (current == limit)
        return;

    // recurse
    func(limit, current+1);

    // TODO: perform task
}

This will result in a pattern that looks like this:

*
**
***
****
***
**
*

Note the center line is not repeated as all the others are.

Finally, the task itself, which can simply be:

void starline(const int length)
{
    for (int i=0; i<length; ++i)
        std::cout.put('*');
    std::cout.put('\n');
}

You can take that utility function and use it in either algorithm presented above, and it will work.

Finally, the parameters to all of the above are const because (a) there is no reason to modify them for these algorithms, and (b) if you accidentally do so, you want to catch it at compile-time; not run-time.


Examples

Both algorithms use the same starline() function shown earlier. The only difference is the recursive function, and the results they emit.

The first algorithm and its output are below

#include <iostream>

void starline(const int length)
{
    for (int i=0; i<length; ++i)
        std::cout.put('*');
    std::cout.put('\n');
}

// function
void star(const int amountStars, const int length = 1)
{
    // termination case
    if (length > amountStars)
        return;

    starline(length);
    star(amountStars, length+1);
    starline(length);
}

int main()
{
    star(10);
}

Output

*
**
***
****
*****
******
*******
********
*********
**********
**********
*********
********
*******
******
*****
****
***
**
*

The second is shown next:

#include <iostream>

void starline(const int length)
{
    for (int i=0; i<length; ++i)
        std::cout.put('*');
    std::cout.put('\n');
}

// function
void star(const int amountStars, const int length = 1)
{
    starline(length);

    // termination case
    if (length == amountStars)
        return;

    star(amountStars, length+1);
    starline(length);
}

int main()
{
    star(10);
}

Output

*
**
***
****
*****
******
*******
********
*********
**********
*********
********
*******
******
*****
****
***
**
*

Try this in your main body

main()
{
    //inside main()
    int i,n,j;

    //Reads number of columns from user

    cout<<"Enter value of n : "<<endl;
    cin>>n;

    //Prints the upper half part of the pattern
    for(i=1; i<=n; i++)
    {
        for(j=1; j<=i; j++)
        {
            cout<<"*";
        }
        cout<<endl;
    }

    //Prints the lower half part of the pattern
    for(i=n; i>=1; i--)
    {
        for(j=1; j<i; j++)
        {
            cout<<"*";
        }
        cout<<endl;;
    }

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM