чтение ввода с клавиатуры

Мне нужно прочитать с клавиатуры (stdin) следующий текст. Обратите внимание, что он будет вводиться пользователем с клавиатуры только в этом формате.

 #the total size of physical memory (units are B, KB, MB, GB)
    512MB   2       #the following are memory allocations
    {
            abc = alloc(1KB);
             {
                y_ = alloc(128MB);
                x1= alloc(128MB);
                y_ = alloc(32MB);
               for (i = 0; i < 256; i++) abc[i] =alloc(512kB);
                  x1 = alloc(32MB); x2 = alloc(32MB); x3 = alloc(32MB);
               x1.next = x2, x2.next = x3, x3.next = x1;
    }
    abc = alloc(256MB);
    }

Итак, в основном позвольте мне сломать это. строка, начинающаяся со знака #, считается комментарием и игнорируется. первые два распределения - это размер физической памяти и количество поколений. глобальная скобка будет открыта. и за ним может следовать строка с именем

abc = alloc(1KB);

где abc — имя объекта, 1 КБ — выделенный объем памяти. x1.next = x2, здесь x1 указывает на x2.

for (i = 0; i < 256; i++) abc[i] =alloc(512kB);

ОС цикла for, введенная в этом формате, может иметь ту же линейную команду или может иметь вложенные циклы for.

У меня есть следующий код, который несколько позаботится об этом. Я хочу знать, улучшить его. Пожалуйста, помогите.

И мой код таков:

#include <iostream>
#include <algorithm>
#include <string>
#include <iomanip>
#include <limits>
#include <stdio.h>
#include <sstream>



using namespace std;
using std::stringstream;

string pMem,sGen, comment,val,input,input_for,id_size,id,init_str1, init_str2, inc_str, id_dummy,s_out,sss, id_dummy1;
int gen=0, pMem_int=0,i=0, gBrckt =0,cBrckt=0, oBrckt=0, id_size_int,v1,v2, for_oBrckt=0,for_cBrckt=0,y=0, y1=0, g=0;
unsigned long pMem_ulong =0, id_size_ulong;
char t[20], m[256], init1[10],init2[10],inc[10];
unsigned pos_start, pos,pos_strt=0,pos_end=0;

string extract(string pMem_extract);
unsigned long toByte(int pMem_int_func, string val);
void commentIgnore(string& input);
void func_insert();
void func_insert_for();
stringstream out;
void commentIgnore_for(string& input_for);

int main() 
{
  /* Reading the input main memory and num of generations */
  /* Ignoring comment line */
  cin >> pMem;
  if(pMem == "#") {
    cin.clear();
    pMem.clear();
    getline(cin,comment);
    cin >> pMem;
  }
  if(pMem == "#") {
    cin.clear();
    pMem.clear();
    getline(cin,comment);
    cin >> pMem;
  }
  if(pMem == "#") {
    cin.clear();
    pMem.clear();
    getline(cin,comment);
    cin >> pMem;
    }
  /* Reading input generations */
  cin>> sGen;
  if(sGen == "#") {
    cin.clear();
    sGen.clear();
    getline(cin,comment);
    cin >> sGen;
  }
  if(sGen == "#") {
    cin.clear();
    sGen.clear();
    getline(cin,comment);
    cin >> sGen;
  }
  if(sGen == "#") {
    cin.clear();
    sGen.clear();
    getline(cin,comment);
    cin >> sGen;
  }
  /* Convert sGen and physical memory to int and report error if not a number */
  gen = atoi(sGen.c_str());
  if(gen ==0) {
    cerr << "Generation must be a number"<<endl;
      exit(0);
  }
  pMem_int = atoi(pMem.c_str());
  //  cout<< gen<<" "<<pMem_int<<endl;

  /* Now that the number from pMem is removed, get its unit B,MB,KB */
  extract(pMem); /* returns val(string) */

  /* convert the given physical memory to Byte. input: pMem_int*/
  toByte(pMem_int, val); /*  return(pMem_ulong)*/
  // move pMem_ulond to another location to keep address intact
  /* read rest of the inputs  */
  /* Ignore comment lines before the global bracket */
   cin >> input;
  if(input == "#"){
    cin.clear();
    input.clear();
    getline(cin,comment);
    cin >> input;
  }
  if(input == "#"){
    cin.clear();
    input.clear();
    getline(cin,comment);
    cin >> input;
  }
  if(input == "#"){
    cin.clear();
    input.clear();
    getline(cin,comment);
    cin >> input;
  }

  if(input.compare("{") ==0)
    gBrckt=1;

  else {
    cerr<< "Syntax error\n";
    exit(0);
  }

  /* Clearing the input stream for next input */
  cin.ignore(numeric_limits<streamsize>::max(), '\n');
  cin.clear();
  input.clear();
  //cout<<"input: "<<input<<endl;
  while( getline(cin,input)) {

    if(input == "CTRL-D")
      break;

    commentIgnore(input);
    //cout<<"inputloop: "<<input<<endl;

    /* If input = '{' or '}'*/
    if(input.compare("{") ==0)
      oBrckt = oBrckt + 1;

     if (input.compare("}") ==0)
      cBrckt = cBrckt + 1;

     if (((input.find("alloc"))!= string::npos) && (input.find("alloc") < input.find("for"))) {
       func_insert();
       //call the allocate function here with name: id, size: id_size_ulong
     }

     if ((input.find("for")) != string::npos) {
        sscanf(input.c_str(), "for (%s = %d; %s < %d; %[^)])", init1, &v1, init2, &v2, inc);
    init_str1 = init1, init_str2 = init2, inc_str = inc;

    cout<<init1<<" ="<< v1<<" "<<init_str1<<" < " << v2<< " "<< inc_str<<endl;
    cout << input <<endl;

    if(init_str1 != init_str2) {
      cerr << "Error!\n";
      exit(0);
    }

    if ((input.find("alloc"))!= string::npos) {
      // unsigned pos = (input.find("alloc"));

      if((input.find(";")) != string::npos) {

         pos_start = (input.find(")")+1);
        string alloc_substr  = input.substr(pos_start);
        cout<<"Substring alloc: "<< alloc_substr<<endl;

        func_insert();
        //call the allocate function here with name: id, size: id_size_ulong
      }
      else {
        cerr << "ERROR: SYNTAX\n";
        exit(0);
      }


    }
    //  cin.ignore();
    while(getline(cin,input_for)) {
      commentIgnore_for(input_for);

      if ((input_for.find("{") != string::npos)) {
        pos = input_for.find("{");
        for_oBrckt = for_oBrckt+1;
        string for_brckt = input_for.substr(pos,pos);
        cout<< "Found: " << for_oBrckt<<endl;
      }


      if ((input_for.find("}") != string::npos)) {
         pos = input_for.find("}");
        for_cBrckt = for_cBrckt+1;
        string for_brckt = input_for.substr(pos,pos);
        cout<< "Found: " << for_cBrckt<<endl;
      }

      if (((input_for.find("alloc"))!= string::npos) && (input_for.find("alloc") < input_for.find("for"))) {
        func_insert_for();
        //call the allocate function here with name: id, size: id_size_ulong
      }




      if(for_oBrckt == for_cBrckt)
        break;


    }
    cout<<"out of break"<<endl;
     }

      if (((input.find(".next"))!= string::npos) && (input.find(".next") < input.find("for"))) {
       func_insert();
       //call the allocate function here with name: id, size: id_size_ulong
     }

      if(((cBrckt-oBrckt)) == gBrckt)
       break;
  }

}

/*---------------------- Function definitions --------------------------------*/
/* Function to extract the string part of physical memory */
string extract(string pMem_extract) {
  i=0;
  const char *p = pMem_extract.c_str();
  for(i=0; i<=(pMem_extract.length()); i++) {
    if (*p=='0'|| *p=='1'|| *p=='2'|| *p=='3'|| *p =='4'|| *p=='5'|| *p=='6'|| *p=='7'|| *p=='8'|| *p=='9')
      *p++;
    else {
      val = pMem_extract.substr(i);
      return(val);
    }
  }
}

/* Convert the physical memory to bytes. return(pMem_ulong);*/
unsigned long toByte(int pMem_int_func, string val)
{
  if (val == "KB")
    pMem_ulong =  (unsigned long) pMem_int_func * 1024;
  else if (val == "B")
    pMem_ulong = (unsigned long) pMem_int_func;
  else if (val == "GB")
    pMem_ulong = (unsigned long) pMem_int_func * 1073741824;
  else if (val == "MB")
    pMem_ulong = (unsigned long) pMem_int_func * 1048576;
  else {
    cerr<<"Missing the value in memory, B, KB, MB, GB\n";
    exit(0);
  }

  return(pMem_ulong);
}


/*Ignoring comment line*/
void commentIgnore(string& input)
{
  unsigned found = input.find('#');

  if (found!=std::string::npos)
   input= input.erase(found);

  else
    return;
  return;
}


void func_insert() {
 sscanf(input.c_str(), "%s = alloc(%[^)]);", t, m);
       id =t;
       id_size =m;
       cout<<"Tag: "<<id <<"  Memory: "<<id_size<<endl;
       extract(id_size); /* Separates B,MB,KB and GB of input, returns val*/
       id_size_int = atoi(id_size.c_str());
       /* Convert object size to B */
       toByte(id_size_int, val); /* return(pMem_ulong) */
       id_size_ulong = pMem_ulong;

}

void func_insert_for() {
  sscanf(input_for.c_str(), "%s = alloc(%[^)]);", t, m);
  id =t;
  id_size =m;
  if(!((id.find("[")) && (id.find("]")) != string::npos)) {
    cout<<"Tag: "<<id <<"  Memory: "<<id_size<<endl;
    extract(id_size); /* Separates B,MB,KB and GB of input, returns val*/
    id_size_int = atoi(id_size.c_str());
    /* Convert object size to B */
    toByte(id_size_int, val); /* return(pMem_ulong) */
    id_size_ulong = pMem_ulong;
    // allocate here
    return;
  }
  else {
    if(inc_str.find("++"))
      y1 =1;
    if(inc_str.find("="))
      {
    sss = inc_str.substr(inc_str.find("+") +1);
    y1 = atoi(sss.c_str());
    cout<<"y1:"<<y1<<endl;

      }
    pos_strt = id.find("[");
    pos_end = id.find("]") -1;
    cout<<"Positions start and ebd: " << pos_strt<<pos_end<<endl;
    id_dummy = id.substr(0,pos_strt);
    id = id_dummy;
    cout<<"Tag: "<<id_dummy <<"  Memory: "<<id_size<<endl;
    extract(id_size); /* Separates B,MB,KB and GB of input, returns val*/
    id_size_int = atoi(id_size.c_str());
    /* Convert object size to B */
    toByte(id_size_int, val); /* return(pMem_ulong) */
    id_size_ulong = pMem_ulong;
    //allocate here
    cout<<"v1: " << v1 << " " << v2<<endl;
    // g = 0;
    for(y = v1; y < v2; y= y+y1) {
      // allocate here
    }
  }
  return;
}

void commentIgnore_for(string& input_for)
{
  unsigned found = input_for.find('#');

  if (found!=std::string::npos)
   input_for= input_for.erase(found);

  else
    return;
  return;
}

Также я должен сделать его совместимым с пробелами. Это означает, что ввод можно вводить и в одну строку. как два выделения в одной строке. Который я не смог позаботиться. Мне нужна помощь с этим.


person Tuffy    schedule 21.05.2013    source источник
comment
Я думаю, что это лучше подходит для http://codereview.stackexchange.com/.   -  person Captain Obvlious    schedule 21.05.2013
comment
@CaptainObvlious: у меня проблема с вопросом...   -  person Mats Petersson    schedule 21.05.2013
comment
я должен сделать его совместимым с пробелами. Это означает, что ввод можно вводить и в одну строку. как два выделения в одной строке. О чем я не думаю, что позаботился. Мне нужна помощь с этим.   -  person Tuffy    schedule 21.05.2013
comment
@MatsPetersson Действительно.   -  person Captain Obvlious    schedule 21.05.2013
comment
Ваш подход довольно плохой. Гораздо лучше было бы написать функцию, которая выдает вам токен. Я напишу ответ на это.   -  person Mats Petersson    schedule 21.05.2013
comment
Да.. Это на самом деле довольно бедно. Постараюсь максимально сжать..   -  person Tuffy    schedule 21.05.2013
comment
Если вы хотите проанализировать входную текстовую строку, возможно, более организованный подход, например. на основе ANTLR или Boost Spirit было бы лучше.   -  person jogojapan    schedule 21.05.2013
comment
Почти уверен, что большая часть этого кода не имеет ничего общего с вопросом. Пожалуйста, удалите его и придумайте sscce.   -  person Peter Wood    schedule 21.05.2013
comment
На самом деле этот код считывает ввод с клавиатуры и сохраняет значения для дальнейших вычислений.   -  person Tuffy    schedule 21.05.2013
comment
Функции, которые были определены, были несколькими добавленными вещами, хотя   -  person Tuffy    schedule 21.05.2013


Ответы (2)


Мое предложение состоит в том, чтобы вы написали правильный токенизатор — фрагмент кода, который понимает, что принадлежит друг другу (например, «слова») и где разделить (например, «(, ), {, }»). Токенизатор вернет перечисление, что-то вроде этого:

enum Token {
    Token_Unknown,   // Error indiciation. 
    Token_LeftParen,
    Token_RightParen,
    Token_LeftBracket,
    Token_RightBracket,
    Token_Comma,
    Token_Semicolon, 
    Token_Equal,
    Token_Word,        // Sequence of alphanumerics
};

Когда у вас есть токен, вам нужно понять, что это за токен. Возможно, имеет смысл иметь таблицу «известных» токенов (также известных как «ключевые слова»), таких как «mem», «alloc», «for» и т. д. Если что-то не является ключевым словом, это имя символа, например переменной. Вы сохраняете их в таблице, чтобы вы могли обратиться к ним позже.

Вам придется использовать какой-то стек того места, где вы находитесь, чтобы вы могли вернуться туда, откуда пришли, когда закончите.

Написать общий синтаксический анализатор не так уж сложно, и, скорее всего, при этом вы получите намного меньше кода, чем ваш текущий код.

Конечно, вы сможете избавиться от всех:

  if(input == "#"){
    cin.clear();
    input.clear();
    getline(cin,comment);
    cin >> input;
  }

Просто позвольте синтаксическому анализатору проверить, есть ли '#' в качестве входных данных, и перейдите к концу строки (заполните текущий токен, если он у вас есть, если нет, просто продолжайте).

person Mats Petersson    schedule 21.05.2013
comment
Существуют свободно доступные инструменты, которые будут генерировать и токенизатор, и парсер; их следует использовать, а не писать все вручную. - person James Kanze; 21.05.2013
comment
И почему clear() после того, как вы увидели начало комментария? Просто пропускайте вперед, пока не увидите следующий конец строки. (Это может быть правило в токенизаторе, или вы можете вставить фильтрующий потоковый буфер во входной поток.) - person James Kanze; 21.05.2013

IIUC, ввод не ориентирован на строки, поэтому обычное правило использования std::getline может не применяться. Мой собственный подход:

  • Вставьте фильтрующий потоковый буфер, чтобы удалить комментарии.

  • Используйте какой-нибудь лексер на основе регулярных выражений (например, flex), чтобы разбить ввод на токены.

  • Дайте определение грамматике; Я бы использовал bison, как только я зашел так далеко, чтобы сгенерировать код для разбора грамматики, но простой парсер рекурсивного спуска не должен быть слишком сложным для написания.

Вы не говорите, что вы должны делать с информацией после ее анализа, поэтому трудно дать более точный совет.

person James Kanze    schedule 21.05.2013
comment
в основном, я выделяю данную физическую память и делю ее на количество поколений. когда я сталкиваюсь с alloc, я выделяю объект с памятью, указанной alloc в физической памяти. - person Tuffy; 21.05.2013
comment
В цикле for я выделяю рекурсивно. Это алгоритм сборки мусора, над которым я работаю. x1.net = x2 заставляет x1 указывать на x2. это связанный список. - person Tuffy; 21.05.2013