Interpreter Bainfuck'a nie działa

0
#include <iostream>
#include <fstream>

std::string read(std::fstream&& file)
{
    std::string temp;
    while (file >> temp) {
    }
    file.close();
    return temp;
}

int main(int argc, char** argv)
{
    std::fstream file;
    if (argc != 1) {
        file.open(argv[1]);
    }
    else {
        std::cerr << "Enter the patch to the *.by file";
        return 1;
    }
    if (!file) {
        std::cerr << "Unable to open file";
        return 2;
    }
    const char* program = read(std::move(file)).c_str();
    char data[1000];
    char* i = data;
    while (*program) {
        switch (*program) {
        case '>':
            ++i;
            break;
        case '<':
            --i;
            break;
        case '+':
            ++(*i);
            break;
        case '-':
            --(*i);
            break;
        case '.':
            std::cout << *i;
            break;
        case ',':
            *i = std::cin.get();
            break;
        case '[': {
            if (*i == 0) {
                int loops = 1;
                while (loops != 0) {
                    ++program;
                    if (*program == ']')
                        --loops;
                    if (*program == '[')
                        ++loops;
                }
            }
        } break;
        case ']': {
            int loops = 0;
            while (loops != 0) {
                ++program;
                if (*program == '[')
                    ++loops;
                if (*program == ']')
                    --loops;
            }
        }
        }
        ++program;
    }
}

Testuje na tym kodzie:

++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

Niestety nic nie wypisuje. Ścieżka na pewno jest dobra

3

Twoja funkcja read wczytuje tylko ostatnie słowo.

const char* program = read(std::move(file)).c_str();

string, na którego dane wskazuje program/c_str() zostaje zniszczony na końcu tej linijki. Dalsze odnoszenie się do jego danych to UB.

Twoja obsługa pętli zupełnie je ignoruje.

0
#include <iostream>
#include <fstream>

void read(std::fstream&& file, std::string& p)
{
    std::string temp;
    while (file >> temp) {
        p += temp;
    }
    file.close();
}

int main(int argc, char** argv)
{
    std::string p;
    std::fstream file;
    if (argc != 1) {
        file.open(argv[1]);
    }
    else {
        std::cerr << "Enter the patch to the *.by file";
        return 1;
    }
    if (!file) {
        std::cerr << "Unable to open file";
        return 2;
    }
    read(std::move(file), p);
    const char* program = p.c_str();
    char data[1000];
    char* i = data;
    while (*program) {
        switch (*program) {
        case '>':
            ++i;
            break;
        case '<':
            --i;
            break;
        case '+':
            ++(*i);
            break;
        case '-':
            --(*i);
            break;
        case '.':
            std::cout << *i;
            break;
        case ',':
            *i = std::cin.get();
            break;
        case '[': {
            if (*i == 0) {
                int loops = 1;
                do {
                    ++program;
                    if (*program == ']')
                        --loops;
                    if (*program == '[')
                        ++loops;
                } while (loops != 0);
            }
        } break;
        case ']': {
            int loops = 0;
            do {
                if (*program == '[')
                    ++loops;
                if (*program == ']')
                    --loops;
                --program;
            } while (loops != 0);
        }
        }
        ++program;
    }
}

Teraz mój kod wygląd tak. Tylko że na wyjściu dostaje: Kello Zorld!Ď

0

Nie mam pomysłu jak zrobić te pętle. Mógłby mi ktoś podpowiedzieć

0

Zmodyfikowałem lekko kod:

#include <iostream>
#include <fstream>

std::string read(std::fstream&& file){
  std::string temp;
  std::string ret;
  while(file>>temp) ret += temp;
  return ret;
}

int main(int argc, char** argv){
  if(argc == 1){
    std::cerr<<"Enter path to the *.by file\nPress any key to exit...";
    std::cin.get();
    return 1;
  }
  std::fstream file(argv[1]);
  if(!file){
    std::cerr<<"Unable to open file\nPress any key to exit...";
    std::cin.get();
    return 2;
  }
  char data[1000];
  char* dp = data; //data pointer
  std::string code = read(std::move(file));
  size_t it = 0;
  size_t nor = 0;
  while(it < code.size()){
    switch(code[it]){
      case '>':
        ++dp;
        break;
      case '<':
        --dp;
        break;
      case '+':
        ++(*dp);
        break;
      case '-':
        --(*dp);
          break;
      case '.':
        std::cout<<*dp;
        break;
      case ',':
        std::cin>>*dp;
        break;
      case '[':
        if(*dp == 0){
          int lc = 1; //loop counter
          while(lc != 0){
            ++it;
            if(code[it] == '[') ++lc;
            if(code[it] == ']') --lc;
          }
        }
        else
          nor = it;
        break;
      case ']':
        it = nor-1;
        break;
      default:
        break;
    }
    ++it;
  }
  std::cout<<"\nExecution time: TODO\nPress any key to exit...";
  std::cin.get();
}

Nawet coś wypisuje tylko że jakieś śmieci:
H莎ę WęČŽ×!ŕ
Mógłby ktoś powiedzieć gdzie leży problem?

1

char data[1000]; - Tablica nie jest zainicjalizowana żadnymi wartościami i może zawierać losowe wartości.
Po naprawieniu tego ( char data[1000] = { 0 }; ) i po zmodyfikowanym inpucie, działa: http://ideone.com/RunPgJ

0

Niestety dalej wypisuje śmieci:

#include <iostream>
#include <fstream>

std::string read(std::fstream&& file){
  std::string temp;
  std::string ret;
  while(file>>temp) ret += temp;
  return ret;
}

int main(int argc, char** argv){
  if(argc == 1){
    std::cerr<<"Enter path to the *.by file\nPress any key to exit...";
    std::cin.get();
    return 1;
  }
  std::fstream file(argv[1]);
  if(!file){
    std::cerr<<"Unable to open file\nPress any key to exit...";
    std::cin.get();
    return 2;
  }
  char data[1000] = {0};
  char* dp = data; //data pointer
  std::string code = read(std::move(file));
  size_t it = 0;
  size_t nor = 0;
  while(it < code.size()){
    switch(code[it]){
      case '>':
        ++dp;
        break;
      case '<':
        --dp;
        break;
      case '+':
        ++(*dp);
        break;
      case '-':
        ++(*dp);
          break;
      case '.':
        std::cout<<*dp;
        break;
      case ',':
        std::cin>>*dp;
        break;
      case '[':
        if(*dp == 0){
          int lc = 1; //loop counter
          while(lc != 0){
            ++it;
            if(code[it] == '[') ++lc;
            if(code[it] == ']') --lc;
          }
        }
        else
          nor = it;
        break;
      case ']':
        it = nor-1;
        break;
      default:
        break;
    }
    ++it;
  }
  std::cout<<"\nExecution time: TODO\nPress any key to exit...";
  std::cin.get();
}
1
 
case '-':
        ++(*dp);
          break;

Co ciekawe w poprzednim poście nie było tego błędu.

Poza tym, cały plik do stringa możesz wczytać tak:
std::string code(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());

0

Dzięki działa, ostateczna wersja:

#include <iostream>
#include <fstream>

std::string read(std::fstream&& file){
  std::string temp;
  std::string ret;
  while(file>>temp) ret += temp;
  return ret;
}

int main(int argc, char** argv){
  if(argc == 1){
    std::cerr<<"Enter path to the *.by file\nPress any key to exit...";
    std::cin.get();
    return 1;
  }
  std::fstream file(argv[1]);
  if(!file){
    std::cerr<<"Unable to open file\nPress any key to exit...";
    std::cin.get();
    return 2;
  }
  char data[1000] = {0};
  char* dp = data; //data pointer
  std::string code = read(std::move(file));
  file.close();
  size_t it = 0;
  size_t nor = 0;
  while(it < code.size()){
    switch(code[it]){
      case '>':
        ++dp;
        break;
      case '<':
        --dp;
        break;
      case '+':
        ++(*dp);
        break;
      case '-':
        --(*dp);
          break;
      case '.':
        std::cout<<*dp;
        break;
      case ',':
        std::cin>>*dp;
        break;
      case '[':
        if(*dp == 0){
          int lc = 1; //loop counter
          while(lc != 0){
            ++it;
            if(code[it] == '[') ++lc;
            if(code[it] == ']') --lc;
          }
        }
        else
          nor = it;
        break;
      case ']':
        it = nor-1;
        break;
      default:
        break;
    }
    ++it;
  }
  std::cout<<"\nExecution time: TODO\nPress any key to exit...";
  std::cin.get();
}
1

swoja droga, ten program bardzo dobrze sie nadaje do nauki debugowania. zobaczysz jaka satysfakcje bedziesz mial gdy krok po kroku dojdziesz do zrodla problemu

0

Nawet nie przewidziałem że problem leży akurat przy znaku '-' sądziłem że jest coś nie tak z '[' albo ']'

1 użytkowników online, w tym zalogowanych: 0, gości: 1