-2

i'm trying to make a simple shell in c++ but i'm having some trouble to make it work:

#pragma warning (disable : 4996)
#include <iostream>
#include <string>
#include <chrono>
#include <ctime>
#include <filesystem>
#include <fstream>
#ifdef _WIN64
#include <direct.h>
#else
#include <unistd.h>
#endif
#define clear cout << "\033[H\033[J"
#define MAXLETTER 1000
#define MAXCOMMAND 1000
using namespace std;

const string currentDateTime() {
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[128];
    tstruct = *localtime(&now);
    strftime(buf, sizeof(buf), "%d/%m/%Y, %X", &tstruct);
    return buf;
}
void help() {
    cout << "core's shell, build 0 from September, 2021." << endl;
    cout << "Available commands:" << endl;
    cout << "exit - exit shell" << endl;
    cout << "cd - changes current working directory" << endl;
    cout << "help - shows this message" << endl;
    cout << "chprompt - changes shell's prompt" << endl;
}
void start() {
    string username = getenv("USERNAME");
    cout << "Welcome to core's shell, " << username << "." << endl;
    cout << currentDateTime() << endl;
}
int main() {
    string prompt = ": ";
    string command;
    const char* command_list[8];
    command_list[0] = "exit";
    command_list[1] = "cd";
    command_list[2] = "help";
    command_list[3] = "chprompt";
    command_list[4] = "start";
    int switch_arg = 0;
    const char* dir = getenv("CD");
    string history("history.csh");
    fstream history_file;
    clear;
    start();
command:
    history_file.open(history, ios::out);
    cout << prompt;
    getline(cin, command);
    if (history_file.is_open()) {
        history_file << command;
    }
    switch (switch_arg) {
    case 1:
        history_file.close();
        exit(0);
    case 2:
        _chdir(dir);
        return 0;
        break;
    case 3:
        help();
        return 0;
        break;
    case 4:
        cout << "Type in your prompt: ";
        cin >> prompt;
        break;
    case 5:
        start();
        break;
    default:
        cout << "Command not found" << endl;
        goto command;
    }
    return 0;
}

how do i use case on strings to make my commands work?

is there a better way to make a command history?

i'm making this code based on this code right here: https://www.geeksforgeeks.org/making-linux-shell-c/

sorry if the question is stupid, i'm quite rusty on c++.

retro
  • 1
  • 4
    Isn't a ***shell*** (as simple as it can be) a too hard task for a C++ (re-)beginner? – Enlico Sep 21 '21 at 15:07
  • When did you read in `switch_arg`? – drescherjm Sep 21 '21 at 15:08
  • 1
    C++ `switch` does not work with strings, only integral types. You also don't update `switch_arg`. – crashmstr Sep 21 '21 at 15:08
  • You also have this problem: [https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction](https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction) – drescherjm Sep 21 '21 at 15:08
  • 4
    First thing is you are relying on a C example to learn C++. C and C++ are different languages even if sometimes a C++ compiler accepts C. You should look for resources and references that are explicitly for C++, and which were made after 2011. Second geeksforgeeks.org is, in my opinion, not a good reference. Most of time, when I find a link to one of their articles, it contains mistakes or bad advice. Third, you cannot use `switch`/`case` with strings. There are schemes based on hashing but it is not a worthwhile approach. – François Andrieux Sep 21 '21 at 15:09
  • 1
    What is the use of a history if you are not using it in the shell? If you want to keep the history in memory I would store it in a std::vector, std::queue, or as a circular buffer (https://www.boost.org/doc/libs/1_77_0/doc/html/circular_buffer.html) – alfC Sep 21 '21 at 15:09
  • You could solve the switch problem in c++ with something like the following but it's not really a beginner code: [https://stackoverflow.com/questions/3113139/how-to-create-mapstring-classmethod-in-c-and-be-able-to-search-for-functi/3114231](https://stackoverflow.com/questions/3113139/how-to-create-mapstring-classmethod-in-c-and-be-able-to-search-for-functi/3114231) – drescherjm Sep 21 '21 at 15:13
  • Here is a way to use the switch /case : [https://stackoverflow.com/a/38166893/487892](https://stackoverflow.com/a/38166893/487892) – drescherjm Sep 21 '21 at 15:14
  • Do not use switch, which doesn't work on string. Also it doesn't scale. Use a proper parser. https://www.boost.org/doc/libs/1_77_0/libs/spirit/doc/html/index.html . You will have more fun at it and learn more useful skills. – alfC Sep 21 '21 at 15:20

1 Answers1

0

Well, there is no way to use a switch-case statement on strings, as far as I know. I believe you can find an answer here - Why the switch statement cannot be applied on strings?

You could also use a map, and map the string values to integer values. That would look like this -

std::map<std::string, int> cmds = {
    {"cd", 1},
    {"ls", 2}
};
switch (map[cmd]){
    ...
}

where cmd is the input command, and cmds contains all the commands.

alonkh2
  • 533
  • 2
  • 11
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 21 '21 at 15:56
  • visual studio gives an error complaining that the expression should have a constant value and that there's a missing argument list for the class model "map". – retro Nov 02 '21 at 08:17
  • nevermind, i used switch (cmds[cmd]) { ... } instead of switch (map[cmd]) { ... } lol – retro Nov 02 '21 at 08:35