Weird output... not sure how to describe. Long code, be warned.

For some reason, when I input a greeting, such as "hi" to my program the first time, it prints a greeting back (like it's supposed to). Every time after that, however, if I input a greeting, it prints a random number of them as well. I really do not know why at all. If anyone has any ideas, I'd appreciate it.

Thanks in advance:)

Code: (i know it's long)
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <vector>
#include <string>
#include <ctime>
#include <windows.h>

using namespace std;

//global vars
int a, b, x, y, z, debug, TheTime;
vector<string> parsed;
vector<string> greetings;
vector<string> commands;
vector<string> objects;
vector<string> simplified; //after parsing of the parsed vector for commands, objects, etc
vector<int> simplifytypes; //type of each thing in simplified, 1=greeting 2=command 3=object
string input;
LPCSTR ShellCommand;
LPCSTR ShellObject;


//Function templates
void InitVectors();
void ParseInput(string toparse);
void Tokenize(string input);
void Greet();
string SStringSpanExcluding(string str);



int main()
{
    b=1;

    do{
    srand(time(NULL));

	InitVectors();

	getline(cin, input);
	ParseInput(input);
    }while(b==1);
	return 0;

}



void InitVectors()
{
	greetings.push_back("hello");
	greetings.push_back("Hello");
	greetings.push_back("hi");
	greetings.push_back("Hi");

	commands.push_back("edit");
	commands.push_back("explore");
	commands.push_back("find");
	commands.push_back("open");
	commands.push_back("print");

	objects.push_back("yourself");
	objects.push_back("Yourself");
	objects.push_back("Word");
	objects.push_back("word");
}



void ParseInput(string toparse)
{
    toparse=SStringSpanExcluding(toparse);
    //Tokenize
    Tokenize(toparse);

    //pick a token
    for(int spot=0; spot<parsed.size(); spot++)
    {
        //Check token
        if(parsed[spot]!="end")
        {
            //Check for debug mode
            //debug=0;
            /*for(int a=0; a<parsed.size(); a++)
            {
                if(parsed[a]=="debug", "Debug")
                {
                    cout << "Debug mode engaged.\n";
                    //debug=1;
                    break;
                }
            }*/

            //Check for greetings
            //cout << "checking\n"; //debug
            for(int x=0; x<greetings.size(); x++)
            {
                if(parsed[spot]==greetings[x])
                {
                    /*if(debug==1)
                    {
                        cout << "Greeting found!\n" << endl;
                    }*/
                    Greet();
                }
            }
            //Check for commands
            for(int y=0; y<commands.size(); y++)
            {
                if(parsed[spot]==commands[y])
                {
                    /*if(debug==1)
                    {
                        cout << "Command found! (" << parsed[spot] << ")" << endl;
                    }*/
                    //Translate command into all lowercase, so that it can be substituted variably into a ShellExecute() command
                    switch(y) //send command to be executed
                    {
                    case 1:
                        ShellCommand="edit";
                        break;
                    case 2:
                        ShellCommand="explore";
                        break;
                    case 3:
                        ShellCommand="find";
                        break;
                    case 4:
                        ShellCommand="open";
                        break;
                    case 5:
                        ShellCommand="print";
                        break;
                    }//end of switch

                }//end of if statement
            }

            //Check for objects
            for(int z=0; z<objects.size(); z++)
            {
                if(parsed[spot]==objects[z])
                {
                    /*if(debug==1)
                    {
                        //Do stuff with the object
                        cout << "Object found! (" << parsed[spot] << ")" << endl;
                    }*/

                    switch(z)
                    {
                        case 1:
                        ShellObject="Jarvis.exe";
                        break;
                        case 2:
                        ShellObject="Jarvis.exe";
                        case 3:
                        ShellObject="Word.exe";
                        break;
                        case 4:
                        ShellObject="Word.exe";
                        break;
                    }
                }
            }
        //end of while loop
        }
        //end of do loop
        else{cout << "end of string";}
    }
}



void Greet()
{
    random_shuffle(greetings.begin(), greetings.end());
    cout << greetings[0] << '\n';

}



void DoCommand() //Cannot complete yet, as I'll need the full file path of the programs I'm running.
{
    ShellExecute(NULL, ShellCommand, ShellObject, NULL, NULL, SW_SHOWDEFAULT);
}



void Tokenize(string input)
{
    //cout << "Tokenizing" << '\n';
    //Vector is parsed;
    char * cstr, *p;
    cstr = new char [input.size()+1];
    //C String equivalent of input
    strcpy (cstr, input.c_str());
    //Tokenize
    p=strtok (cstr," ");
    while (p!=NULL)
    {
        parsed.push_back(p);
        p=strtok(NULL," ");
    }
    //C String is no longer necessary
    delete[] cstr;
}




string SStringSpanExcluding(string str)
{
    //cout << "Cleaning input" << '\n';
    //str.erase( remove( str.begin(), str.end(), ' ' ), str.end() );
    str.erase( remove( str.begin(), str.end(), ',' ), str.end() );
    str.erase( remove( str.begin(), str.end(), '.' ), str.end() );
    str.erase( remove( str.begin(), str.end(), '!' ), str.end() );
    str.erase( remove( str.begin(), str.end(), ';' ), str.end() );
    return str;
}


Here's psuedo code of what's happening to cause just the problem:
InitVectors() pushes back some greetings into vector greetings->
Main loop runs->
ParseInput is called->
Input goes through SStringSpanExcluding, and Tokenize successfully->
Input is parsed->
Greeting is detected->
Greet() function runs->
Return to main loop<-
Last edited on
Every time after that, however, if I input a greeting, it prints a random number of them as well.
Hehe, well not a random number. It's wat I call 'the global variable effect'.

You add all tokens to the global variable parsed, but you never remove it. So on line 81 you deal with all tokens ever parsed.

By the way: better use stringstream for the parsing:
http://www.cplusplus.com/reference/iostream/stringstream/
I don't understand. On line 81, how does this affect the output of my function Greet()?


EDIT: Also, looked into stringstream. I wrote the following function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16


    void TokenizeStd(std::string Thing)
    {
        std::stringstream s(Thing);
        std::string token;
        while ( s >> token )
        {
                std::cout << token <<'\n'; //Debug
                parsed.push_back(token);
        }
            // Clear the stream state
            s.clear();
            // Rewind the stream
            s.seekg ( 0, std::ios::beg );
    }


Which I think should be fine. The problem is, when I try to send (on line 78) the std::string toparse to this function, Code::Blocks tells me "TokenizeStd was not declared in this scope." I included <sstream> obviously, and changed line 78 so that it was calling the correct function. I don't know what the scope thing means.
Last edited on
Coder777 told you what's wrong. Line 81 is the loop where you process everything in parsed, and while the contents don't affect the output of your Greet() function, they do affect the number of times it is called.

Put the line parsed.clear(); in InitVectors() and see what happens.
On line 207 you push the parsed data to the global object, but you never remove it. If you want to keep the global variable you should clear() it at the beginning of Tokenize(). Or do what cire said.

By the way: all your global variables might have the problem of unwanted remaining data

Code::Blocks tells me "TokenizeStd was not declared in this scope."
When you use another name for the function you must declare it before it is used like you did with the other functions (line 27 to 31)
I understand, I think. I'll go play with it and see what happens. And that last bit (@coder777) now I feel really dumb. haha
Last edited on
Okay, so I put parsed.clear(); on a couple of different lines, to no avail. Using the original code as reference (since I used those functions anyway), I put it on line 54, 196, and 204. It still continues to cause the problem. I understand now what the problem is, I think (that when I send a greeting to parsed, it then saves it, and the next time I use a greeting it finds two greetings, and so responds in turn, or something along those lines).

EDIT: Corrected the problem by adding greetings.clear() at the end of Greet() will see about my other functions now.
Last edited on
clear() all your global vectors in InitVectors() and this particular problem will go away. Loads of global problems are waiting...
Yeah I can see that. I've just gone ahead and cleared them all in that function. Thanks for your help, all:)
You can easily avoid global variables 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
...

//global vars
...
// vector<string> parsed;
...

//Function templates
...
vector<string> Tokenize(string input);


void ParseInput(string toparse)
{
...
    //Tokenize
    vector<string> parsed =  Tokenize(toparse);
...
}

...

vector<string> Tokenize(string input)
{
   vector<string> parsed;

...

    return parsed;
}

...
Topic archived. No new replies allowed.