0

@AssertNull Yes the brackets do not count for non-comment line. When I entered 7, it worked fine. I reworked all of the contacts to explain only what the function does, and not how it does it. I went back to ensure the n value wasn't being changed in all of the functions. If I need n to change, I place it within a different variable

@JamesCherrill I got ride of the else {} from my functions that didn't need it.

Now the biggest issue I'm having is the max function. AssertNull, is there something I messed up here? I couldn't have 'n' = next(n) because it would be changing the parameter, so I just placed it in a different variable, but I can't even get my program to run passed that line now. Code::Blocks isn't showing what the issue is or even a hint to what is wrong.

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

//Function Prototype Declaration
int next(int), sequence_Length(int), sequence_Max(int), sequence_Comparison(int),
    initialcomp_Num(int);

void hailstone_Sequence(int);

int main (int argc, char** argv)
{
    int user_Input;

    cout << "What number shall I start with? ";
    cin >> user_Input;
    cout << user_Input << "\n";

    cout << "The hailstone sequence starting at " << user_Input << " is: " << endl;
    hailstone_Sequence(user_Input);

    cout << "\nThe length of the sequence is " << sequence_Length(user_Input);
    cout << ".\n";

    cout << "The largest number in the sequence is " << sequence_Max(user_Input);
    cout << ".\n";
    cout << "The longest hailstone sequence starting with a number up to " << user_Input << " has length "
         << sequence_Comparison(user_Input) << ".\n";

    cout << "The longest hailstone sequence starting with a number up to " << user_Input << " begins with ";
    cout << initialcomp_Num(user_Input) << ".\n";
}

/*
//next(int n)
//Returns a number
//that follows 'n' in the sequence.
*/
int next(int n)
{
    if (n > 1)
    {
        if ((n % 2) == 0)
        {
            return n / 2;
        }
        else
        {
            return  3 * n + 1;;
        }
    }
    return n;

}

/*
//hailstone_Sequence(int n)
//Prints the entire sequence beginning with 'n'.
*/
void hailstone_Sequence (int n)
{
    //Variable Declaration.
    int temp = n;

    cout << temp << " ";

    if (temp > 1)
    {
        while (temp != 1)
        {
            temp = next(temp);
            cout << temp << " ";
        }
    }
}

/*
//sequence_Length(int n)
//Returns the output length of
//the hailstone sequence.
*/
int sequence_Length(int n)
{
    //Variable Declaration.
    int count, temp = n;
    //Determines the length of the sequence until
    //'temp' is equal to 1.
    for (count = 1; temp != 1; count++)
    {
        temp = next(temp);
    }
    return count;
}

/*
//sequence_Max(int n)
//Returns the largest value in the
//hailstone sequence starting at 'n'.
*/
int sequence_Max(int n)
{
    //Variable Declaration.
    int max = n, temp1;

    if ( n <= 1)
    {
        return n;
    }

    temp1 = n;
    while (temp1 > 1)
    {
        temp1 = next(n);
        //temp2 = temp1;

        if(temp1 > max)
        {
            max = temp1;
        }
    }
    return max;
}
    //return max;

/*
//sequence_Comparison(int n)
//Returns the integer with the longest hailstone
//sequence starting from 1 to 'n'.
*/
int sequence_Comparison(int n)
{
    //Variable Declaration.
    int count, top, aftertop;

    if ( n <= 1)
    {
        return n;
    }

    top = sequence_Length(n);
    for (count = 1; count != n; count++)
    {
        if (top < sequence_Length(count))
        {
            aftertop = sequence_Length(count);
            top = aftertop;
        }
    }
    return top;
}

/*
//initialcomp_Num(int n)
//Returns the starting value
//of the longest sequence that starts on a value from
//1 to 'n'.
*/
int initialcomp_Num(int n)
{
    //Variable Declaration.
    int count, initial, topValue, cal;

    //Function will work as intended if 'n' is not less than 1.
    if (n <= 1)
    {
        return n;
    }
    initial = sequence_Length(n);

    for (count = 1; count != n; count++)
    {
        cal = sequence_Length(count);

        if (initial < cal)
        {
            initial = cal;
            topValue = count;
        }
    }
    return topValue;
}
0

Nevermind, I figured out the issue. For one, I need some sleep. Below is the recovery:

int sequence_Max(int n)
{
    //Variable Declaration.
    int max = n, temp = n;

        //temp = n;

        while (temp > 1)
        {
            temp = next(temp);
            if(temp > max)
            {
                max = temp;
            }
        }
        return max;
}
0

I couldn't have 'n' = next(n) because it would be changing the parameter

Who says you can't change the parameter?

int sequence_Max(int n)
{
    //Variable Declaration.
    int max = n;

    if ( n <= 1)
    {
        return n;
    }

    while (n > 1)
    {
        n = next(n);
        if(n > max)
        {
            max = n;
        }
    }
    return max;
}
0

And you can actually take out the if(n <=1) guard above. It has no effect. The while loop below it handles it.

0

Although it's true that you can omit the guard, I would argue for leaving it in. When you're reading a recursive method the first question is (how) does it Terminate? I would be very happy to see that right up front. For me readability trumps efficiency 95% of the time.

Re changing parameters, C++ passes parameters by value unless you specify passing by reference, so the value inside your function is your own private copy of the original, and you can do whatever you like with it.

0

The professor doesn't like to see the starting parameters change value in the function (same with the noncomment lines requirement). I'm not sure if this is a real world thing, but thats what he wants. I'm still trying to wrap my head around it. I was under the impression that I could do whatever as well.....but, this limitations does kind of get to me. Have any of you came across a similar situation? What did the situation prepare you for?

0

Yes, in the past I have seen style guides and standards that deprecate re-using parameter variables,even if the language allows it. I don't know the reason, but maybe its to avoid confusing less-skilled programmers who may think that

void fn(int a) {
   a = 3;
}

int a = 1;
fn(a);
print a

may display the value 3.

It's also common to have style guides about the max length of a function definition (also if block, else block, loop body etc) with the value set about 1 screen-full. That's a valid readability/understandability target, but it's totally unrealistic as a mandatory standard. Sometimes its clearer to keep code together in one block, even if it is a bit long.
In practice, if you adopt good design, with single-purpose functions, and optimum cohesion & coupling then the resulting code blocks will be the right size anyway.

Having said that, I see where your prof is coming from. Here on DaniWeb we often see beginner's programs that are one huge function with ifs and their matching elses separated literaly by hundreds of lines. The are totally unreadable. Better to stamp that out from day 1 than try to fix bad habits later. I get obsessive about variable and function names for the same reason :)

Edited by JamesCherrill

0

I'm not sure if this is a real world thing

If "real world" means "professional C++ programmers", no.

but thats what he wants.

What the professor wants, the professor gets!

I'm still trying to wrap my head around it.

Might be one of those things you should just accept rather than try to understand, or just ask him straight out and see if he answers. He may or may not have a good reason for this, but even if he has a good reason, it probably won't register till you get more experienced, sort of like Mr. Miyagi's "Wax on, wax off". Do it first, worry about why later.

I was under the impression that I could do whatever as well

You can do whatever you want within the guidelines of the requirements. If the requirement means you can't change the parameter, then you can't change the parameter.

but, this limitations does kind of get to me.

Try not to let it get to you. Again, I would ask the professor straight out. You may or may not get an answer that you understand or like, but why speculate?

Have any of you came across a similar situation?

Yep. I've dealt with all sorts of professors/bosses that had their own quirky way of doing things. You have to pick your battles. If it gets too stupid to handle, you drop the class or leave the job. If it's harmless, just roll with it. My general approach to to topics where I am a newbie is to assume the person taching/training me knows what he's doing and there is a method behind the madness even if I don't understand it. Until proven otherwise. Sometimes the professor IS wrong (ie all the threads in Daniweb using obsolete compilers for absolutely no reason).

What did the situation prepare you for?

It prepared me for the real world, picking my battles, knowing when to surrender, knowing when to fight, knowing when to suck it up and drive on, knowing when I was on a sinking ship and needed to jump off, knowing how to deal with incompetent people without losing my own competence or my own sanity, and knowing when to simply go with the program and get the grade/paycheck.

You've been given a specification. You must follow that specification right, wrong, or indifferent if you want a good grade. The prof might very well say, in three weeks, something like "So far we haven't changed the paramter value. Now you can..." Sometimes when teaching, you teach it "wrong" on purpose to beginners on purpose to keep it simple so they don't get in over their heads. Perfect example is the first semester Physics concept of a "frictionless, massless pulley". Everyone knows pullies aren't frictionless or massless, but you have too many variables too soon otherwise, so you simplify things. So tennis balls fall in a vacuum, projectiles don't spin, no energy is lost when two balls collide, etc., etc.

This isn't something to worry about.

0

@AssertNull I remember you pointing out that when you inputted a certain value, that the last function in my program would give you an incorrect number. I'm not sure what is going on here to the point that occurs for certain number, but not all. It has something to do with the 'topValue' variable. When I used code::blocks...I had no issue. Once I switched over to noMachine, thats when the issue came about. Not sure how the issue was covered up in code::blocks.

0

Can 't think of why you'd have no issues in Code Blocks. Try entering 2. You get good results from initialcomp_Num?

0

When entered 9, I got a huge number at the end. I was able to see in noMachine this error:

g++ -Wall -Wshadow -Wuninitialized -O -o hailstone hailstone.cpp
hailstone.cpp: In function ‘int initialcomp_Num(int)’:
hailstone.cpp:163:25: warning: ‘topValue’ may be used uninitialized in this function [-Wmaybe-uninitialized]
 int count, initial, topValue, cal;
                     ^

I'm completely lost because it clearly shows topValue = count

0

So I gave topValue and initial value of 0. Now the problem seems to be the if statement in the for loop. I have to figure out what to do with the topValue if the initial and cal are equal to one another. The previous function was way easier to deal with.

0

Glad you figured it out. To go back to my earlier tips way back...

Every time you assign a new value to top, assign the value that resulted in the sequence of length top to start.

Key word is "Every" from "Every time". You changed the variables and it might be a different function, but the concept is the same. Every time you set initial, you must set topValue. See below.

int initialcomp_Num(int n)
{
    //Variable Declaration.
    int count, initial, topValue, cal;

    //Function will work as intended if 'n' is not less than 1.
    if (n <= 1)
    {
        return n;
    }
    initial = sequence_Length(n);
    // add line below.
    topValue = n;

    for (count = 1; count != n; count++)
    {
        cal = sequence_Length(count);

        if (initial < cal)
        {
            initial = cal;
            topValue = count;
        }
    }
    return topValue;
}

That's it.

There's no limit to the accuracy of the Hailstone Sequence. It's 100% accurate in that there is no roundoff error. You can, however, get such huge numbers that the C++ integer type cannot store the number if your number gets too far above around 2 billion in a 32-bit system. I'm not sure what will happen with your program if/when that happens.

You say you've solved it, so I won't point out the problem with entering 9 with the code you have (presumably changed).

As an important side note, sometimes you get away with bad coding. How the compiler and the processor handle the code is beyond the scope of this thread, but it could explain why you got different output on different systems. If there are no bugs in your code, it will work everywhere.

0

If there are no bugs in your code, it will work everywhere.

True for many modern languages, but not C++. C++ suffers from "undefined behaviour" - code situations that the language definition deliberately says are legal but whose implementation can be left for the compiler to decide what to do. The best you can hope for is that your compiler will flag any such nightmares.
Eg

i = ++i + 2;       // undefined behavior until C++11
i = i++ + 2;       // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i);       // undefined behavior until C++17, unspecified after C++17
i = ++i + i++;     // undefined behavior
0

I generally take the view that if I code something in a way that can result in "undefined behavior", I have a "bug", though definitions of "bug" vary. Whether C++ "suffers" from undefined behavior or whether that's a FEATURE of C++ is also in the eyes of the beholder. If the beholder is the compiler writer, it's definitely a feature. From the programmer's point of view, it can be a nuisance for sure, but still a feature usually. C++ gives you a lot of rope to hang yourself with, intentionally so. If the C++ compiler was a building inspector, all the alarms, smoke detectors, fuses, and circuit breakers would be optional.

Case in point, I suggested that the OP type in 2 to make his program give bad results. Then I typed in 2 and it gave good results even with the bug. Dumb luck.

For this particular program and the OP's code, the bug was a logic error. The Wmaybe-uninitialized flag caught it and gave a warning rather than an error, which you are allowed to ignore. It's been a while, but I think Java might make that an error and force you to initialize a variable even if it's guaranteed that it will be overwritten later, which is anathema to the C++ way of thinking which always assumes that the programmer knows exactly what he's doing and never sacrifices efficiency for safety.

0

Yes, Java is pretty strict on making sure you have initialised variables - and the logic analysis it does to confirm that is pretty sophisticated, but in the end it goes for safety. "No surprises at run time" is a fundamental desire behind Java's design.

Honestly, having avoided C++ like the Devil's spawn, I was still astonished to discover that something as innocent as f(f1(i), f2(j)) is code that can legally produce different results at run time depending on the compiler's whim. The Java Language Spec, incidentally, does describe what the one correct solution is for the Java equivalent, and it's not difficult. I guess that compiler writers write C++ compilers to suit themselves, so making their life a bit easier is well worth the price of having ordinary programs produce unpredictable results

Anyway, please feel free to ignore this as the rantings of a bigot who thinks C++ should have been strangled at birth.

Edited by JamesCherrill

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.