Parsing Commands

Apr 20, 2013 at 8:38pm
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 Apr 20, 2013 at 8:38pm
Apr 20, 2013 at 8:44pm
man getopt
Apr 20, 2013 at 8:53pm
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 Apr 20, 2013 at 8:54pm
Apr 20, 2013 at 9:12pm
@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.
Apr 20, 2013 at 9:26pm
You never initialize args or argv2.

¿how are you using it?
Last edited on Apr 20, 2013 at 9:27pm
Apr 20, 2013 at 9:30pm
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;
Apr 20, 2013 at 9:33pm
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)
Apr 20, 2013 at 9:36pm
So all I do is change it to int args = 0; and char * argv2[5] = {NULL, NULL, NULL, NULL, NULL};?
Apr 20, 2013 at 9:40pm
¿and what would that do?
You'll parse nothing.
Apr 20, 2013 at 10:01pm
So how do I parse like I want to do like stated in the OP?
Apr 20, 2013 at 11:48pm
./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 Apr 20, 2013 at 11:48pm
Apr 21, 2013 at 1:40am
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?
Apr 21, 2013 at 2:27pm
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.