Running program from text file

I have a text file that contains:
a=10 - 2;
print a:


I need to use a C++ program that reads the file, solves it, and prints the results.

I've been thinking how this is going to work.
I guess I would have to read the first line until it reaches an "=" sign, then store everything before it into a struct (or some stack/queue maybe), then when it reaches an "=" sign, it would continue reading the line and store everything after the "=" sign into a different struct (or some stack/queue maybe). Then I got lost with having the program get to the next line.

I'm just totally lost on where to go.
What is the context of the lesson? What are you supposed to have learned that would apply here?
Taking CIS 200 this semester, which includes lessons on stacks and queues, linked lists, sorting and searching.
Break it on little pieces, so you have:
1. variables
2. operators
3. literal constants (numbers)
4. commands (functions)

read line by line
parse each line
read character by character until some operator/space or newline reached
determine what is it (1,2,3 or 4)... you should get idea
What exactly are the specifications here?
Can there be more than one variable? Is the right side of = constant or can it have other variables?

I'll assume multiple variables and constants only.

Read a line (I assume line ends at ; , not \n)
Check if that line is "print [some string]:"
If yes, read the [some string] into a variable and print the associated number from the map (I'll explain later on)
Else, that line must be an arithmetic operation.

For simplicity you should treat = separately. Find it, then save the name before = somewhere and keep evaluating the right side:
Find the operator in the line that has the least precedence (first +- then */%)
After you have found it, split the line into the left and right strings so that neither contains the operator.
Example: "5*3+2" becomes "5*3" and "2"
So the value you need to assign to "a" is the sum of the values of "5*3" and "2". You can get the value of "2" with a stringstream. You can get the value of "5*3" by applying the same method recursively, that is, "5*3" becomes (after splitting) "5" * "3" and then finally 5*3=15.

Once you have the numeric value of the right side, you have to bind it to the name "a". Do that with an std::map<std::string, int>. (Of course if you allow only one variable, you don't need this).

This is not a great explanation. If it hasn't become any more clear, say so and I'll try again.
I'm guessing this is the correct program to read line by line and character by character:
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
#include <iostream>
#include <fstream>

using namespace std;

int main() 
{
	ifstream readFile;
	readFile.open ("read.txt"); //open a file stream
	char character;
	int line = 1;
	
	while(readFile.good()) 
	{
		readFile.get(character); //read the file character by character
		if(readFile.eof()) //read until end-of-file
		{
			break;
		}

		cout << character;

		if( character == '\n' )
			line++; //+1 line count
	}
	
	cout << endl;

	readFile.close(); // close the file stream
	system("pause");
	return 0;
}


It does seem to work as it prints exactly what I have in the text file.
But the confusion I have with is storing information or something, like a=10 - 2. How do I make it so 10 - 2 gets stored into a.
@hamsterman,

I can understand everything you said, and yes you can have multiple variables and there are constants.

Here is the rule:
-The language is case sensitive.
-It has two kinds of statements: an assignment statement and a print statement.
-A statement is terminated by a semicolon.
-There is one reserved word “print”.
-You can define variables, reserved words can not be used as variable names, otherwise, the variable name is a combination of letters(a ..z, A.. Z). For example, x, aBc, Klasses are valid, but A1, print are not.
-The assignment statement takes the form “variable = expression”, it assigns the result of the expression to the variable.
-The expression contains integer numbers, variables and binary operators +(add), –(subtract), *(multiply), and /(quotient). For example, 10+3/59, 2*a/pbs + 10 -30 are valid expressions, 10 + + b – c is not.
-The standard rules on operator precedence apply.
-Blanks can appear anywhere just like the way in C++.
-An assignment statement such as xy=abc+3/50 is valid, so is xy = abc + 3 / 50.
-A print statement takes the form “print variable(s)”, it displays the value(s) of the variables on the screen.
-The variable(s) can be one variable, or more than one variable separated by blanks. For example, print a; print a b cbs; are valid print statements.

-For assignment statement, the expression to the right of the equal sign is evaluated and the result is assigned to the variable to the left of the equal sign; for print statement, the name of the variable and the value of it with a equal sign in between will be displayed, one pair per line.

-Your program will assign the value 2 to variable A, assign the value 0(A – 2) to variable c, and stops while trying to evaluate A/c (2/0). An output like “RUN TIME ERROR: divide by 0” should appear on the screen and your program will stop and the rest of the user program is ignored. If you want to be more user friendly, you can indicate where but that is not mandatory. The use program died because it tries to divide by zero. If a variable is referenced without having previously assigned a value, a default value of zero shall be used.



Here is the full example (I only used 2 lines in the first post because I just want to know how I can do it, then I should be able to figure it out from there)

a=10 – 2;
b = 20 – 5 * a / 4;
print b a;
a=b;
print a:

You can use vector of strings to read entire file:
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
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
using namespace std;

int main()
{
	const int maxCharsInLine = 500;
	vector<string> vFile;
	fstream in("text.txt", ios::in);
	if(in.is_open())
	{
		while(!in.eof())
		{
			char buffer[maxCharsInLine];
			in.getline(buffer, maxCharsInLine);
			vFile.push_back(buffer);
		}
	}
	in.close();

	cin.get();
	return 0;
}
You gonna have brainstorm about this task.

I have some code examples that i was downloaded some time ago form UltimateGameProgramming website, but i can't no longer access it (removed maybie) so i have uploaded an example that might get you started, can't find any other similar simple examples:
http://www.2shared.com/file/7giWdNPW/D3D_PropertyScripting.html

Just remove reference to d3d and make console application to test/play with.
Last edited on
So in short, you have functions int evaluate(std::string), void interpret(std::string) and an std::map<std::string, int> var.

*interpret( any string that starts with "print" ) for every space separated string S does std::cout << S << "=" << evaluate(S);
(though you might want to find S in var without evaluate() so that "print 2+2" produces an error)
*interpret( any string that has = ) does var[left_side] = evaluate(right_side);

every expression is either a number or an expression, operator, expression (it is good that you don't need to allow parentheses and unary operators), thus
*evaluate( expression_operator_expression ) returns the operation performed on evaluate(left) and evaluate(right)

*evaluate( any_single_word ) looks up that name in var and returns what it finds (or an error)
*evaluate( number_string ) returns that number

Note that the right way would be to parse the file first into some sort of tree. It would give much more control over what is allowed and what is not, but in this simple case immediate interpretation seems sufficient.

I do realize that this post isn't needed, it's just that this problem is much more interesting than the ones we usually see and I don't have anything (effortless) better to do.
Here's an updated attempt on reading the file.
Can someone help me with storing information from the right side of the "=" sign to the variable on the left? I was told by a classmate that it might be possible to use stacks in this, but I'm not sure.


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
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;
struct code
{
	string line;
	string var;
	string value;
};

class codelist
{
private:
	struct code list[10];
public:
	codelist();
	void display();
};

codelist::codelist() //constructor reads in the information from the file.
	{
	ifstream ins;
	ins.open("read.txt");

	stringstream iss;

	int count = 0; 

	while(ins.good()) //Gets the information from the input file.
	{
		getline(ins, list[count].line, ';');
		iss << list[count].line;
		while(iss.good())
		{
			getline(iss, list[count].var, '=');
			getline(iss, list[count].value);
		}
	count++;
	iss.clear();
	}
	}

void codelist::display()
{
	for (int i=0; i<10; i++)
	{
	cout << list[i].var;
	cout << list[i].value;
	}
}

int main()
{
	codelist code;

	code.display();

	system("pause");
	return 0;
}
What is the output (and input) of that code?

Anyway, a good thing would be to write a tokenizer: a function that takes a file and returns a vector of tokens, where a token is every independent string ("print" "a" ";" "+" "5" etc.)
The most primitive method would be to read the file one char at a time and compare it with the previous char.
So if you find a letter and then a symbol you know that it is time to end one token and start another.
The good thing about this is that then things like finding the left side of "=" will become trivial and you won't have to worry about spaces any more.
Topic archived. No new replies allowed.