0

So I have a program which simplifies a Boolean Expression. What I'm trying to achieve is that at the end of simplification of the first Expression I'd want the user to choose whether he would want to simplify another Expression or just Exit the Console Application ( The programme ).

Here's the code for the Main function

int main(int argc, char *argv[]) {

/* allow command line calling with arguments -m -b X
where X is a number. order or -m and -b X does not
matter*/
cout << "\Designed By a Student For the Students :)\n";
char choice;
do
{
    cout << "\nEnter the number of variables to be Minimized\n";
    cin >> m;
    if (argc >= 2)
    {
        string arg = argv[1];
        if (arg.find("-m") != -1) {
            show_mid = true;
            if (argc >= 3) {
                arg = argv[2];
                if (arg.find("-b") != -1)
                    MIN_BIT = atoi(argv[3]);
            }
        }
        else if (arg.find("-h") != -1) {
            cout << "-b X\tminimum bits should be X.\n"
                << "-m  \tshow mid process computation.\n"
                << "-h  \tshow this.\n";
                                     return 0;


        }
        else {
            if (arg.find("-b") != -1 && argc >= 3)
                MIN_BIT = atoi(argv[2]);

            if (argc >= 4) {
                arg = argv[3];
                if (arg.find("-m") != -1)
                    show_mid = true;
            }
            else
            {
                cout << "Invalid argument\n"
                    << "-b X\tminimum bits should be X.\n"
                    << "-m  \tshow mid process computation.\n"
                    << "-h  \tshow this.\n";
                                            return 0;

            }
        }
    }

    getinput();
    init();
    cout << "Press 'y' to Reduce Another Expression or 'n' to Close this Application";
    cin >> choice;
} while (choice == 'y');
WINPAUSE;
return 0;

}

As you can see above i've used a do while Loop for the purpose, but i face two issues here i.e The programme terminates without taking user input and if I use WINPAUSE the programme exits when i PRESS ANY KEY. Is recursion an answer, please suggest a workaround.

Note: I use VS2017 IDE..:)

Edit: new code

int main(int argc, char *argv[]) {

/* allow command line calling with arguments -m -b X
where X is a number. order or -m and -b X does not
matter*/
cout << "\Designed By a Student For the Students :)\n";
char choice;
    if (argc >= 2)
    {
        string arg = argv[1];
        if (arg.find("-m") != -1) {
            show_mid = true;
            if (argc >= 3) {
                arg = argv[2];
                if (arg.find("-b") != -1)
                    MIN_BIT = atoi(argv[3]);
            }
        }
        else if (arg.find("-h") != -1) {
            cout << "-b X\tminimum bits should be X.\n"
                << "-m  \tshow mid process computation.\n"
                << "-h  \tshow this.\n";


        }
        else {
            if (arg.find("-b") != -1 && argc >= 3)
                MIN_BIT = atoi(argv[2]);

            if (argc >= 4) {
                arg = argv[3];
                if (arg.find("-m") != -1)
                    show_mid = true;
            }
            else
            {
                cout << "Invalid argument\n"
                    << "-b X\tminimum bits should be X.\n"
                    << "-m  \tshow mid process computation.\n"
                    << "-h  \tshow this.\n";

            }
        }
    }
    do
    {
        cout << "\nEnter the number of variables to be Minimized\n";
        cin >> m;
        getinput();
        init();
        cout << "Press 'y' to Reduce Another Expression or 'n' to Close this Application";
        cin >> choice;
    } while (choice == 'y');
WINPAUSE;
return 0;

}

edit : Here's the code for getinput() and init()

void getinput() {
unsigned in;
int num_bits = 0;
cout << "\nInput value followed by ENTER[^D ends input]\n> ";
while (cin >> in) {
    input_values.push_back(in);
    num_bits = count_bits(in);
    if (num_bits>MIN_BIT)
        MIN_BIT = num_bits;
    cout << "> ";
}
}
/*return min number of bits a number is represented by. used for best output*/
unsigned count_bits(unsigned n) {
    short bit = 0;
    int count = 0;
    while (n>0) {
        bit = n % 2;
        n >>= 1;
        count++;
    }
    return count;
}


void init() {
table.resize(1);
p_group.resize(1);
final_group.resize(1);
create_table();
print_table();
create_p_group();
if (show_mid)
    print_p_group();
create_final_group();
print_final_group();

}

Chris
  • 11
  • 7
  • 1
    If you plan to call `main()`, don't do it, that's forbidden (undefined behavior). – alain Sep 22 '17 at 16:19
  • any key including 'y' ? – Vijay Kalmath Sep 22 '17 at 16:20
  • 1
    Since you have return 0 in your else if and else block...the program terminates...Remove them... – Vijay Kalmath Sep 22 '17 at 16:21
  • @VijayKalmath Yes including 'y' – Chris Sep 22 '17 at 16:22
  • @VijayKalmath I've tried that too, I'd have to make the main function void which I did but the programme has the same behaviour. – Chris Sep 22 '17 at 16:23
  • Not really..you have a return 0 in the end..don't have to make main function void – Vijay Kalmath Sep 22 '17 at 16:27
  • 1
    Alas, the sizable pile of ill-advised globals makes this rather obfuscated. The two `return`-s I see are there to dump a usage-guide, then terminate the program (perfectly reasonable). They fire when the *command line arguments* (not the user prompt) aren't what you're expecting. The value of `m` is worthless until you make it past the command-line startup arguments, which you seem bent on reprocessing for each iteration for some reason. Frankly, all the setup of those globals would likely be better done *outside* of this loop. – WhozCraig Sep 22 '17 at 16:32
  • @VijayKalmath Oh yeah I missed that, and I actually tried what u said and it worked!! – Chris Sep 22 '17 at 16:40

2 Answers2

1

You logic is flawed in a number of places, and though the pile of globals make it somewhat obfuscated, some things are clear:

  • Stop reprocessing command line arguments on each iteration.
  • Realize that formatted extraction of a char does NOT skip whitespace

The former of these is likely proper if you're properly parsing your command line arguments. In short, if you find your program terminating prior to reaching your loop, it means your command line arguments are either not proper, or your parsing logic is broken

The latter of these is what is holding up your loop from properly terminating. Your prior formatted input, unless consuming full line data (including the trailing newline), will leave at least a newline on the input stream. Without clearing that, the formatted character read for choice will simply use that, which obviously isn't the value 'y'. To accommodate for that, prior to reading the choice, discard any data in the input stream through any newline. Note: this step is NOT needed if your input processing is using something like std::getline, which consumes (and discards) newlines.

You loop should look like this:

int main(int argc, char *argv[])
{
    /* configure command line argument settings ONCE */
    if (argc >= 2)
    {
        string arg = argv[1];
        if (arg.find("-m") != -1) {
            show_mid = true;
            if (argc >= 3) {
                arg = argv[2];
                if (arg.find("-b") != -1)
                    MIN_BIT = atoi(argv[3]);
            }
        }
        else if (arg.find("-h") != -1) {
            cout << "-b X\tminimum bits should be X.\n"
            << "-m  \tshow mid process computation.\n"
            << "-h  \tshow this.\n";
            return 0;

        }
        else {
            if (arg.find("-b") != -1 && argc >= 3)
                MIN_BIT = atoi(argv[2]);

            if (argc >= 4) {
                arg = argv[3];
                if (arg.find("-m") != -1)
                    show_mid = true;
            }
            else
            {
                cout << "Invalid argument\n"
                << "-b X\tminimum bits should be X.\n"
                << "-m  \tshow mid process computation.\n"
                << "-h  \tshow this.\n";
                return 0;
            }
        }
    }

    cout << "Designed By a Student For the Students :)\n";
    char choice = 'y';
    do
    {
        cout << "\nEnter the number of variables to be Minimized\n";
        if (cin >> m)
        {
            getinput();
            init();
            cout << "Press 'y' to Reduce Another Expression or 'n' to Close this Application";

            // flush through eoln, read prompt
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            if (!(std::cin >> choice))
                break;
        }
        else
        {   // could not extract a valid value for m. not much more we can do.
            break;
        }

    } while (choice == 'y');
    return 0;
}
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • 1
    @VijayKalmath there should be no need to in this loop. Both input extractions will terminate the loop on failure, by design. Normally if you're performing formatted input and want to *skip* undecipherable data, a clear+ignore pairing is warranted; not in this case. – WhozCraig Sep 22 '17 at 16:57
  • Clubbing my answer for your previous reply on my post, first 'm' can change per iteration as per the wish of the user ( defined in getinput() ) , and I've defined a macro to calculate the value of MIN_BIT which depends on 'm' , which also varies per iteration of the main function. Please let me know if I haven't made myself​ clear on this aspect. – Chris Sep 22 '17 at 16:58
  • I'm a novice and your code is much much more neat :-) @WhozCraig – Chris Sep 22 '17 at 17:03
  • @chrisstone this answer does two things: (1) process the command line arguments (if any) to setup your globals, then (2), enters a loop to processing input values of `m`, then your `getinput()` and `init()` operations, and conditionally continues the loop by prompting for a `'y'`, or non-`'y'` input. From my understanding, that is precisely what you need. There is no reason to repeatedly process your command line arguments. If something setup during command line processing is dependent on `m`, it should be concisely moved into the loop. – WhozCraig Sep 22 '17 at 17:09
  • Oh okay, I get that Craig. But now it doesn't repeat the iteration and the console application closes irrespective of my input :( – Chris Sep 22 '17 at 17:22
  • @chrisstone just edit the question...write edit: new code. Will help in solving your problem – Vijay Kalmath Sep 22 '17 at 17:24
  • @VijayKalmath Please check now. – Chris Sep 22 '17 at 17:46
  • @chrisstone you didn't do what he said, You were supposed to *add* in your new code as an addendum, not replace your existing code, which makes every comment and/or answer up to that point completely meaningless to the now-posted code, which is no longer what was there before. In short, a progression. – WhozCraig Sep 22 '17 at 17:48
  • @chrisstone while I am not sure about your getinput() and init(), the program seems to be working fine and is asking me for choice and iterating itself when I executed it. – Vijay Kalmath Sep 22 '17 at 18:00
  • @chrisstone The easiest way to know if the problem is rooted in your data management of `getinput` and `init`, is to simply remove them from the loop and run it again. Obviously nothing gets done, but the choice-processing should work, asking you each time for the value of `m`, then immediately asking for your choice selection. If that works, the issue is related to whatever `getinput` and/or `init` leave in the input stream, and we can't help with that. That ball is in your court. – WhozCraig Sep 22 '17 at 18:03
  • So this is what is happening, in debug mode or release when I press 'y' the Console opens afresh when I press it again the Console exits and doesn't open back up again. Which means it's working for only one iteration. Does the problem lie in getinput() and init() functions? – Chris Sep 22 '17 at 18:25
  • @chrisstone If you removed those function calls the loop simply repeats itself, eating a value for `m` and then prompting you for your choice, then with certainty, *yes*, the problem is related to those functions... somehow. – WhozCraig Sep 22 '17 at 18:28
  • I've checked without the getinput() and init() functions, it works fine. And I've posted the code for those two functions as an edit. – Chris Sep 22 '17 at 18:42
  • @chrisstone, Yeah, the problem is in the state `getinput` leaves `cin` in. It consumes data until there is no more, and in so doing the stream is left in a eof/fail state. That means later stream reads will fail on inception, including your `m` and `choice`. That function is designed to only process input *once*. You have to clear the `cin` stream state before prompting for your choice and repeating your loop. The globals and their effects certainly aren't helping any here. It will *probably* work if you put `cin.clear()` at the end of `getinput()`, btw. – WhozCraig Sep 22 '17 at 18:46
  • I get this error when I use cin.clear => Severity Code Description Project File Line Suppression State Error C3867 'std::basic_ios>::clear': non-standard syntax; use '&' to create a pointer to member – Chris Sep 22 '17 at 18:55
  • Thus the qualifier, "probably". You forgot your `()`. Honestly, `m` is apparently unused in `getinput`, and I have no idea why. as I said, the nature of using globals is bugs like that. ctrl-D termination should not be required if `m` is honored for each iteration. – WhozCraig Sep 22 '17 at 18:57
  • I fixed that error but still same response from the application. – Chris Sep 22 '17 at 19:10
0

Move the part of checking the command line arguments before your for loop, like this:

cout << "\nEnter the number of variables to be Minimized\n";
cin >> m;
if (argc >= 2)
{
        string arg = argv[1];
        ...
        else
        {
            cout << "Invalid argument\n"
                << "-b X\tminimum bits should be X.\n"
                << "-m  \tshow mid process computation.\n"
                << "-h  \tshow this.\n";
            return 0;
        }
    }
}

do
{
    // your logic, init(), etc.
    cout << "Press 'y' to Reduce Another Expression or 'n' to Close this Application\n";
    cin >> choice;

} while (choice == 'y');

and then your

You have many statements of this kind:

if (arg.find("-m") != -1)

You should use string::npos to test for no matches found, as suggested in the std::string::find. So change them to, in this way:

if (arg.find("-m") != string::npos)

I'd have to make the main function void

NO.

Do not do that. What should main() return in C and C++? int is the answer.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 2
    Yea..told him the same thing... Kudos for writing it in entirety. – Vijay Kalmath Sep 22 '17 at 16:25
  • 1
    Thanks a ton guys gsamaras and @Vijay_Kalmath it worked. But then there's an issue, when I press y the console application starts up again afresh whereas I would like it to continue on the same screen. Any ideas? – Chris Sep 22 '17 at 16:44
  • @chrisstone you mean it stops (your program exits the loop)? – gsamaras Sep 22 '17 at 16:44
  • @gsamaras Yes it exists the loop when the input is anything else other than 'y'. Once again I'd like to point that I'm designing a Console Application, so when the input is 'y' the current console closes and opens a new fresh one. My question was that is there any way how I could continue on the same Console without starting afresh? – Chris Sep 22 '17 at 16:49