Char数组到数学方程

时间:2016-03-16 08:08:52

标签: c arrays parsing

我正在尝试从给定的char数组中解析出数学方程式,例如char equation[255] = "4+4";我希望将第一个数字复制到long number1,将运算符复制到char oper,将第二个数字复制到long number2 {1}}。

我已经尝试了sscanf(equation, "%d%c%d", &number1, &oper, &number2);,但它只获得了第一个号码而无法提取运营商和第二个号码。

尝试过这种方法:

while (isdigit(equation[k]))
    {
        k++;
    }                   
oper = equation[k];

仍然没有得到运营商。有没有更简单的方法来解析c ++中的方程?

2 个答案:

答案 0 :(得分:7)

将其转换为MCVE ...

return "user?add";

...给出...

#include <stdio.h>

int main()
{
    char * equation = "4+4";
    long number1, number2;
    char oper;
    int rc = sscanf( equation, "%d%c%d", &number1, &oper, &number2 );
    printf( "%d\n", rc );
    if ( rc == 3 )
    {
        printf( "%d - %c - %d\n", number1, oper, number2 );
    }
    return 0;
}

按预期工作。 投票结束问题,请阅读我在回答开始时提供的链接。

此外:

  • How to read / parse input in C?,各节:
    • 不要将* scanf()用于可能格式错误的输入
    • 当* scanf()无法按预期工作时(如果输入字符串包含空格)

如果你实际上希望使用C ++(如原始标记所示),则需要Boost.Spirit来解析你的需求。

答案 1 :(得分:3)

如果你想在C ++中编写一个简单的lexer,我可以在这里修改math-expr-lexer.cpp(作者:Dmitry Soshnikov),使其适用于MS Windows操作系统。

#include <iostream>
#include <vector>
#include <ctype.h>
#include <cstring>

#define NL std::endl   

class Lexer {

private:
    char* m_source;
    int   m_sourceLength;
    int   m_cursor;
    char  m_currentChar;

    void  readNextChar();
    void  skipWhiteSpaces();
    char* readNumber();
    char* readSymbol();

public:
    Lexer(char* source);

    bool isEOF();
    char* readNextToken();
    static std::vector<char*> tokenize(char*);
};

// ---------------------------------
// Lexer implementation.
// ---------------------------------

Lexer::Lexer(char* source) {
    m_source = source;
    m_sourceLength = strlen(source);
    m_cursor = 0;

    readNextChar();
}

bool Lexer::isEOF() {
    return m_cursor > m_sourceLength;
}

/**
 * Reads next char advancing cursor.
 */
void Lexer::readNextChar() {
    skipWhiteSpaces();

    if (isEOF()) {
        m_currentChar = '\0';
        return;
    }

    m_currentChar = m_source[m_cursor++];
}

/**
 * Reads next token: a number or a symbol.
 */
char* Lexer::readNextToken() {
    if (isdigit(m_currentChar))
        return readNumber();

    return readSymbol();
}

/**
 * Reds a number containing digits.
 */
char* Lexer::readNumber() {
    char* number = new char[20];
    int i = 0;
    while (isdigit(m_currentChar)) {
        number[i++] = m_currentChar;
        readNextChar();
    }
    number[i] = '\0';
    return number;
}

/**
 * Reads a symbol (operator or grouping).
 */
char* Lexer::readSymbol() {
    char* symbol = new char[2];
    symbol[0] = m_currentChar;
    symbol[1] = '\0';
    readNextChar();
    return symbol;
}

void Lexer::skipWhiteSpaces() {
    while (isspace(m_source[m_cursor]))
        m_cursor++;
}

/**
* Tokenizes a source expression, returns
* a vector with the tokens.
*/
std::vector<char*> Lexer::tokenize(char* source) {
    std::vector<char*> tokens;
    Lexer lexer(source);
    do {
        tokens.push_back(lexer.readNextToken());
    } while (!lexer.isEOF());
    return tokens;
}

void printTokens(std::vector<char*> tokens) {
    std::cout << "Tokens: [";
    unsigned int size = tokens.size();
    for (unsigned int k = 0; k < size; k++) {
        std::cout << '"' << tokens[k] << '"';
        if (k < size - 1) std::cout << ", ";
    }
    std::cout << "]" << NL << NL;
}

int main()
{ 
    char* expression = new char[100];
    std::cout << "Enter expression: ";
    std::cin.getline(expression, 100);
    printTokens(Lexer::tokenize(expression));
    return 0;
}