-3

I'm using Microsoft Visual Studio 2017 Community and was curious about something. How do you properly end a program with a switch function? I know that programmers have certain no-no's like exit(). I have tried using return 0; in different places like in function goodbye and in the switch but haven't had any luck, it just ends the function or switch, but the problem is it does not quit or close the program. Also feel free to correct me on anything that might be wrong or could be done better. I'm really new to c++ and this is my first program. Note: Tried to avoid making username a global variable but it is used in several functions, so I went ahead and made it global.

Here is my example:

#include <iostream>
#include <string>
#include <fstream>

/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
////                Switch does not end program on QUIT :(                   ////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

void welcome();

int options_menu();

void register_username();

std::string register_password();

void save_user(const std::string &password);

void user_login();
void display_file();

void clock_in_hour();
void clock_in_minute();
void clock_out_hour();
void clock_out_minute();

void test();

void goodbye();

std::string username;

template <typename T>
T get_input(const std::string &strQuery)
{
    std::cout << strQuery << "\n> ";
    T out = T();

    while (!(std::cin >> out))
    {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits <std::streamsize>::max(), '\n');
        std::cout << "Error!" "\n";
        std::cout << strQuery << "\n> ";
    }
    return out;
}

int main()
{
    welcome();
    options_menu();
    test();
    return 0;
}

void welcome()
{
    std::cout << "Welcome to the Time Card Calculator Pro V1.0 \n\n";
}

int options_menu()
{
    int menu = 0;

        std::cout << "Please type an option number and press enter to continue: \n\n";

        std::cout << "[1] Register \n";
        std::cout << "[2] Login \n";
        std::cout << "[3] Quit \n\n";

        menu = get_input <int>("Please type an option number and press enter to continue \n");

        switch (menu)
        {
        case 1:
            std::cout << "\n";
            std::cout << "You chose to register \n\n";
            register_username();
            break;
        case 2:
            std::cout << "\n";
            std::cout << "You chose to login \n\n";
            user_login();
            break;
        case 3:
            std::cout << "\n";
            std::cout << "You chose to quit \n\n";
            goodbye();
            break;
        default:
            std::cout << "\n";
            std::cout << "Error! Invalid option \n\n";
            options_menu();
            break;
        }
}

void register_username()
{
    std::string username;

    std::cout << "Please enter your full name: ";   //ask user to create username...
    std::cin.ignore();
    std::getline(std::cin, username);

    while (get_input <int>("Confirm? [0|1]") != 1)
    {
        std::cout << "Please enter your full name: ";
        std::cin.ignore();
        std::getline(std::cin, username);
    }

    std::ifstream file(username + ".txt");  //check if user file exists...
    if (file.is_open())
    {
        std::cout << "Error! Username already taken \n\n";
        options_menu();
    }
    else     //ask user to create a password...
    {
        register_password();
    }
}

std::string register_password()
{
    std::cout << "Now please create a password \n";
    std::string ask_password = get_input<std::string>("Password may not have any spaces ");
    std::string password = get_input<std::string>("Please re-enter the password ");

    if (ask_password == password)
    {
        save_user(password);
    }
    else
    {
        std::cout << "Error: Passwords did not match \n";
        register_password();
    }
    return password;
}

void save_user(const std::string &password)
{
    std::cout << "Saving user info... \n";

    std::ofstream file(username + ".txt");
    file << password << "\n";

    std::cout << "Username: " << username << "\n";
    std::cout << "Password: " << password << "\n";
}

void user_login()
{
    std::cout << "Please enter your username ";
    std::cin.ignore();
    std::getline(std::cin, username);

    std::cout << "Searching for file... \n";

    std::ifstream file(username + ".txt");  //look for user file...

    if (file.is_open())     //if user file is found...
    {
        std::cout << "File found \n";
        display_file();
    }
    else
    {
        std::cout << "Error: Username not registered \n";
        std::cout << "Please register username \n";
        options_menu();
    }
}

void display_file()
{
    std::string line;
    int numberoflines = 0;

    std::cout << "Searching for user file " << username << "\n";

    std::ifstream file(username + ".txt");
    while (std::getline(file, line))
    {
        std::cout << line << "\n";
        numberoflines++;
    }
}


void test()
{
    std::cout << "This is a test \n";
}

void goodbye()
{
    std::cout << "Thank you for using the Time Card Calculator Pro V1.0 \n";
    std::cout << "Good bye \n";
}
  • 6
    You're starting too big! Narrow the question down to a [mcve], and in doing so you may even stumble across your own problem. Why not have a simple `main()` function with a hard-coded variable and `switch`, and see if that exits? From there, build it up to take input from the user. – Tas Jul 31 '17 at 02:15
  • Possible duplicate of [How do I make a C++ console program exit?](https://stackoverflow.com/questions/4038302/how-do-i-make-a-c-console-program-exit) – philipxy Jul 31 '17 at 02:51

2 Answers2

1

You need to return something from your switch statement to your main loop. The return 0 in you main loop is what terminates the program.

int main()
{
    welcome();
    int exitNow = options_menu(); //lets say a -1 return is the symbol for exit
    while(exitNow != -1)
        exitNow = options_menu();
    test();
    return 0;
}

So your switch would be something like this:

int options_menu()
{
    int menu = 0;

        std::cout << "Please type an option number and press enter to continue: \n\n";

        std::cout << "[1] Register \n";
        std::cout << "[2] Login \n";
        std::cout << "[3] Quit \n\n";

        menu = get_input <int>("Please type an option number and press enter to continue \n");

        switch (menu)
        {
        case 1:
            std::cout << "\n";
            std::cout << "You chose to register \n\n";
            register_username();
            break;
        case 2:
            std::cout << "\n";
            std::cout << "You chose to login \n\n";
            user_login();
            break;
        case 3:
            std::cout << "\n";
            std::cout << "You chose to quit \n\n";
            goodbye();
            return -1;
            break;
        default:
            std::cout << "\n";
            std::cout << "Error! Invalid option \n\n";
            options_menu();
            break;
        }
     return 0;
}
  • I solved this and I'm really sorry about including the entire code instead of just the small part that I needed to solve. I solved my problem by keeping options_menu a void function. I then made my menu variable global so I could set it up for a while statement right in the main function. I called the options_menu() function above the while statement. I made the while statement while menu isn't equal to 3 (the quit case) then return 0; in main (end the program). – pickybeginner Jul 31 '17 at 05:31
  • Its bad practice to have global variables. Just an fyi – Error - Syntactical Remorse Jul 31 '17 at 11:25
  • Your code did not end the program, and was not the answer to the problem. On another note I will figure out how to do my method (which actually works and ends the program like it is supposed to) without global variables. Thank you for the tip, I usually try to avoid global variables but this time seemed a bit tricky for me. Thinking about somehow keeping menu variable scoped but at the same time return it to main. – pickybeginner Aug 01 '17 at 01:11
  • notice how in my example below, the test function gets ignored (and everything else called after it) if you select quit from the options menu, effectively ending the program, not just ending the switch or function. – pickybeginner Aug 01 '17 at 01:15
  • In your example below the `while` loop is pointless. The program terminates instantly after `test()` is called. Basically after the user selects an option the code will always terminate. The `while` could be an `if` and have the same effect in your example below. – Error - Syntactical Remorse Aug 01 '17 at 01:19
0

I solved my problem just now :) just please let me know if this is a no-no like exit() or system(). I don't want to get into bad habits like I read about everywhere. I try to be careful. Here is my answer to my question. I hope it's okay. It does work though. Notice how the test function (or any function called after it or in it's place) does not get called if you select quit from the menu. So, now the quit option works, now the question is, is this good code? Please feel free to give me advice or correct me anywhere or get me into good habits for programming. Thank you everyone that took the time to read through the long code and for lending me their insights.

#include <iostream>
#include <string>
#include <fstream>
#include <limits>

void welcome();

void options_menu();

void register_username();

std::string register_password();

void save_user(const std::string &password);

void user_login();
void display_file();

void test();

void goodbye();

std::string username;
int menu = 0;

template <typename T>
T get_input(const std::string &strQuery)
{
    std::cout << strQuery << "\n> ";
    T out = T();

    while (!(std::cin >> out))
    {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits <std::streamsize>::max(), '\n');
        std::cout << "Error!" "\n";
        std::cout << strQuery << "\n> ";
    }
    return out;
}

int main()
{
    welcome();
    options_menu();
    while (menu != 3)
    {
        test();
        return 0;
    }
    return 0;
}

void welcome()
{
    std::cout << "Welcome to the Time Card Calculator Pro V1.0 \n\n";
}

void options_menu()
{
    std::cout << "Please type an option number and press enter to continue: \n\n";
    std::cout << "[1] Register \n";
    std::cout << "[2] Login \n";
    std::cout << "[3] Quit \n\n";

    menu = get_input <int>("Please type an option number and press enter to continue \n");

        switch (menu)
        {
        case 1:
            std::cout << "\n";
            std::cout << "You chose to register \n\n";
            register_username();
            break;
        case 2:
            std::cout << "\n";
            std::cout << "You chose to login \n\n";
            user_login();
            break;
        case 3:
            std::cout << "\n";
            std::cout << "You chose to quit \n\n";
            goodbye();
            break;
        default:
            std::cout << "\n";
            std::cout << "Error! Invalid option \n\n";
            options_menu();
            break;
        }
}

void register_username()
{
    std::string username;

    std::cout << "Please enter your full name: ";   //ask user to create username...
    std::cin.ignore();
    std::getline(std::cin, username);

    while (get_input <int>("Confirm? [0|1]") != 1)
    {
        std::cout << "Please enter your full name: ";
        std::cin.ignore();
        std::getline(std::cin, username);
    }

    std::ifstream file(username + ".txt");  //check if user file exists...
    if (file.is_open())
    {
        std::cout << "Error! Username already taken \n\n";
        options_menu();
    }
    else     //ask user to create a password...
    {
        register_password();
    }
}

std::string register_password()
{
    std::cout << "Now please create a password \n";
    std::string ask_password = get_input<std::string>("Password may not have any spaces ");
    std::string password = get_input<std::string>("Please re-enter the password ");

    if (ask_password == password)
    {
        save_user(password);
    }
    else
    {
        std::cout << "Error: Passwords did not match \n";
        register_password();
    }
    return password;
}

void save_user(const std::string &password)
{
    std::cout << "Saving user info... \n";

    std::ofstream file(username + ".txt");
    file << password << "\n";

    std::cout << "File saved \n";
    std::cout << "Username: " << username << "\n";
    std::cout << "Password: " << password << "\n";
}

void user_login()
{
    std::cout << "Please enter your username ";
    std::cin.ignore();
    std::getline(std::cin, username);

    std::cout << "Searching for file... \n";

    std::ifstream file(username + ".txt");  //look for user file...

    if (file.is_open())     //if user file is found...
    {
        std::cout << "File found \n";
        display_file();
    }
    else
    {
        std::cout << "Error: Username not registered \n";
        std::cout << "Please register username \n";
        options_menu();
    }
}

void display_file()
{
    std::string line;
    int numberoflines = 0;

    std::cout << "Searching for user file " << username << "\n";

    std::ifstream file(username + ".txt");
    while (std::getline(file, line))
    {
        std::cout << line << "\n";
        numberoflines++;
    }
}

void test()
{
    std::cout << "This is a test \n";
}

void goodbye()
{
    std::cout << "Thank you for using the Time Card Calculator Pro V1.0 \n";
    std::cout << "Goodbye \n";
}

  • Additional note: return 0; ONLY ends the program if called in main. It will only end the function or process if called in function or process. return 0; to end the program MUST BE CALLED FROM MAIN as far as I know... – pickybeginner Jul 31 '17 at 05:46
  • edit: changed the if else statement in main into a while statement to shorten the code and simplify it. – pickybeginner Aug 01 '17 at 01:17
  • `return 0;` must be called in your `main` function to terminate an overall program, that's normally universal in c++. – Error - Syntactical Remorse Aug 01 '17 at 01:25
  • I feel like not enough people know this and the online tutorials I found do not effectively teach it. Most people on these sites seem to think that it ends the program and not the function/loop if called in a function that is not main. I'm glad we found the root of the problem and I will now put this question as solved :) btw I got rid of my username global variable but the menu variable stayed global as it needs to be recognized by main and there is no way to return the value of int menu back to main that I know of... Thank you for the tips and I hope I helped someone out there as well :) – pickybeginner Aug 01 '17 at 03:27
  • Tried to mark the correct answer but was not allowed. I guess more answers will be allowed as long as I'm restricted... sorry... – pickybeginner Aug 01 '17 at 03:29