Char указатели и строки через ifstream - PullRequest
1 голос
/ 24 марта 2011

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

Анализатор с использованием аргументов командной строки:

#include <iostream>
#include <fstream>

using namespace std;

bool A(void);
bool E(void);
bool T(void);
bool F(void);
bool P(void);
bool I(void);
bool L(void);

char *c;

int main(int argc, char *argv[]){

    c = argc == 2 ? argv[1] : (char *)"";

    if (A() && *c == '\0') {
        cout << "The string \"" << argv[1] << "\" is in the language." << endl;
    }
    else {
        cout << "The string \"" << argv[1] << "\" is not in the language." << endl;
    }

    return 0;
}

bool A(void){

    if( I() )
    {
        if ( *c == '=' ){
            ++c;
            if ( E() )
            return true;
        }
    }
    return false;
}

bool E(void){

    if( T() ){
        if ( *c == '+' || *c == '-' ){
                ++c;
                return E();
        }
        return true;
    }
    return false;
}

bool F(void){

    if( P() ){
        if( *c == '^'){
            ++c;
            return F();
        }
    return true;
    }
    return false;
}

bool I(void){

    if ( *c >= 'a' && *c <= 'z'){
        ++c;
        return true;
    }
    return false;
}

bool L(void){

    if ( *c >= '0' && *c <= '9' ){
        ++c;
        return true;
    }
    return false;
}

bool P(void){

    if ( I() ){
        return true;
    }
    else
    if ( L() ){
        return true;
    }
    else
    if ( *c == '(' ){
            ++c;
            if ( E() ){
                    if ( *c == ')' ){
                        ++c;
                        return true;
                    }
            }
    }
    return false;
}

bool T(void){

    if( F() ){
        if ( *c == '*' || *c == '/' ){
                ++c;
                return T();
        }
        return true;
    }
    return false;
}

Я не знаю, чем можно заменить argv [1] для печати строки. Чтобы получить правильный указатель на символ, я могу просто сделать это?

ifstream fin("input.dat");
        while (fin >> *c)

когда я пытаюсь получить ошибку сегментации.

Ответы [ 2 ]

0 голосов
/ 24 марта 2011

Предполагая, что ваш файл является текстовым файлом с одной записью для разбора на строку, вы можете сделать это:

ifstream fin("input.dat")
if (fin.is_open())
{
    std::string line;
    while (fin.good())
    {
       getline(fin, line);
       c = line.c_str();
       ... go and parse c
    }
}

Обновление : очевидно, c неконстантно, поэтому используйтеc_str() не будет так просто работать.У вас есть два варианта:

  1. Изменить ваш анализатор для работы с std :: string (используйте индекс для указания на текущий символ).
  2. Выделите немного памяти и скопируйте c_str() там.

Вероятно, номер 1 - лучший способ.

0 голосов
/ 24 марта 2011

Вы просите поток сохранить значение в том, что представлено значением, на которое указывает c. Вместо этого рассмотрим:

char ch;
char *c = &ch;

ifstream fin("input.dat");
while (fin >> ch) {
    // whatever
}

Это не приведет к немедленной ошибке. Однако на следующей итерации могут произойти плохие вещи, если вы измените значение c внутри функций синтаксического анализа.

Вам необходимо реструктурировать программу и абстрагироваться от намерения прочитать следующий символ из метода чтения следующего символа (путем увеличения указателя или чтения из потока или что угодно).

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

...