我正在尝试从给定的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 ++中的方程?
答案 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;
}
按预期工作。 投票结束问题,请阅读我在回答开始时提供的链接。
此外:
如果你实际上希望使用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;
}