Jump to a specific string of a list<string>

Pages: 12
Hello, just like the title says, i want to jump to a specific string from a line<string> that has a lot of strings that were passed by a text, for example, lets say the list has:
INT a
INT b
a = 4
b = 5
SHOW a
SHOW b
JUMP 5

how can i do to jump to the line 5?
I tried with this but i get stuck on a loop.

1
2
3
4
5
6
7
8
9
if (cadena.at(0) == 'J' && cadena.at(1) == 'U' && cadena.at(2) == 'M' && cadena.at(3) == 'P') {
	if (isnumS(cadena.at(5))) {
	d = atoi(&cadena.at(4));
	it = Original.begin();
	for (int i = 0; i < d; i++) {
	      it++;
	}
	}
}
It seems you have a list of strings named “line”.

line.at(0) == "INT a"
line.at(1) == "INT b"
line.at(2) == "a = 4"


This is where you need an “instruction counter” / “instruction pointer” / index of the current line.

So, given:
1
2
3
4
5
6
7
INT a
INT b
a = 4
b = 5
SHOW a
SHOW b
JUMP 5

The way your interpreter should work is by starting with current_line = 0 (which is line 1 above).

When you find the instruction to “JUMP”, simply set the current_line to the value supplied - 1, and continue from there. For the given code, that will produce an infinite output of
4
5
4
5
4
5
and so on.


You should also consider using some tokenization on your lines. It would make life easier for parsing. For example:

1
2
3
4
5
6
7
8
9
vector <string> tokenizar( const string& c )
{
  vector <string> tokenes;
  istringstream cf( c );
  string token;
  while (cf >> token)
    tokenes.push_back( token );
  return tokenes;
}

Now you can easily process the line.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int current_line = 0;
while (current_line < lines.size())
{
  auto tokenes = tokenizer( line[current_line] );

  if ((tokenes.size() == 2) and (tokenes[0] == "JUMP"))
  {
    auto n = stoi( tokenes[1] ) - 1;
    if (n < 0 or n >= lines.size())
    {
      cerr << "error on line " << current_line << ": JUMP to invalid line number\n";
      return 1;
    }
    current_line = n;
    continue;
  }

  …

  ++current_line;
}

Hope this helps.
how can i do [the] jump to the line 5?
Use a vector instead of a list. If you need random access to items in a collection then a list is a bad choice.
@dhayden the task is save all the lines of the text into a list, not a vector :/. I have already sort things out with that point, now im struggling with another one... This homework jesus haha
Ah, for a list that you are iterating over, use the std::next() function.
Sorry I didn’t notice the advance in your code...

 
#include <iterator> 
 
  it = std::next( Original.begin(), d );  // d is zero-based 


Good luck!
the task is save all the lines of the text into a list, not a vector :/.
I'm sorry to hear that. I'm surprising how many assignments ask students to do things the hard way. :(
A std::list has no direct access to the elements by their position. You have to iterate through the container, from beginning to end or end to beginning, to access an element.

You can not jump to a specific element when using a list.

Using pointer math on a list's iterators is possible, if a bit clunky.

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <list>
#include <string>

int main()
{
   std::list<std::string> str_list { "Hello", "World", "Good-bye", "Cruel", "World" };

   // access the list's 3rd element ( str_list[2] )
   auto itr = str_list.begin(); itr++; itr++;

   std::cout << *itr << '\n';
}
Good-bye
Last edited on
You could use a function and pointer math to "find" specific elements:

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 <list>
#include <string>

std::list<std::string>::iterator list_get(std::list<std::string>&, int);

int main()
{
   std::list<std::string> str_list { "Hello", "World", "Good-bye", "Cruel", "World" };

   // access the list's 4rd element using a function
   std::list<std::string>::iterator found = list_get(str_list, 4);

   std::cout << "The 4th element is " << *found << '\n';
}

std::list<std::string>::iterator list_get(std::list<std::string>& list, int position)
{
   std::list<std::string>::iterator found = list.begin();

   for (int i = 1; i < position; i++, found++) { ; }

   return found;
}
The 4th element is Cruel

WARNING! This function does NO bounds checking, it is just a quick example.
the task is save all the lines of the text into a list, not a vector

If the instructions just says "store all lines in a list" I wouldn't necessarily assume you have to use std::list. A std::vector is often a good way to store a list of things.
Last edited on
If I were to use a vector, how could i do the jump?
If I were to use a vector, how could i do the jump?

By using std::vector's operator[] or at() method.

JUMP (to) 5: You access the 5th element. Vectors are zero-based, so the 5th element is my_vector[4] or my_vector.at(4)

http://www.cplusplus.com/reference/vector/vector/operator[]/
I tried to, but I dont know if its because im also using an iterator for the vector (im not sure if what im doing is correct tbh) when i did my_vector.at(4) it didnt do anything, i will post the code below so you can see what i did to return to that line and to the operation it says on that line. Im struggling to get the math part done, like the a = a + b, im not using a stack and i cant figure how could i do it. Here goes the code. Im pretty new in this so please forgive me if my code is totally bad.
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
bool AYED2019::operaciones(vector<string> Original) {
	bool cond;
	int aux1 = 0, aux2 = 0, o2 = 0, o1 = 0;
	int d = 0;
	char h, k, con;
	for (linea_actual = Script.begin(); linea_actual != Script.end(); linea_actual++) {
		string& cadena = *linea_actual;
		if (cadena.find("INT") == 0) {
				ump.insert({ cadena.at(4),0 });
				// Increment the Iterator to point to next entry
		}
		

		if (cadena.at(2) == '=') {
			for (iterador_mapa = ump.begin(); iterador_mapa != ump.end(); iterador_mapa++) {
				cout << "int: " << iterador_mapa->first << " " << "value: " << iterador_mapa->second;
				if (ump.find(cadena.at(0)) != ump.end()) {
					cout << "Found " << cadena.at(0) << endl;
					ump[cadena.at(0)] = atoi(&cadena.at(4));
				}
				else {
					cout << cadena.at(0) << " not found\n";
				}
			}
		}

		if (cadena.at(0) == 'I' && cadena.at(1) == 'F') {
			size_t pos1 = cadena.find("IF");
			string str1 = cadena.substr(pos1);
			for (iterador_mapa = ump.begin(); iterador_mapa != ump.end(); iterador_mapa++) {
				if (ump.find(cadena.at(5)) != ump.end()) {
					o1 = ump[cadena.at(5)];
					cout << "El valor de o1 es: " << o1 << endl;
					aux1 = 1;
					iterador_mapa++;
					if (ump.find(cadena.at(9)) != ump.end()) {
						o2 = ump[cadena.at(9)];
						cout << "El valor de o2 es: " << o2 << endl;
						aux2 = 1;
					}
					else {
						o2 = atoi(&str1.at(9));
						cout << "El valor de o2 es: " << o2 << endl;
						aux2 = 1;
					}
					if (aux1 == 1 && aux2 == 1) {
						h = str1.at(7);
						condicionIfElse(h, o1, o2);
						break;
					}
				}
			}/*
			if (condicionchequeada == true) {
				if (size_t pos = cadena.find("THEN")) {
					string str3 = cadena.substr(pos);
					for (conteo = declaraciones.begin(); conteo != declaraciones.end(); conteo++) {
						if (str3.find("SHOW")) {
							if (conteo->get_c() == str1.at(10)) {
								
							}
						}

						else if (str3.find("JUMP")) {
							
						}
					}
				}
			}*/
		}

		if (cadena.at(0) == 'S' && cadena.at(1) == 'H' && cadena.at(2) == 'O' && cadena.at(3) == 'W') {
				if ((iterador_mapa = ump.find(cadena.at(5))) != ump.end()) {
					cout << "El valor de: " << iterador_mapa->first << " es: " << iterador_mapa->second << endl;
				}
		}

		if (cadena.at(0) == 'J' && cadena.at(1) == 'U' && cadena.at(2) == 'M' && cadena.at(3) == 'P') {
			if (isnumS(cadena.at(5))) {
				linea_actual = Script.begin();
				d = atoi(&cadena.at(5));
				for (int i = 0; i < d - 2; i++) {
					linea_actual ++ ;
				}
				break; // This shouldnt go, but if i dont put it the output is an infinite loop between the line i jump to and the jump
				
			}
		 }
		
	}
		
	for (iterador_mapa = ump.begin(); iterador_mapa != ump.end(); iterador_mapa++) {
		cout << " " << iterador_mapa->first << " : " << iterador_mapa->second << endl;

	}
}
Alright, so, I think I understand better now, and I am going to recommend you restructure your code a little bit. (Sorry!)

First, the syntax you shared with me leads me to the following syntaxis:

  <symbol>      ::= 'a' .. 'z'
  <integer>     ::= '-'? ('0'..'9')+
  <value>       ::= <symbol> | <integer>
  <operator>    ::= '+' | '-' | '*' | '/' | '=' | '<' | '<=' | '>' | '>=' | '!='  
  <expression>  ::= <value> (<operator> <value>)*

  <declaration> ::= 'INT' <symbol>
  <assignment>  ::= <symbol> '=' <expression>

  <line-number> ::= <expression>
  <jump>        ::= 'JUMP' <line-number>
  <if>          ::= 'IF' '(' <expression> ')' 'THEN' <statement>

  <output>      ::= 'SHOW' <expression>

  <statement>   ::= <assignment> | <jump> | <output>


All statements are terminated by a newline.
This is very, VERY limited, but sufficient. Specifically:

  • Input does not exist
  • Output is limited to a single integer value, newline automatically appended
  • IF cannot nest directly
  • No ELSE
  • No commentary possible
  • Variable names are single, lowercase, alphabetic letters
  • Mathematical expressions are managed strictly left-to-right (no precedence ordering)
  • Comparison operators produce integer 0 or 1 for result
  • IF executes THEN only if the argument expression evaluates to non-zero

Most of these limitations are significant — specifically with respect to the IF statement and how it affects the interpreter’s design. That said, at this point it is not too much to make major modifications should we wish to improve the language. Also, it is easy to start with; we can drop-in something like proper mathematical expression handling later.

@Ivitoh
Let me know if the above syntaxis is incomplete or in any way incorrect.


Using that, we can write a program that will solve the following pair of congruences:

  x ≡ 2 (mod 3)
  x ≡ 3 (mod 7)
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
INT a
INT m
a = 2
m = 3

INT b
INT n
b = 3
n = 7

IF (a = b) THEN JUMP 21

  IF (a < b) THEN JUMP 18

  b = b + n
  JUMP 11

  a = a + m
  JUMP 11

SHOW a
m = m * n
SHOW m

When run, the program should produce the following output:

17
21

Which is correct:

  x ≡ 17 (mod 21)


Let me know if we can continue from here.
Yes, let me tell you exactly how this goes.
INT followed only by a letter from the alphabets declares a new integer, if you put (for example) a=4, then the integer a is set to 4, and so on. The IF / THEN statment is indeed only executed if the condition is true, and JUMP and SHOW are what they say they are, the program should be able to read each line and do what the line says. After that, everything you said is correct.
So you could say INT a = 4?

There are two collections of things you need to manage:


The source code
This is the program code you will be interpreting. The way you store this is important.

For this particular program, you can treat it as a list (or vector) of strings. If your professor expects you to use a list then you will have to do the ‘loop until you get to the correct line’ thing when you handle a JUMP, just like you were in your first post above.

Using a std::list
1
2
3
#include <iterator>
#include <list>
#include <string> 
1
2
typedef std::list <std::string>            Script;
typedef std::list <std::string> ::iterator IteradorLineaActual;

Select a line with
 
  IteradorLineaActual linea_actual = std::next( script.begin(), n - 1 );  // n en [1..N] 

Check to see if the line is a valid index:
 
  if (linea_actual < script.end())

Use the line normally (for example, to print it to output):
 
  std::cout << *linea_actual << "\n";

Get the next line easily:
 
  ++linea_actual;


Using a std::vector
1
2
#include <string>
#include <vector> 
1
2
typedef std::vector <std::string>             Script;
typedef std::vector <std::string> ::size_type IndiceLineaActual;

Select a line using its index:
 
  IndiceLineaActual linea_actual = n - 1;  // n en [1..N] 

Check to see if the line is a valid index:
 
  if (linea_actual < script.size())

Use it normally (for example, to print it to output):
 
  std::cout << script[linea_actual] << "\n";

Get the next line easily:
 
  ++linea_actual;


Either way works fine.
If you wish to write a custom container (like a custom linked list), you can do that too.


The Environment
The “environment” is the name→value lookup for the script’s variables. If you have to roll your own, there is an example in the other thread (http://www.cplusplus.com/forum/beginner/253473/#msg1114631).

Otherwise you can use a std::unordered_map to make your life easy:

 
#include <unordered_map> 
1
2
3
typedef char VariableNombre;
typedef int  VariableValor;
typedef std::unordered_map <VariableNombre, VariableValor> Entorno;

To add a value to the environment:
1
2
  entorno['a'];  // adds the default value, in this case = 0
  entorno['a'] = 12;

To check whether a value exists in the environment:
 
  if (entorno.count( 'a' ))

To get the value (for example, to print it to standard output):
 
  std::cout << entorno['a'] << "\n";

With these two things, you are ready to parse your code and modify the variable environment. I will talk about parsing the code next.
But... The way you are implementing it is specificly for my text example, but if i dont know the lines they gave me? how do i run through them? I was starting the iterator and making it read line by line with a for
Remember, there are two programs:
  • your code
  • the script your code will execute

Your code will be able to execute any valid program given to it.
Start with making your AYED2019 class be able to load a script and manipulate an environment (add and use variables).

You have already done most of that, so most of your work will be getting rid of anything that doesn’t do those two things.

I’ll be back later...
@Duthomhas
regarding the part where i have to do the math... i was trying to do something like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for (linea_actual = Script.begin(); linea_actual != Script.end(); linea_actual++) {
		iterador_mapa = Entorno.begin();
		string& chain = *linea_actual;
		if(chain.size()>6){
			if (chain.at(2) == '=') {
				if (Entorno.find(chain.at(4)) != Entorno.end()) {
					auxiliar = iterador_mapa->first;
					tempA = Entorno[chain.at(4)];
				}
				iterador_mapa++;
				if (Entorno.find(chain.at(8)) != Entorno.end() && (Entorno.find(chain.at(4)) != Entorno.find(chain.at(8)))) {
					tempB = atoi(&chain.at(8));
				}
				operacion = chain.at(6);
				calcular(tempA, tempB, operacion);
			}
		}
	}
but i dot know why it doesnt do the math, it just returns me the Entorno[chain.at(4)] value
The code for calcular is
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
int AYED2019::calcular(int o1, int o2, char aux) {
	switch (aux) {
		case '+': {
			total = o1 + o2;
		}
				  break;
		case '-' : {
			total = o1 - o2;
		}
				   break;
		case '*': {
			total = o1 * o2;
		}
				  break;
		case '/': {
			if (o2 == 0) {
				cout << "Division por 0 no posible.";
			}
			else {
				total = o1 / o2;
			}
		}
	}
	cout << "Total: " << total << endl;
	return total;
}
Okay I managed to get that sort out i think, i changed this
1
2
3
4
5
6
7
8
9
if (chain.at(2) == '=') {
				if (Entorno.find(chain.at(4)) != Entorno.end()) {
					auxiliar = iterador_mapa->first;
					tempA = Entorno[chain.at(4)];
				}
				iterador_mapa++;
				if (Entorno.find(chain.at(8)) != Entorno.end() && (Entorno.find(chain.at(4)) != Entorno.find(chain.at(8)))) {
					tempB = atoi(&chain.at(8));
				}
for something like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if(chain.size()>6){
				if (chain.at(2) == '=') {
					if (Entorno.find(chain.at(4)) != Entorno.end()) {
						auxiliar = iterador_mapa->first;
						tempA = Entorno[chain.at(4)];
					}
					iterador_mapa++;
					if (isnumS(chain.at(8))) {
						tempB = atoi(&chain.at(8));
					}
					else {
						tempB = Entorno[chain.at(8)];
					}

					operacion = chain.at(6);
					calcular(tempA, tempB, operacion);
				}
			}
Okay yes, Ive managed to that, but how can I excute the IF THEN part? i was thinking of splitting that string but for what i understand if i do that the counter of the iterador should also increase? I mean if i had IF ( SOMETHING ) THEN JUMP 6, if i were to split it, now the original line 6 would be 7, am i correct?
Pages: 12