我一直在为我的命令行项目做一个简单的解释器,然而我最近偶然发现了一个问题,我不知道原因。
下面是代码:
// cls.h
#pragma once
#include <iostream>
#include <string>
#include <iomanip>
enum id {undef, kwd, idt, opr, val}; // Ignore idt
extern std::string keywords[]; // Declaring the keywords array
extern std::string operators[]; // Declaring the operators array
class Token
{
id ID;
std::string value;
public:
Token() {
ID = undef;
value = "";
}
void SetID(id ID) {
this->ID = ID;
}
void SetValue(std::string value) {
this->value = value;
}
id GetID() {
return ID;
}
std::string GetValue() {
return value;
}
};
std::string UserInput();
void Lexical(Token *token, int nstr, std::string str, int ntok);
// cls.cpp
#include <iostream>
// Definitions of the keywords and operators arrays
std::string keywords[] = {
"echo",
"exit"
};
std::string operators[] = {
"+",
"-",
"/",
"%"
};
// input.cpp
#include "cls.h"
std::string UserInput() // Function to take user's input
{
std::string input;
std::getline(std::cin, input);
return input;
}
// lex.cpp
#include "cls.h"
// To check whether a token is a keyword
static bool aKeyword(std::string str)
{
for (int i = 0; i < 10; i++) {
if (keywords[i] == str)
return true;
}
return false;
}
// To check whether a token is an operator
static bool aOperator(std::string str)
{
for (int i = 0; i < 10; i++) {
if (operators[i] == str)
return true;
}
return false;
}
void Lexical(Token *token, int ntok, std::string str, int nstr)
{
// Working the tokens' values
int idx = 0;
bool fspace = false;
std::string plh[256];
for (int i = 0; i < nstr; i++) {
if ((str.at(i) == ' ') && (fspace == false)) {
idx++;
fspace = true;
continue;
} else
if ((str.at(i) == ' ') && (fspace == true)) {
continue;
}
plh[idx].append(&(str.at(i)), 1);
fspace = false;
}
for (int i = 0; i < ntok; i++) {
(token + i)->SetValue(plh[i]);
}
// Working the tokens' IDs
// Checking whether a token is a keyword, an operator or a value
for (int i = 0; i < ntok; i++) {
if (aKeyword((token + i)->GetValue()) == true) {
(token + i)->SetID(kwd);
} else
if (aOperator((token + i)->GetValue()) == true) { // <--- The problem
(token + i)->SetID(opr);
} else {
(token + i)->SetID(val);
}
}
}
// init.cpp
#include "cls.h"
int main()
{
std::string usinput;
Token token[256];
std::cout << "User input: ";
usinput = UserInput(); // Taking user's input
Lexical(token, 256, usinput, (int) usinput.size()); // Calling the lexical function
// Outputting the tokens' values and IDs (The IDs is in the parentheses)
for (int i = 0; i < 10; i++) {
std::cout << "Token[" << i << "] = "
<< token[i].GetValue()
<< std::setfill(' ')
<< std::setw(15 - (token[i].GetValue()).size())
<< "(" << token[i].GetID() << ")"
<< std::endl;
}
return 0;
}
字符串
当Lexical函数尝试使用ID的关键字(kwd)、运算符(opr)或值(val)检查和分类标记时,问题出现在Lexical函数中。
enum id {undef, kwd, idt, opr, val};
型
很明显opr的值应该是3(表示运算符),但是当我试着运行程序并看到输出时,它给出的值是1(表示关键字)
benanthony@DESKTOP-QI9Q4LV:~/codes/CLine$ make
g++ init.cpp lex.cpp input.cpp cls.cpp -Wall -Wextra -o CLine
benanthony@DESKTOP-QI9Q4LV:~/codes/CLine$ ./CLine
User input: Hello there + - Rand - Lett - echo yes
Token[0] = Hello (4)
Token[1] = there (4)
Token[2] = + (1)
Token[3] = - (1)
Token[4] = Rand (4)
Token[5] = - (1)
Token[6] = Lett (4)
Token[7] = - (1)
Token[8] = echo (1)
Token[9] = yes (4)
型
token[2]、token[3]、token[5]和token[7]中的+和-应该具有ID值3。
我试着通过改变ID的名称来解决这个问题,但它仍然不起作用。
这道题看起来很简单,但我还是不知道该怎么做。是我遗漏了什么,还是我犯了什么错误?
1条答案
按热度按时间xtfmy6hx1#
这个问题是由
aKeyword
和aOperator
方法中的Undefined Behaviour引起的。你正在比较数组i < 10
之外的字符串,如果你修复这些,你会得到预期的结果:字符串