Parsing Commands

Is there a better way to parse words in a string to pass as "commands for the console"? I'm making a customized CLI, and have a whole bunch of if statements like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
if (line[x] == 'a') {

                        }
                        if (line[x] == 'b') {

                        } // BELOW IS WHAT I WANT TO ELIMINATE: PARSING CHAR BY CHAR
                        if (line[x] == 'c') {
                            if (line[x+1] == 'o') {
                                if (line[x+2] == 'l') {
                                    if (line[x+3] == 'o') {
                                        if (line[x+4] == 'r') {
                                            SetColor(10);
                                        }
                                    }
                                }
                            }
                        }
                        /*
                        if (line[x] == 'd') {

                        }
                        if (line[x] == 'e') {

                        }
                        if (line[x] == 'f') {

                        }
                        if (line[x] == 'g') {

                        }
                        if (line[x] == 'h') {

                        }
                        if (line[x] == 'i') {

                        }
                        if (line[x] == 'j') {

                        }
                        if (line[x] == 'k') {

                        }
                        if (line[x] == 'l') {

                        }
                        if (line[x] == 'm') {

                        }
                        if (line[x] == 'n') {

                        }
                        if (line[x] == 'o') {

                        }
                        if (line[x] == 'p') {

                        }
                        if (line[x] == 'q') {

                        }
                        if (line[x] == 'r') {

                        }
                        if (line[x] == 's') {

                        }
                        if (line[x] == 't') {

                        }
                        if (line[x] == 'u') {

                        }
                        if (line[x] == 'v') {

                        }
                        if (line[x] == 'w') {

                        }
                        if (line[x] == 'x') {

                        }
                        if (line[x] == 'y') {

                        }
                        if (line[x] == 'z') {

                        } */


Is there any way to parse a command (below) to make the console set the color to lime green? (<-- I know how to do that, but how do I parse the command with switches/parameters?)

color -lg
Last edited on
man getopt
well for one you could input a string by using getline(cin, stringname); and that would get rid of the having to if 'c' if 'o' ect..for color but the color code eg 'l'g' might be a bit more difficult for the switch since switches are in this formart switch(char), switch(int) and not switch(string) but you could convert the letters to numbers then change color based on that.
and then you could do soemthing like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <stdlib.h>
using namespace std;

int main()
{
string input, error, colorCodeStr;
unsigned int colorCode;
do {
     cout << "Which color would you like?: " << flush;
     getline(cin, input);
     for(unsigned int i = 0; i<input.size(); i++) if(isdigit(input[i])) error = "true"; else error = "false;
} while(error == "true");
switch(input[0]){
case 'l': colorcodeStr[0] = '0'; break;
}
switch(input[1]){
case 'g': colorCodeStr[1] = '0'; break;
}
colorCode = atoi(colorCodeStr.c_str());
switch(colorCode){
case 00: setColor(10); break;
}
} 

didn't tesat the code its just an thought that you could try.
Last edited on
@ne555 - I've looked at the examples on GNU.org, and apparently I can't modify it to fit my needs:

1
2
3
4
5
6
7
8
9
while ((c = getopt (args, argv2, "-:")) != -1) {
                                switch (c) {
                                    case '-':
                                    col = optarg;
                                    cout << col;
                                    getchar();
                                    break;
                                }
                            }


I want it to output "col", but it doesn't. Ideas? Full code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
#include <algorithm>
#include <unistd.h>
#include <string>
#include <windows.h>
#include <fstream>
#include <vector>

using namespace std;

void SetColor(unsigned short color) {
    HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hcon, color);
}

BOOL WINAPI SetConsoleIcon(HICON hIcon) {
    typedef BOOL (WINAPI *PSetConsoleIcon)(HICON);
	static PSetConsoleIcon pSetConsoleIcon = NULL;
	if(pSetConsoleIcon == NULL)
		pSetConsoleIcon = (PSetConsoleIcon)GetProcAddress(GetModuleHandle(("kernel32")), "SetConsoleIcon");
	if(pSetConsoleIcon == NULL)
		return FALSE;
	return pSetConsoleIcon(hIcon);
}

int main(int argc, char* argv[])
{
    SetConsoleTitle("Cmd2");
    HICON hIcon = LoadIcon(GetModuleHandle(0),"MAINICON");
   	SetConsoleIcon(hIcon);

    if (argc<2) {
        cerr << "Cmd2\n\n";
        getchar();
    } else {
        int args;
        char * argv2[5];
        char * col = NULL;
        string line;
        int c;
        string cmd;

        ifstream file;
        file.open(argv[1]); // Args start a 0, then go up by 1. argv[0] is the Program path.
        if(!file.is_open()) {
            file.close();
            cout << "Error opening file.";
            getchar();
        } else {
            while(!file.eof()) { // While the file isn't ended
                getline(file, line); // get the command's whole line
                if (!line.empty()) { // If the line isn't empty...
                    for (unsigned int i = 0; i < line.length(); i++) { // Tranform string to lowercase
                        tolower(line[i]);
                    }
                    for (unsigned int x = 0; x < line.length(); x++) {
                        if (line[x] != ' ') {
                            cmd += line[x];
                        } else {
                            while ((c = getopt (args, argv2, "-:")) != -1) {
                                switch (c) {
                                    case '-':
                                    col = optarg;
                                    cout << col;
                                    getchar();
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        file.close();
    }
    cout << "Command Completed Successfully.";
    getchar();
}


@giblit - Seems like it would work, but I think I'll go with ne555's way.
You never initialize args or argv2.

¿how are you using it?
Last edited on
Yes I do. Check the code again:

1
2
3
4
5
6
7
} else {
        int args;
        char * argv2[5];
        char * col = NULL;
        string line;
        int c;
        string cmd;
int args; is not initialization ¿what value does `args' hold?

By the way,
$ ./program.bin -col
will take `c' `o' and `l' as options (as long as no one expects a value)
So all I do is change it to int args = 0; and char * argv2[5] = {NULL, NULL, NULL, NULL, NULL};?
¿and what would that do?
You'll parse nothing.
So how do I parse like I want to do like stated in the OP?
./program.bin -b red -f green
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main(int argc, char **argv){
	int opt;
	std::string optstring;
	while( (opt=getopt(argc, argv, "b:f:")) != -1 ){
		switch(opt){
		case 'b':
			colour = optstring; //red
			break;
		case 'f':
			colour = optstring; //green
			break;
		default:
			std::cerr << "unknow option " << opt;
		}
	}
}
Also take a look at `getopt_long'
Last edited on
That seems to be for the main arguments. The file that I'm trying to parse has color -c 10 in it. How do I parse such a thing?
I've found a way to do this right, but can't seem to correctly parse the commands. Here's the full code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <string>
#include <windows.h>
#include <fstream>
#include <vector>
#include <sstream>

using namespace std;

void SetColor(unsigned short color) {
    HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hcon, color);
}

BOOL WINAPI SetConsoleIcon(HICON hIcon) {
    typedef BOOL (WINAPI *PSetConsoleIcon)(HICON);
	static PSetConsoleIcon pSetConsoleIcon = NULL;
	if(pSetConsoleIcon == NULL)
		pSetConsoleIcon = (PSetConsoleIcon)GetProcAddress(GetModuleHandle(("kernel32")), "SetConsoleIcon");
	if(pSetConsoleIcon == NULL)
		return FALSE;
	return pSetConsoleIcon(hIcon);
}

int main(int argc, char* argv[])
{
    SetConsoleTitle("Cmd2");
    HICON hIcon = LoadIcon(GetModuleHandle(0),"MAINICON");
   	SetConsoleIcon(hIcon);

    if (argc<2) {
        cerr << "Cmd2";
    } else {

        string line;
        string cmd;
        string params;
        string token;

        unsigned int i;
        unsigned int x = 0;

        ifstream file;
        file.open(argv[1]); // Args start a 0, then go up by 1. argv[0] is the Program path.
        if(!file.is_open()) {
            file.close();
            cout << "Error opening file.";
        } else {
            int words = 0;
            string word;
            while (file >> word) {
                words++;
            }
            string tokens[words];
            while(!file.eof()) { // While the file isn't ended
                getline(file, line); // get the command's whole line
                if (!line.empty()) { // If the line isn't empty...
                    for (i = 0; i < line.length(); i++) { // Tranform string to lowercase
                        tolower(line.at(i));
                    }
                    stringstream ss(line);
                    while (getline(ss, token, ' ')) {
                        tokens[x] = token;
                        x++;
                    }
                }
            }

            unsigned int y = 0;

            while(y <= x) {
                if (tokens[y] == "color") {
                    if (tokens[y+1] == "-lime") {
                        SetColor(10);
                    }
                }
                y++;
            }

            cout << "Command Completed Successfully.\n";
        }
        file.close();
    }
    getchar();
}
Topic archived. No new replies allowed.