| asda333 (36) | |||
|
Hi I have to create this program, which reads commands from a text file and draws them. I have split them into stages. The problem is reading text from the text file. text file: FORWARD 10 LEFT 90 FORWARD 20 LEFT 90 FORWARD 5 LEFT 90 FORWARD 10 LEFT 90 FORWARD 5 i am trying to read each line and store it in an array of strings so it can be like this stringarray = FORWARD 10 LEFT 90 FORWARD 20 FORWARD 5 LEFT 90 ... i don't know how to use vectors in this situation. my code is
if i output cmd cout<<cmd<<endl; it will output FORWARD 5 and not FORWARD 10 LEFT 90 FORWARD 20 LEFT 90 FORWARD 5 LEFT 90 FORWARD 10 LEFT 90 FORWARD 5 thanks | |||
|
Last edited on
|
|||
| andywestken (1950) | |
See the info + example on this page:vector::push_backhttp://www.cplusplus.com/reference/vector/vector/push_back/ and this one vector::operator[]http://www.cplusplus.com/reference/vector/vector/operator%5B%5D/ Andy PS Also see firedraco's article: "How to use tags" http://www.cplusplus.com/articles/z13hAqkS/ (you can go back and add tags to your opening post!) | |
|
|
|
| toum (169) | |||
|
getline erases the content of the string to replace it with the data from the file. You need to use a variable in which you accumulate what you read
| |||
|
|
|||
| asda333 (36) | |||
|
nice one toum, thanks. I understand what you mean and got it to work. i am new to getline function one big problem in my project is that example a command my program has to read might be something like this REPEAT 10[LEFT 90 REPEAT 20[FORWARD 5 REPEAT 10[LEFT 90 FORWARD 10]]] So for n number of repeat you need n number of nested loops, so i want to try and find a way to create a variable number of nested loops depending on how many repeat statements there are. i tried recursive function, but i just don't understand how they work. i was thinking something like the following, but when i go through it, it just falls apart.
and with the recursive i was thinking that it would perform the current command and the loop command, which increases the index to the next current command for the next repeat and when finished comes out does the previous current command and the loop until the loop of the previous one ends and finish, but my function does not do that. Also if i have a array of strings, which you helped with ofcourse alltext=Left 90 forward 10 forward 10 right 20 forward 5 left 10 can i split them up into arrays so alltext = [Left 90, forward 10] [forward 10, right 20] so alltext(0,0)=left 90 alltext(0,1)=forward 10 and so on. thanks guys for all your help | |||
|
Last edited on
|
|||
| toum (169) | |||||||
|
It's possible to split the strings into arrays. The way to do that depends on what you want to obtain. Regarding the repeats, you need to store separately the lines so repeating them will be easy. I'd suggest using a vector.
Generating the repeated command can be done using only loops. The idea is to start from the end. - create an empty string that will contain the repeated commands - loop from the last command to the first -- append current command to the beginning of your string -- concatenate your string with itself the required number of times Using your example REPEAT 10[LEFT 90 REPEAT 20[FORWARD 5 REPEAT 10[LEFT 90 FORWARD 10]]]: - First iteration, append third command "LEFT 90 FORWARD 10" to the string. Since it was empty now it contains "LEFT 90 FORWARD 10". - Concatenate the string 9 (10-1) times. It contains 10x"LEFT 90 FORWARD 10" - Second iteration, append second command "FORWARD 5". The string contains "FORWARD 5" + 10x"LEFT 90 FORWARD 10" - Concatenate. The string contains 20x("FORWARD 5" + 10x"LEFT 90 FORWARD 10") - Third iteration, append first command "LEFT 90". The string contains "LEFT 90" + 20x("FORWARD 5" + 10x"LEFT 90 FORWARD 10"). - Concatenate. The string contains 10x("LEFT 90" + 20x("FORWARD 5" + 10x"LEFT 90 FORWARD 10")) The code would be something like that:
I voluntarily used function calls so that you can understand the big steps and not focus on pointless implementation details. In your case, these functions could be written
| |||||||
|
|
|||||||
| asda333 (36) | |
|
But all this has done is create a string on what to loop and how many times. but how would you convert that to in this case 3 nested loops. change 10x("LEFT 90" + 20x("FORWARD 5" + 10x"LEFT 90 FORWARD 10")) to for i=0;i<10 left 90 for(j=0;j<20 forward 5 for(k=0;k<10 left 90 forward 10 regarding the array. i want to split first element of vector from REPEAT 10[ LEFT 90 REPEAT 5[ LEFT 10 FORWARD 9] to {REPEAT 10, LEFT 90, REPEAT 5, LEFT 10, FORWARD 9} the comma represent end of each section of first element. or i was thinking maybe just store the number part in to a variable called the commands REPEAT = [10] [5 ] LEFT = [90 ] [10 ] and so on. but there has to be a more efficient way to create a variable nested for loop function. maybe a class, i don't know. | |
|
|
|
| toum (169) | |||
|
The code I wrote generates the string recursively. If you do not want to store everything before performing the actions, I think this might work:
As for the rest, I have 1 question: when the command is "REPEAT", does it always apply to everything that comes after it ? For example, could you have REPEAT 10[ LEFT 90] REPEAT 5[ LEFT 10 FORWARD 9] ? | |||
|
|
|||
| asda333 (36) | |
|
Yes with the repeat function it has to repeat every command that comes after it including repeat so REPEAT 20[LEFT 90 REPEAT 10[FORWARD 5 LEFT 1]] THE FIRST REPEAT LEFT 90 REPEAT 10[FORWARD 5 LEFT 1] SECOND REPEAT FORWARD 5 LEFT 1 above implementation would be for(i=0;i<20;i++) { left 90 for(j=0;j<10;j++) { forward 5 left 1 } } | |
|
|
|
| asda333 (36) | |||
|
Also now that we have a vector of commands REPEAT 10[ LEFT 90 REPEAT 5[ FORWARD 10]] LEFT 90 FORWARD 10 i want to take each line store in a new vector called curcommand split it into curcommand = left 90 forward 10 repeat = 10 10 my problem is detecting the repeats and acquring the following number after repeat into repeat variable i tried the following
| |||
|
|
|||
| toum (169) | |||||||||
|
I think you should not try to parse the strings by yourself. It can be pretty complicated, especially for a beginner. It's much simpler to use what already exists. My first advice would be to use a structure to store your commands:
Since the REPEAT command applies to everything that follows, if we can have an array of Command structures that describes your commands, it becomes easy to write a recursive function that will perform the actions in the desired order:
Now, what you need to do is extract the commands from the string you read from the file. It would be easy if those brackets were not there. But since the REPEAT command applies to everything that comes after it, those brackets are in fact useless. So let's erase them from the string. Getting the commands is now easy:
Your code that reads from the file can then be rewritten like this:
| |||||||||
|
Last edited on
|
|||||||||
| asda333 (36) | |
|
Would it make any easier for you if were to use classes and use polymorphism. Class Forward Class Left Class Right which is inherited from derived class Class commands float amount; | |
|
|
|
| asda333 (36) | |
|
Command below produces error std::stringstream ss(line); variable std:stringstream ss has initializer but incomplete type. | |
|
|
|
| asda333 (36) | |
|
I changed the struct command to class like below. so i can include polymorphism behaviour. but i don't understand how do i make one class inherit from another class e.g. class Command { Private: string Action; int Value; Public: Command(const string& initAction, const int& initValue): Action(initAction), Value(initValue) {;} }; note: i don't understand why you have : after the above function then action and value. would i inherit by doing the following class Forward { Protected or Private: Command fwd; Public: forwd(float amount) { glmov(amount,0,0,1); %or whatever the function maybe to draw forward etc } }; same with the other commands except for Repeat, i will have to use your function. so what do you think | |
|
|
|
| toum (169) | ||||
You need to include <sstream>
It would make things harder.
It's a constructor for the class. Why do you want to define a class for every move ? Using polymorphism here is completely useless and will only make things more complicated. | ||||
|
|
||||
| asda333 (36) | |||
|
Neve rmind about that, i have already understood about polymorphism and classes, that's where the action takes place, but the important part is before it. Here is the stage i have divided my project so i can tackle it in stages and what i have done and what stage i am at. 1. Input from file to vector (Done) 2. Loop through vector, take first string (done) using
3. Remove Brackets from string (done, which you have shown) 4. Convert string to sections change curcmd = REPEAT 10 LEFT 90 REPEAT 100 FORWARD 10 LEFT 5 to curmcd = [LEFT 90] [FORWARD 10, LEFT 5] repeat = [10] [100] so curcmd is 2d array, first row contains all the commands for first repeat second row contains all commands for second repeat. repeat contains the amount of repeat for each command. so curcmd(0,0)=LEFT 90 curcmd(1,0) = FORWARD 10 curcmd(1,1) = LEFT 5 how do i achieve this. i was thinking of maybe converting it to char but, the problem would be how to partition the string with the end of the number being a delimter, like when there is a change from number to letter. after i acquire this i planned the repeat function would be something like loop repeat(i) number of times loop through amount of commands in curcmd vertically. e.g perform curcmd(1), for repeat(1) times, then after perform curcmd(1) and curcmd(2) repeat(2) number of times. formula = curcmd(i) = curcmd(i+1) something like this | |||
|
|
|||
| asda333 (36) | |||
|
so i was thinking about the repeat function and i got below would this work curcmd = left 90 0 forward 10 1 repeat = 10 0 20 1
| |||
|
|
|||
| toum (169) | ||||
It's possible, you just need to rewrite the ReadCommands() function:
As for your repeat function : it will work. You just have to correct small mistakes: - line 12 it should be if( index+1 < lastelementindex )- remove lines 14 and 15. If you go back, then when you go back, you'll go forward, then go back, then go forward, then go back, ... and it will never end. If you have difficulties making this function work, you can take a look at the RecursiveLoop() function I posted previously. Also, now that the array of commands contains entire rows of commands, curcmd(index) contains several commands. In fact it's an array. | ||||
|
Last edited on
|
||||
| asda333 (36) | |
|
I will try implement the things you have shown as for the readcommands function gives error invalid initialization of reference type std::vector<std::vector<command, s... error in passing argument of 2 of void readcommand(std::string& std::vector<std vector.. also your vector vector<Command> CommandList where does this variable Command come from as it says Command not declared in this scope. | |
|
Last edited on
|
|
| toum (169) | |||
|
It's passed from outside. It should be created in your file reading code:
| |||
|
|
|||
| asda333 (36) | |||
im still getting error
the error comes from the function ReadCommands( currentline, CommandList, CommandList ); invalid initialization of reference of type std::vector<int, std::allocator<in.. when stated //insert here the code to perform the commands i don't even know the current command is to know which command to perform. ok, i found out that i can get a certain character from a string using string.at(index) now from here i want to use the number as the last char before moving on to next section command = REPEAT 10 LEFT 10 FORWARD 5 how can i tell the compiler add all the chars on the current index of a char array and when you see a change from number to letter. stop, increment the index and then add that char to the next index including the int or better yet have 2 seperate arrays one from comd and one for amt. so loop through chars if char store in char array index 1 and when it comes to a number store in amt array. then increment index and repeat. i will have to plan it out tonight. i'm not aware of all the different capabilities c++ has. thanks | |||
|
Last edited on
|
|||