Brainfuck interpreter strange output - c++

I've decided to write a simple Brainfuck IDE in C++ using Borland's CppBuilder6. I've put on my for a RichEdit and made it look somewhat like notepad. Then I've added TEdit for input and TMemo for output. After some tests, I thought that RichEdit is bad component to use in my case and I changed it to TMemo.
In my code input = Edit2, code = Memo2, output = Memo1. I rewrote it two times and this version seems most correct; I've decided to not use pointers (i thought about it and even wrote pointer version, unfortunately it didn't work too so for simplifying I've removed pointers).
char *cells = (char*)calloc(65536,1); //Should i use malloc?
int cellp = 0;
void __fastcall BFIde::interpret() {
char* pf = Memo2->Lines->Text.c_str(); //Weird output
char* p = (char*)malloc(strlen(pf)+1);
strcpy(p, pf); //Because pf is constant, i need to copy it into not constant string.
int pp = 0;
MessageBox(NULL,p,NULL,MB_OK); //To ensure that program is correct, but it ain't.
while(p[pp]){
switch(p[pp]){
case '>':
cellp++;
break;
case '<':
cellp--;
break;
case '+':
MessageBox(NULL, "Plus", NULL, MB_OK); //When executing test code, never gets shown.
cells[cellp]++;
break;
case '-':
cells[cellp]--;
break;
case '.':{ //It should look other, but I've replaced it to ensure that output is correct.
char arr[2]={cells[cellp],0};MessageBox(NULL, arr, NULL, MB_OK);}
break;
case ',': //Remove first character and pass it to program
if(Edit2->Text == "")cells[cellp] = 0;
else {cells[cellp] = Edit2->Text.c_str()[0];char* str;strcpy(str, Edit2->Text.c_str());Edit2->Text=str++;}
break;
case '[':{ //Propably works.
int bal = 1;
if (cells[cellp] == '\0') {
do {
pp++;
if (p[pp] == '[') bal++;
else if (p[pp] == ']') bal--;
} while ( bal != 0 );
}
break;
}
case ']':
int bal2 = 0;
do {
if (p[pp] == '[') bal2++;
else if (p[pp] == ']') bal2--;
pp--;
} while ( bal2 != 0 );
break;
}
pp++;
}
MessageBox(NULL, IntToStr(cellp).c_str(), NULL, MB_OK); //To check that something was parsed. Shows 0 everytime (not expected).
}
When i enter some code, eg. "+." and execute this function (via button), this shows series of messagebox. First: ┼ (line 8), second: 0 (line 55), and nothing more shows. Expected result was to write: First +., second Plus, and empty 3rd. What I've made wrong in my code? Maybe I've missed something.

There are memory-related errors in your code. The very first line of interpret() is taking a pointer to a temporary AnsiString that is freed immediately afterwards, so the subsequent lines of code are operating with a dangling pointer to invalid memory. Likewise, in your ',' handler, you are trying to copy data to an uninitialized pointer that is not pointing at valid memory. And you are not doing any bounds checking when accessing your cells[] array.
There are also logic errors in your ']' handler. You are not checking the current cell data for 0 to decide which instruction to jump to next, and you are not seeking backwards correctly when looking for the opening '['.
Try something more like this instead:
static const int maxCells = 65536;
class BFIde : public TForm
{
__published:
TEdit *Edit2;
TMemo *Memo1;
TMemo *Memo2;
TButton *Button1;
void __fastcall Button1(TObject *Sender);
private:
char cells[maxCells];
int cellp;
char& cellData();
void __fastcall interpret(const AnsiString &commands, AnsiString input);
public:
__fastcall BFIde(TComponent *Owner);
};
__fastcall BFIde::BFIde(TComponent *Owner)
: TForm(Owner)
{
}
char& __fastcall BFIde::cellData()
{
if ((cellp < 0) or (cellp >= maxCells))
throw Exception("Accessing cells out of bounds");
return cells[cellp];
}
void __fastcall BFIde::interpret(const AnsiString &commands, AnsiString input)
{
Memo1->Clear();
memset(cells, 0, maxCells);
cellp = 0;
const char* start = commands.c_str();
const char* p = start;
while (*p)
{
switch (*p)
{
case '>':
++cellp;
break;
case '<':
--cellp;
break;
case '+':
cellData()++;
break;
case '-':
cellData()--;
break;
case '.':
{
char ch = cellData();
Memo1->SelStart = Memo1->GetTextLen();
Memo1->SelLength = 0;
Memo1->SelText = ch;
break;
}
case ',':
{
char ch;
if (input.Length() == 0) {
ch = '\0';
}
else {
ch = input[1];
input.Delete(1, 1);
}
cellData() = ch;
break;
}
case '[':
{
if (cellData() == '\0')
{
int bal = 1;
while (*++p)
{
if (*p == '[') {
++bal;
}
else if (*p == ']')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
case ']':
{
if (cellData() != '\0')
{
int bal = 1;
while (p > start)
{
--p;
if (*p == ']') {
++bal;
}
else if (*p == '[')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
}
++p;
}
ShowMessage(cellp);
}
void __fastcall BFIde::Button1(TObject *Sender)
{
interpret(Memo2->Lines->Text, Edit2->Text);
}

Related

How can I assign values in the form 'void' to variables in the form 'char'?

I'm creating a program using a stack to make sure the parenthesis order is correct.
But a small error holds me back.
's1.pop()' cannot be assigned to the variable 'open_ch'.
I tried the function 'malloc', but I couldn't stop the error.
This error makes me tired. What is the solution to this error?
int check_matching_STL(const char* in)
{ stack <int> s1;
char ch, open_ch;
int i, n = strlen(in);
for (i = 0; i < n; i++)
{
ch = in[i];
switch (ch)
{
case '(': case '[': case '{':
s1.push(ch);
break;
case ')': case ']': case '}':
if (s1.empty())
return 0;
else
{
open_ch = s1.pop(); // error
if ((open_ch == '(' && ch != ')') ||
(open_ch == '[' && ch != ']') ||
(open_ch == '{' && ch != '}'))
return 0;
break;
}
}
}
if (!s1.empty())
return 0;
return 1;
}
std::stack::pop removes the top element from the stack.
i think you was searching for std::stack::top instead.
open_ch = s1.top(); //getting top element
s1.pop(); //removing top element
and i think you should also change your std::stack<int> to std::stack<char> to make your purpose clearer and avoid useless implicit casts int to char and char to int that could push out warnings.

c++ The evaluation of expression. How to exit the while loop?

I use stack to evaluate an expression.
The most important function is below:
double Expression_Eval()
{
SeqStack<char,100> OPTR;
SeqStack<double,100> OPND;
OPTR.Push('#');
char ch;
ch=getchar();
while (ch!='#' || OPTR.GetTop()!='#')
{
if (!InOPTR(ch))
{
int n=ch-'0';
double num=(double)n;
OPND.Push(num);
ch=getchar();
}
else
{
char pre_op=OPTR.GetTop();
switch (Precede(pre_op, ch))
{
case '<': OPTR.Push(ch);
ch=getchar();
break;
case '=': OPTR.Pop();
ch=getchar();
break;
case '>': double b=OPND.Pop();
double a=OPND.Pop();
pre_op=OPTR.Pop();
OPND.Push(Operate(a, pre_op, b));
ch=getchar();
break;
}
}
}
return OPND.GetTop();
}
Then, when I input 8/(5-3)#, it will not print the result.
I think the loop termination condition ch!='#' || OPTR.GetTop()!='#' is wrong.
When I press Enter, getchar() get the last char is CR but not #.
But, I don't know how to revise it to make my program work.
The other part of my program is below:
#include<iostream>
using namespace std;
template<typename DataType,int StackSize>
class SeqStack
{
private:
DataType data[StackSize];
int top;
public:
SeqStack()
{ top=-1; }
~SeqStack() {}
void Push(DataType x)
{
if(top == StackSize-1)
throw "error";
data[++top]=x;
}
DataType Pop()
{
if(top == -1)
throw "error";
DataType x=data[top--];
return x;
}
DataType GetTop()
{
if(top != -1)
return data[top];
else
cout<<"error";
}
};
bool InOPTR(char ch)
{
if( (ch>='(' && ch<='+') || ch=='-' || ch=='/' )
{
return true;
}else{
return false;
}
}
char Precede(char op1, char op2)
{
char pri[7][7]={ {'>','>','<','<','<','>','>'}
, {'>','>','<','<','<','>','>'}
, {'>','>','>','>','<','>','>'}
, {'>','>','>','>','<','>','>'}
, {'<','<','<','<','<','=','#'}
, {'>','>','>','>','#','>','>'}
, {'<','<','<','<','<','#','='} };
int m,n;
switch(op1)
{
case '+': m=0;break;
case '-': m=1;break;
case '*': m=2;break;
case '/': m=3;break;
case '(': m=4;break;
case ')': m=5;break;
case '#': m=6;break;
}
switch(op2)
{
case '+': n=0;break;
case '-': n=1;break;
case '*': n=2;break;
case '/': n=3;break;
case '(': n=4;break;
case ')': n=5;break;
case '#': n=6;break;
}
return pri[m][n];
}
double Operate(double a, char op, double b)
{
double result;
switch(op)
{
case '+': result=a+b; break;
case '-': result=a-b; break;
case '*': result=a*b; break;
case '/': result=a/b; break;
}
return result;
}
int main()
{
double r=Expression_Eval();
cout<<r<<endl;
return 0;
}
Problem seem to be that '#' is considered a number, but it should be considered an operation:
Use:
bool InOPTR(char ch) {
if ((ch >= '(' && ch <= '+') || ch == '-' || ch == '/' || ch=='#'){
return true;
}
else {
return false;
}
}
Note that '#' is ASCII 64 which is not covered in the ranage '(' to '+' [40-43]
Hope this helps.
You need to consume carriage return or newline character after getchar(); which comes into play when you press enter button.
One trick is as below.
ch=getchar();
getchar(); //this getchar to consume CR.
since you have used ch = getchar() many times you have to use above solution at many places.
Better solution to this problem will be to enter string instead of entering single character using getchar()...
Hope you got what I am trying to say...

C++ : read csv file with fgetc and separate words on semicolon ";"

I have to read in a csv file with 5 fields (int , char[], char[], char[], float) that looks like that :
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
I have to put the fields in a struct, and then put the struct after one line is complete, into a array of the struct type ...
for the learning effect, we are only allowed to use LOW-LEVEL coding, and only use functions like fgetc, strcpy and no strings, only char[]...
Now I made my algorithm to read the textfile character by character, but I have problems separating them correctly, putting them together again and assigning them to the struct fields correctly. Here is my Code:
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
using namespace std;
int main(int argc, char **argv)
{
struct Stud{
long matrnr;
char vorname[30];
char name[30];
char datum[30];
float note;
};
const int MAX = 30;
Stud stud;
Stud mystud[30]; // <<-- Array of "Stud" type
//memset((void*)mystud,0,sizeof(mystud) * sizeof(Stud));
int wordCounter(0);
int i(0); //thats the charCounter or index
int studentCounter(0);
char wort[MAX];
//int matrnr;
//char vorname[MAX];
//char name[MAX];
//char datum[MAX];
//float note;
FILE * pFile;
int cnr(0);
pFile=fopen("studentendaten.txt","r");
if (pFile==nullptr)
{
perror ("Fehler beim öffnen der Datei");
}
else
{
while (cnr != EOF)
{
(cnr=fgetc(pFile)) ;
if ((char)cnr == '\n') {
mystud[studentCounter] = stud;
studentCounter++;
continue;
}
if ((char)cnr == ';') {
wort[i] = '\0';
switch (wordCounter % 5) {
case 0:
stud.matrnr = atol(wort);
break;
case 1:
strcpy(stud.name, wort);
break;
case 2:
strcpy(stud.vorname, wort);
break;
case 3:
strcpy(stud.datum,wort);
break;
case 4:
stud.note = atof(wort);
break;
}
wordCounter++;
i = 0;
continue;
}
if (wordCounter % 5 == 0 && (char)cnr != ';') {
wort[i] = (char)cnr;
i++;
//stud.matrnr = atol(wort);
}
if (wordCounter % 5 == 1) {
wort[i] = (char)cnr;
i++;
//strcpy(stud.name, wort);
}
if (wordCounter % 5 == 2) {
wort[i] = (char)cnr;
i++;
//strcpy(stud.vorname, wort);
}
if (wordCounter % 5 == 3) {
wort[i] = (char)cnr;
i++;
//strcpy(stud.datum,wort);
}
if (wordCounter % 5 == 4) {
wort[i] = (char)cnr;
i++;
//stud.note = atof(wort);
}
}
fclose (pFile);
}
for (int i(0) ; i <= studentCounter; i++) {
cout <<mystud[i].matrnr << " " << mystud[i].name << " " << mystud[i].vorname <<" "
<< mystud[i].datum <<" " << mystud[i].note << endl;
//printf("%5ld %5s %5s %5s %5f \n",mystud[i].matrnr,mystud[i].name,mystud[i].vorname,mystud[i].datum,mystud[i].note);
}
return 0;
}
I am not sure if it has to do with a wrong increment variables, or the fact that I don't put an '\0' at the end of my wort[] array..and therefore not recognizing the end of my array? And if so, how do I do it without knowing where the end exactly is... ? (I don't know the length of the words..)
EDIT: I updated my code again, the only thing that wonders me is that the LAST LINE IS NOT BEING CORRECTLY PARSED , its showing some rubbish, and I can't see the error in my code...
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
Suggestion: use a case structure for the parsing, and make yourself a "copyToSemicolon" function: then you can write things like
sIndexCount = 0;
char temp[50];
while((cnr=fgetc(pFile)) != EOF) {
offset = 0;
for(var = 0; var < 5; var++ {
switch(var) {
case 0:
offset = copyToSemicolon(temp, cnr, offset) + 1;
stud.matrnr = atoi(temp);
break;
case 1:
offset = copyToSemicolon(mystud[sIndexCount].vorname, cnr, offset) + 1;
break;
... etc
}
}
sIndexCount++;
if(sIndexCount == 50) break; // in case the input file is longer than our structure
}
And you need a function copyToSemicolon that takes two char* pointers as inputs, and that copies characters from the second string (starting at offset) until it reaches either a semicolon or the end of line - and that returns the offset it reached (last character read).
int copyToSemicolon(char* dest, char* source, int offset) {
while(source[offset] != ';' && source[offset] != '\n') {
*dest = source[offset++];
dest++;
}
return offset;
}
EDIT strtok method:
sIndexCount = 0;
char temp[50];
while((cnr=fgetc(pFile)) != EOF) {
offset = 0;
temp = strtok(cnr, ';');
for(var = 0; var < 5; var++ {
switch(var) {
case 0:
stud.matrnr = atoi(temp);
break;
case 1:
strcpy(mystud[sIndexCount].vorname, strtok(NULL, ';'));
break;
... etc
case 4:
mystud[sIndexCount].note = atof(strtok(NULL, '\n'));
}
}
sIndexCount++;
if(sIndexCount == 50) break; // in case the input file is longer than our structure
}
One issue that I am seeing is that your code copies or parses one character at a time, such that when you're reading 2345678;Meier;Hans;12.10.1985;2.4; you first set stud.matrnr to 2, then 23, then 234, then 2345, then 23456, then 234567, then 2345678. Similarly, for stud.name, you first set it to M, then the Me, then to Mei, etc. I propose to you to think of things in a different way. I'll give you some pseudocode:
while (!eof) {
get character from file
if (character isn't ';' and isn't '\n') {
copy character into buffer (increment buffer index)
} else if (character is ';') {
it's the end of a word. Put it in its place - turn it to an int, copy it, whatever
reset the buffer
} else if (character is '\n') {
it's the end of the last word, and the end of the line. Handle the last word
reset the buffer
copy the structure
}
}
This should make life a lot easier on you. You're not changing your data nearly as much, and if you need to debug, you can focus on each part on its own.
Generally, in programming, the first step is making sure you can say in your native speaking language what you want to do, then it's easier to translate it to code. You're close with you implementation, and you can make it work. Just be sure you can explain what should be happening when you see ';' or '\n'.
Since you have tagged this as C++, you should consider using std::getline for reading the line from the file, the use std::getline(file, text_before_semicolon, ';') for parsing the fields.
You could also use std::istringstream for converting the textual representation in the text line to internal numeric format.

c++ Bracket Validator with Stacks

I'm trying to write a program that will validate a user input consisting of brackets for proper nesting using a stack. I am trying to do this without the use of STL containers or recursion. I have somewhat hit a road block and I'm looking for a little nudge in the right direction. I think I am kind of close, but I feel like I may be oversimplifying it (I'm in the process of learning through self teaching)
Here is what I have so far:
#include <iostream>
#include <string>
#include "ArrayStack.h"
using namespace std;
bool test(char *argg);
int main()
{
string input;
int size = 50;
cout << "enter here: ";
getline(cin, input);
for (int i = 0; i < size; i++)
test(input[i]);
}
bool test(char *argg)
{
ArrayStack S;
char D;
while ( *argg ) {
switch( *argg ) {
case '[': case '{': case '(':
S.push( *argg );
break;
case ']':
if( S.isEmpty() )
return false;
D = S.pop();
if( D!='[' )
return false;
break;
case '}':
if( S.isEmpty() )
return false;
D = S.pop();
if( D!='{' )
return false;
break;
case ')':
if( S.isEmpty() )
return false;
D = S.pop();
if( D!='(' )
return false;
break;
default:
return false;
}// end switch
argg++;
}// end while
return S.isEmpty(); // return true if reach here with empty stack
}
Thanks for any assistance in advance
If anything, you're overcomplicating it
char inverse(char c){
if(c==']') return '[';
if(c=='}') return '{';
if(c==')') return '(';
return c;
}
int stillvalid(char c, ArrayStack &stack){
if(strchr("[{(", c))
stack.push(c);
else if(strchr("]})", c))
if(stack.isEmpty() || inverse(c) != stack.pop())
return 0;
return 1;
}
int main(){
int c;
ArrayStack stack;
while((c=getchar())!=EOF){
if(!stillvalid((char)c, stack)){
printf("bad\n");
exit(0);
}
}
printf("good\n");
return 0;
}
Should be all you need.
Trace through your code by hand with the input myfunc(42);
Observe what happens, character by character. That should point you your errors.

C++ simple operations (+,-,/,*) evaluation class

I am looking for a C++ class I can incorporate into a project I am working on.
the functionality I need is evaluation of string operations to numerical form: for example "2 + 3*7" should evaluate to 23.
I do realize what I am asking is a kind of an interpreter, and that there are tools to build them, by my background in CS is very poor so I would appreciate if you can point me to a ready made class .
This should do exactly what you want. You can test it live at: http://www.wowpanda.net/calc
It uses Reverse Polish Notation and supports:
Operator precedence (5 + 5 * 5 = 30 not 50)
Parens ((5 + 5) * 5 = 50)
The following operators: +, -, *, /
EDIT: you'll probably want to remove the Abs() at the bottom; for my needs 0 - 5 should be 5 and not -5!
static bool Rpn(const string expression, vector<string> &output)
{
output.clear();
char *end;
vector<string> operator_stack;
bool expecting_operator = false;
for (const char *ptr = expression.c_str(); *ptr; ++ptr) {
if (IsSpace(*ptr))
continue;
/* Is it a number? */
if (!expecting_operator) {
double number = strtod(ptr, &end);
if (end != ptr) {
/* Okay, it's a number */
output.push_back(boost::lexical_cast<string>(number));
ptr = end - 1;
expecting_operator = true;
continue;
}
}
if (*ptr == '(') {
operator_stack.push_back("(");
expecting_operator = false;
continue;
}
if (*ptr == ')') {
while (operator_stack.size() && operator_stack.back() != "(") {
output.push_back(operator_stack.back());
operator_stack.pop_back();
}
if (!operator_stack.size())
return false; /* Mismatched parenthesis */
expecting_operator = true;
operator_stack.pop_back(); /* Pop '(' */
continue;
}
if (*ptr == '+' || *ptr == '-') {
while (operator_stack.size() && IsMathOperator(operator_stack.back())) {
output.push_back(operator_stack.back());
operator_stack.pop_back();
}
operator_stack.push_back(boost::lexical_cast<string>(*ptr));
expecting_operator = false;
continue;
}
if (*ptr == '*' || *ptr == '/') {
while (operator_stack.size() && (operator_stack.back() == "*" || operator_stack.back() == "/")) {
output.push_back(operator_stack.back());
operator_stack.pop_back();
}
operator_stack.push_back(boost::lexical_cast<string>(*ptr));
expecting_operator = false;
continue;
}
/* Error */
return false;
}
while (operator_stack.size()) {
if (!IsMathOperator(operator_stack.back()))
return false;
output.push_back(operator_stack.back());
operator_stack.pop_back();
}
return true;
} // Rpn
/***************************************************************************************/
bool Calc(const string expression, double &output)
{
vector<string> rpn;
if (!Rpn(expression, rpn))
return false;
vector<double> tmp;
for (size_t i = 0; i < rpn.size(); ++i) {
if (IsMathOperator(rpn[i])) {
if (tmp.size() < 2)
return false;
double two = tmp.back();
tmp.pop_back();
double one = tmp.back();
tmp.pop_back();
double result;
switch (rpn[i][0]) {
case '*':
result = one * two;
break;
case '/':
result = one / two;
break;
case '+':
result = one + two;
break;
case '-':
result = one - two;
break;
default:
return false;
}
tmp.push_back(result);
continue;
}
tmp.push_back(atof(rpn[i].c_str()));
continue;
}
if (tmp.size() != 1)
return false;
output = Abs(tmp.back());
return true;
} // Calc
/***************************************************************************************/
boost::spirit comes with a calculator example which would do what you need:
http://www.boost.org/doc/libs/1_33_1/libs/spirit/example/fundamental/ast_calc.cpp
muParser is written in C++ and does just what you need.
C++ in Action, in addition to being a great book on C++, includes a fully working calculator, doing what you need (and actually much more). And the book is available for free online