Desperately need help for project

Pages: 123
Does the last param passed to ReadCommands() still make sense to you if you reread the declaration of this function?
Yep, that was a copy-paste mistake.
One that is easily found if you just pay attention.

The code to perform the actions is your repeatcmd function. That should have been obvious.

Last edited on
So, during the recursive function i will get first line of curcmd

Forward 10 Left 9

I will detect what the first command is by using compare
but to extract all the numbers after before the next command is a bit tricky i was thinking last night, that maybe i could compare the ascii values.

if ascii value is higher than 47 but less than 58 than it is a number a send to draw function. i think i might have to loop this until char is equal to space or i could just convert all chars after the command to int and stop once it reaches a space so something like this.

for(i=o;strcurcmd.size();i++)
if(strcurcmd.compare(i,7,'forward')==0)
for(k=8; strcurcmd.at(k)!=' ';k++)
amt=+int(strcurcmd.at(k)); //convert to int

also i had the problem of trying to seperate

REPEAT 10[ LEFT 90 REPEAT 80[ FORWARD 5 LEFT 1]]

TO

curcmd = LEFT 90
FORWARD 5 LEFT 1

i see a patter which i can use but don't know how to implement
that the last command will be between '[' and ']' and the previous commands are between [ and REPEAT.

how do i loop through it using these as delimiters to store all commands in string and place that in vector.

i tried your readcommand() i don't know why it still gives error, even when passed from the opening file.

thanks
here is my attempt on breaking one string into curcmd vector just a start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for(unsigned int i=0; i<cmd.size();i++)
    {
        cout<<"Checking character"<<i<<"="<<cmd.at(i)<<endl;
        if(cmd.compare(0,6,"REPEAT")==0)
        {
            while(cmd.at(i)!='[')
            {
                rep.append(cmd.at(i));   //append all the numbers after repeat until it finds '[' char.
                k=int(rep);   //convert to int
                i++;
            }
            cout <<"First repeat done"<<k<<"number of times"<<endl;
            for(unsigned int l=i;((cmd.compare(l,6,"REPEAT")!=0)||(cmd.at(l)!=']'));l++)
            {
                temp.append(cmd.at(l));  //add all instructions until a repeat is found or closing bracket.
            }
            cout<<"Let's see what instructions it found for first repeat"<<temp<<endl;
        }
    }


this gives me error
|43|error: invalid conversion from 'char' to 'const char*'|
|43|error: initializing argument 1 of 'std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::append(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'|
|44|error: invalid cast from type 'std::string' to type 'int'|
|50|error: invalid conversion from 'char' to 'const char*'|
|50|error: initializing argument 1 of 'std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::append(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'|

thanks
Last edited on
I you want me to correct the problem with ReadCommands you have to show me your code and what the compiler tells you.

As for analysing the content of the line, you should not try to do it all by yourself. If you use stringstreams you'll be able to easily identify the commands and their associated values.
Even if you can not make it work, try to understand how ReadCommands works.
I did post my code and the error i am getting, which is located on the last post of the first page.

i don't understand read command because you have a vector in a vector and Command inside and not string.

i also tried to write my version of read command shown above.

which brings error, i want your help to why i am getting above error.

i read the stringstream, but don't know how i can use it to get the string and number.

thanks
so i was looking at your code and the ones that created error i removed it and go the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    replace(cmd.begin(), cmd.end(), '[', ' ');
    replace(cmd.begin(), cmd.end(), ']', ' ');

    stringstream ss(cmd);
    string Action;
    vector <int> nRepeats;
    vector <string> CommandList;
    int value;
    string Command(Action,value);

    while( ss >> Action >> value )
    {
        if( string("REPEAT") == Action )
        {
            cout << "\nNew row : (REPEAT," << value << ") ";
            nRepeats.push_back(value);
        }
        else
        {
            std::cout << '(' << Action << ',' << value << ')' << ' ';
        }
    }


which produces for test string
string cmd("REPEAT 10 [FORWARD 9 REPEAT 20[ LEFT 8 FORWARD 50]]");

output
New row: (Repeat,10) (FORWARD,9)
New row: (Repeat,20) (LEFT,8) (FORWARD,50)

the repeat vector contains the numbers

i tried the following

1
2
3
4
for(unsigned k=0;k<sizeof(curcmd);k++)
    {
        cout<<nRepeats.at(k)<<endl;
    }


which shows the numbers but then gives a runtime error.

how do i store the action and the value to a curcmd vector.
e.g. if i wanted to obtain the action of the first element it would be forward and if i wanted the value element i would get 9.
i know you did this with the vector< vector<Command>> but it didn't work as i gave the error in last post of first page.
i will show you again the error when i do the following 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
stringstream ss(cmd);
    string Action;
    vector <int> nRepeats;
    vector <string> CommandList;
    int value;
    string Command;
    CommandList.clear();
    nRepeats.clear();

    while( ss >> Action >> value )
    {
        if( string("REPEAT") == Action )
        {
            cout << "\nNew row : (REPEAT," << value << ") ";
            nRepeats.push_back(value);
            CommandList.push_back( vector<Command> () );
        }
        else
        {
            cout << '(' << Action << ',' << value << ')' << ' ';
            CommandList.back().push_back( Command(Action,value) );
        }
    }
    return 0;


i get the error


regarding CommandList.push_back( std::vector<Command> () );

error:'Command' cannot appear in a constant expression
error: template argument 1 is invalid
error: template argument 2 is invalid
no match for call to '(std::string) (std::string&, int&)'

thanks it's looking much better.

so would the command list be a vector of string which contain actionvalue space actionvalue , etc.
Last edited on
to include commands i decided to join the action and value store in variable called Commad

then i could say CommandList.push_back(Command);

which the following is the code:
1
2
3
4
cout << '(' << Action << ',' << value << ')' << ' ';
            act<<Action<<' '<<value;
            Command=act.str();
            CommandList.push_back(Command);

Row 0 should be FORWARD 9
Row 1 should be LEFT 8 FORWARD 50

but looking in CommandList[1]

cout<<CommandList[1]<<endl;
gives

FORWARD 9LEFT 8

instead of

LEFT 8FORWARD 50

thanks
Last edited on
I did post my code and the error i am getting, which is located on the last post of the first page.
andywestken and me told you where the mistake was and how to correct it:
ReadCommands( currentline, CommandList, nRepeats);

i don't understand read command because you have a vector in a vector and Command inside and not string.
My "Command" structure simply contains the string indicating the action to perform and the value associated with it. It's easier to manipulate that way.
You wanted to store it in an array of rows. Since the rows are also arrays, it's an array of array. I implemented it using vectors because it's simpler.


i tried the following
1
2
3
4
for(unsigned k=0;k<sizeof(curcmd);k++)
    {
        cout<<nRepeats.at(k)<<endl;
    }


which shows the numbers but then gives a runtime error.

It should be
1
2
3
4
for(unsigned k=0;k<nRepeats.size();k++)
{
    cout<<nRepeats.at(k)<<endl;
}




how do i store the action and the value to a curcmd vector.
e.g. if i wanted to obtain the action of the first element it would be forward and if i wanted the value element i would get 9.
i know you did this with the vector< vector<Command>> but it didn't work as i gave the error in last post of first page.

I just gave you the correction.



Row 0 should be FORWARD 9
Row 1 should be LEFT 8 FORWARD 50

but looking in CommandList[1]

cout<<CommandList[1]<<endl;
gives

FORWARD 9LEFT 8

instead of

LEFT 8FORWARD 50

You need to clear to content of act by doing something like act.str(std::string()); before doing act<<Action<<' '<<value;
The result will not be what you want because this code creates a new row for each command.
For what you want the code should be more like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
while( ss >> Action >> value )
{
    if( string("REPEAT") == Action )
    {
        cout << "\nNew row : (REPEAT," << value << ") ";
        nRepeats.push_back(value);
        CommandList.push_back( std::string () );
    }
    else
    {
        cout << '(' << Action << ',' << value << ')' << ' ';
        act.str( std::string() );
        act << Action << ' ' << value << ' ';
        CommandList.back() += act.str();
    }
}


Last edited on
I did post my code and the error i am getting, which is located on the last post of the first page.
andywestken and me told you where the mistake was and how to correct it:
ReadCommands( currentline, CommandList, nRepeats);


I just figured that out, when looking at the function definition and in the call you put 2 commandList.


My "Command" structure simply contains the string indicating the action to perform and the value associated with it. It's easier to manipulate that way.
You wanted to store it in an array of rows. Since the rows are also arrays, it's an array of array. I implemented it using vectors because it's simpler.


When looking at the call when this is made in the open file area

you also have the same thing std::vector< std::vector<Command> >
but i don't see where the command is declared and initialized.
yes i did want array and yes vectors are nice.

i was thinking of using a struct, which contains both string and int and push that into a vector.

struct Instruct
{
int Num;
string Comnd;
};

Instruct Command;

Command.Comnd=Action;
Command.Num=value;

CommandList.push_back(Command)


would i be able to access the int and string from the vector.

i'm probably thinking too much into this, according to your idea, which i have become fond of, i could have a vector, which contains different vectors for different repeat commands instead of strings and each element in the inside vector can i access the int value and string value by using struct or easier use stringstream.

so changing my older version. would it look like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

vector<string> Command;
vector<Command> CommandList;

while( ss >> Action >> value )
{
    if( string("REPEAT") == Action )
    {
        cout << "\nNew row : (REPEAT," << value << ") ";
        nRepeats.push_back(value);
        Command.push_back( std::string () );
    }
    else
    {
        cout << '(' << Action << ',' << value << ')' << ' ';
        act.str( std::string() );
        act << Action << ' ' << value << ' ';
        Command.push_back(act.str());
    }
    CommandList.Push_Back(Command);
}


I want it to fill first vector with all the commands of each repeat then push that vector into the vector and start with a new vector for other commands in the next repeat function.


would this work

1
2
3
4
for(unsigned k=0;k<nRepeats.size();k++)
{
    cout<<nRepeats.at(k)<<endl;
}


so this would loop through the vector vertically and not horizontally through each character.

thanks
Last edited on
My "Command" structure is exactly like your "Instruct" structure.

Your code is pretty close to what you want:
- in the code you've written, you create a new row for each command. You need to create a new row only when there's a REPEAT command. So CommandList.Push_Back(Command); must be inside the if( string("REPEAT") == Action ).
- Command.push_back( std::string () ); appends an empty string. I think what you really want is to empty the vector. It's done with Command.clear();

The corrected code would be this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vector<string> Command;
vector< vector<string> > CommandList;

while( ss >> Action >> value )
{
    if( string("REPEAT") == Action )
    {
        cout << "\nNew row : (REPEAT," << value << ") ";
        nRepeats.push_back(value);
        CommandList.push_Back(Command);
        Command.clear();
    }
    else
    {
        cout << '(' << Action << ',' << value << ')' << ' ';
        act.str( std::string() );
        act << Action << ' ' << value << ' ';
        Command.push_back(act.str());
    }
}


Unfortunately this code has a bug. When the first REPEAT command arrives, the"Command" vector is empty, so it inserts an empty row.
When it reaches the last command, since there is no REPEAT command coming after, the "Command" vector is not inserted into "CommandList".
So we need to modify the code to remove the first empty row and add the missing last row:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
vector<string> Command;
vector< vector<string> > CommandList;

while( ss >> Action >> value )
{
    if( string("REPEAT") == Action )
    {
        cout << "\nNew row : (REPEAT," << value << ") ";
        nRepeats.push_back(value);
        CommandList.Push_Back(Command);
        Command.clear();
    }
    else
    {
        cout << '(' << Action << ',' << value << ')' << ' ';
        act.str( std::string() );
        act << Action << ' ' << value << ' ';
        Command.push_back(act.str());
    }
}
CommandList.erase( CommandList.begin() ); // erase empty first row
CommandList.push_back( Command ); // insert the missing last row 


Personnally I find it ugly. It's possible to avoid this kind of hack if instead of waiting to have the full row before inserting into CommandList, you insert the elements directly into CommandList as they come.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
vector<string> Command;
vector< vector<string> > CommandList;

while( ss >> Action >> value )
{
    if( string("REPEAT") == Action )
    {
        cout << "\nNew row : (REPEAT," << value << ") ";
        nRepeats.push_back(value);
        CommandList.Push_Back( vector<string> () ); // create a new empty row
    }
    else
    {
        cout << '(' << Action << ',' << value << ')' << ' ';
        act.str( std::string() );
        act << Action << ' ' << value << ' ';
        CommandList.back().push_back(act.str()); // add the string directly in the last row of CommandList
    }
}


This code should do exactly what you want, with strings.


As you know, I prefer using a structure because I find it's easier to use afterwards.
The code is almost the same, except that instead of creating a string that contains the data, I create a structure that contains the data.
Here's an example that uses your "Instruct" structure:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vector<Instruct> Command;
vector< vector<Instruct> > CommandList;

while( ss >> Action >> value )
{
    if( string("REPEAT") == Action )
    {
        cout << "\nNew row : (REPEAT," << value << ") ";
        nRepeats.push_back(value);
        CommandList.Push_Back( vector<Instruct> () );
    }
    else
    {
        cout << '(' << Action << ',' << value << ')' << ' ';
        
        // create the Instruct structure that contains the data
        Instruct newInstruction;
        newInstruction.Comnd = Action;
        newInstruction.Num = value;
        
        // push it into the array
        CommandList.back().push_back( newInstruction );
    }
}
vector<Instruct> Command;


so i don't have to declare a variable with the struct i.e. Instruct Command i can just place straight into vector, oh yeah like a string.

so would the vector contain a string and an int. which is a multi data type variable. that's the think i like about structures.

ok, now will have to get to work.

Oh, i nearly forgot.

When it comes to drawing my main int

opens window function, which inside calls a draw function

void draw(void)
{

}

int main(int numargs, char* psz[])
{
window(some arguments)
}

so the draw function would have to be performed in the draw void function.
how would i make a function happen within draw without it being in draw.

e.g. if Action == Left

Rotate(Value); this is will draw it only if it is in draw.

i was thinking of instead of performing draw function, set up a class which takes a vector, which would be pushing all the command that has to be performed to the back and then a global object of the class would have to be declared then in draw you can loop through the contents of the vector.

what do you think.

i was thinking of instead of performing draw function, set up a class which takes a vector, which would be pushing all the command that has to be performed to the back and then a global object of the class would have to be declared then in draw you can loop through the contents of the vector.

what do you think.


If your draw() function does not take any parameter, you have to use a global variable.
Your idea sounds good.
as i type the final implementation of the code so many errors here and there

i have 2 cpp file and one header files

i want to store all the functions in the second cpp file and the class in the first header file but i keep getting errors

redefinition of class' '

or

can not declare 'public' or 'function' without type

or multiple function.

only when empty the second cpp file and put all the functions and class in the header file and just delete the second cpp file not working

regarding the code you posted

1
2
3
4
5
6
7
8
9
10
11
12
13
CommandList.Push_Back( vector<Instruct> () );
    }
    else
    {
        cout << '(' << Action << ',' << value << ')' << ' ';
        
        // create the Instruct structure that contains the data
        Instruct newInstruction;
        newInstruction.Comnd = Action;
        newInstruction.Num = value;
        
        // push it into the array
        CommandList.back().push_back( newInstruction );


first line pushs empty vector or creates a new line
but the second commandlist.back().push_back(newinstruction)

isn't this just storing all the commands in a vector instead of storing all the commands for a repeat in a vector and then push that vector into another vector.

Yes and no.
It's the same principle, but doing it this way avoid some problems.
I explained the difference in this post: http://cplusplus.com/forum/beginner/85841/2/#msg468491 (the first 3 code examples).
hey

regarding the bug of when the vector adds an empty elements

what if i add a if statement to check if command vector is not empty then push back else don't push back.

and for the adding last item in the we can just add push back after the loop.

or i can just add string on to vectors and then using stringstream to separate each one to send to the right instruction function.

this is what i have got for my vector in vector function

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
vector< vector<Instruct> > processvector(vector<string> comds, vector<int> nRepeats)
{
vector<Instruct> Command;
vector< vector<Instruct> > CommandList;

    while( ss >> Action >> value )
    {
        if( string("REPEAT") == Action )
        {
            cout << "\nNew row : (REPEAT," << value << ") ";
            nRepeats.push_back(value);
            if(Command.empty()!=0)
            {
                CommandList.Push_Back(Command);
                Command.clear();
            }
        }
        else
        {
            cout << '(' << Action << ',' << value << ')' << ' ';

            // create the Instruct structure that contains the data
            Instruct newInstruction;
            newInstruction.Comnd = Action;
            newInstruction.Num = value;

            // push it into the array
            Command.push_back( newInstruction );
        }
    }
    CommandList.push_back(Command);
    return CommandList;


will this be able to create a vector which is filled with vectors

since i want to return nRepeats and the new nested vector in a vector i would need to use pointers

how do i change it would it look like this

function head

vector< vector<Instruct> > processvector(vector<string> comds, vector<int>* nRepeats)
{

call function

Commandlist=processvector(CommandList,Repeats&)
Last edited on
if i have a vector with a struct inside it how do i access individual elements.

vector<instruct> command

for(unsigned i=0;i<command.size();i++)
{
a = command.at(i);
val=a.Num;
act=a.Comnd;
performleft(act,val);
}
how would you access each vector in a vector and then access each element of the struct from the vector; i was thinking something like below:

vector< vector<instruct> > commandlist;
vector<instruct> command;
instruct comd;
string act;
float val; ///because some actions take decimal numbers i.e. forward 0.5

for(i=0;i<commandlist.size();i++)
{
command = commandllist[i];
for (j=0; j<command.size(); j++)
{
comd = command[j];
comd.Comnd = act;
comd.Num = val;
performdraw(act,val);
}
}

would this work?

thanks
Pages: 123