`std::find()` 使用字符串产生奇怪的结果
`std::find()` producing weird results with strings
我有一项大学作业是为给定的假设指令集编写汇编程序。我已经实现了它,当我调试时,我实现的 std::find()
函数给出了奇怪的结果。请帮忙。
#include <bits/stdc++.h>
//imperative keywords
std::list<std::string> Mn_imp = { "READ","PRINT","MOVER","MOVEM","ADD","SUB","MUL","DIV" };
//declarative keywords
std::list<std::string> Mn_dcl = { "DS","DS" };
//assembler directives
std::list<std::string> Mn_drc = { "START","STOP","LTORG","EQU" };
struct Row {
std::string name;
long LC_val;
Row(std::string _name, long LC) : name(_name), LC_val(LC) { }
bool operator==(const Row& row) {
return ((this->name == row.name) && (this->LC_val == row.LC_val));
}
};
long LOCCTR = 0;
std::vector<Row> SYMTAB;
std::vector<Row> LITTAB;
std::vector<int> POOLTAB;
std::string getToken(std::string& buffer) {
std::string retToken;
int i = 0;
while (1) {
if (i == buffer.size()) {
buffer.clear();
break;
}
else if (buffer[i] == ' ' || buffer[i] == ',') {
i++;
std::string newString(buffer.begin() + i, buffer.end());
buffer.clear();
buffer = newString;
break;
}
retToken += buffer[i];
i++;
}
return retToken += '[=10=]';
}
bool getNumber(char* str, long* num_ptr) {
bool flag = false;
int i = 0;
*num_ptr = 0;
char ch = ' ';
while (ch != '[=10=]') {
ch = *(str + i);
if (ch >= '0' && ch <= '9') {
*num_ptr = (*num_ptr) * 10 + (long)(ch - 48);
flag = true;
}
i++;
}
return flag;
}
short process_imp(std::vector<std::string> statement) {
auto isRegister = [](const std::string& token) {
return (token == "AREG" || token == "BREG" || token == "CREG" || token == "DREG");
};
auto find = [](std::string str, char c) {
for (const auto& ch : str) {
if (ch == c) {
return true;
}
}
return false;
};
//first argument
if (!isRegister(statement[1])) {
if (find(statement[1], '=')) { //isLiteral
if (std::find(LITTAB.begin(), LITTAB.end(), Row(statement[1], -1)) != LITTAB.end()) { //check for presence
LITTAB.push_back(Row(statement[1], -1));
}
}
else if (statement[1][1] == 'F') { //isNumber
long number = 0;
getNumber(const_cast<char*>(statement[1].c_str()), &number);
}
else { //isVariable
for (const auto& row : SYMTAB) {
if (row.name == statement[1]) {
return 0;
}
}
SYMTAB.push_back(Row(statement[1], -1));
return 0;
}
}
//second argument
if (!isRegister(statement[2])) {
if (find(statement[2], '=')) { //isLiteral
if (std::find(LITTAB.begin(), LITTAB.end(), Row(statement[2], -1)) != LITTAB.end()) { //check for presence
LITTAB.push_back(Row(statement[2], -1));
}
}
else if (statement[2][1] == 'F') { //isNumber
long number = 0;
getNumber(const_cast<char*>(statement[2].c_str()), &number);
}
else { //isVariable
for (auto& row : SYMTAB) {
if (row.name == statement[2]) {
return 0;
}
}
SYMTAB.push_back(Row(statement[2], -1));
return 0;
}
}
return 0;
}
short process_drc(std::vector<std::string> statement) {
if (statement.front() == std::string("START")) {
if (statement.size() > 1) {
getNumber(const_cast<char*>(statement[1].c_str()), &LOCCTR);
}
}
else if (statement.front() == std::string("LTORG")) {
int i = POOLTAB.back();
for (; i < LITTAB.size(); i++) {
LITTAB[i].LC_val = LOCCTR++;
}
POOLTAB.push_back(LITTAB.size());
}
else if (statement.front() == std::string("EQU")) {
for (auto& row : SYMTAB) {
if (row.name == statement[0]) {
for (auto& _row : SYMTAB) {
if (_row.name == statement[2]) {
row.LC_val = _row.LC_val;
return 0;
}
}
}
}
}
else if (statement.front() == "STOP") {
return 1;
}
}
short process_dcl(std::vector<std::string> statement) {
for (auto& row : SYMTAB) {
if (row.name == statement[0]) {
row.LC_val = LOCCTR++;
return 0;
}
}
SYMTAB.push_back(Row(statement[0], LOCCTR));
LOCCTR++;
return 0;
}
int process_line(std::string line) {
auto find = [](std::list<std::string> list, std::string str) { //could have used std::find()
for (const auto& var : list) {
if (std::string(var) == str) {
return true;
}
}
return false;
};
int retVal = 0;
std::vector<std::string> token_vec;
while (line != "") {
token_vec.push_back(getToken(line));
}
//start processing the tokenised array
auto token = token_vec.begin();
std::string tok = token_vec.front();
//pop the label
if (tok[tok.size() - 1] == ':') {
SYMTAB.push_back(Row(tok, LOCCTR));
token_vec.pop_back();
}
//find the type of statement
unsigned short type = 0;
if (std::find(Mn_imp.begin(), Mn_imp.end(), tok) != Mn_imp.end()) {
type = 1;
}
else if (std::find(Mn_drc.begin(), Mn_drc.end(), tok) != Mn_drc.end()) {
type = 2;
}
else {
type = 3;
}
switch (type) {
case 1: //imperative statement
retVal = process_imp(token_vec);
break;
case 2: //assembler directive
retVal = process_drc(token_vec);
break;
case 3: //declarative statement
retVal = process_dcl(token_vec);
break;
//default: (not needed)
}
return retVal;
}
int main(int argc, const char** argv) {
std::vector<std::string> code;
std::ifstream infile;
infile.open(argv[1]);
while (!infile.eof()) {
std::string str;
std::getline(infile, str);
code.push_back(str);
}
infile.close();
//Now we have the code in a string vector
//check for a proper end
if (code.back() != "STOP") {
std::cerr << "Where do I stop?? Perhaps you forgot to put an end (STOP) statement?\n";
return -1;
}
//if code is proper then begin pass1
for (int i = 0; ; i++) {
auto line = code[i];
short success = process_line(line);
if (success == -1) {
std::cerr << "Something wrong at line number " << i + 1 << std::endl;
break;
}
else if (success == 0) {
//silence is golden :P
}
else if (success == 1) {
std::cout << "Pass1 completed successfully :)" << std::endl;
break;
}
}
return 0;
}
奇怪的结果是指在 stl 字符串 class 中重载的运算符 == 似乎不起作用。问题是,我尝试编写自己的查找函数:
lambda 函数:
for(auto& item : list) {
if (item == str) //str was passed to this lambda function
{ printf("purr"); }
}
即使 item
和 str
相等,它也没有进入,正如调试器显示的那样
喜欢,std::find,它总是去 type = 3
您在解析时向标记添加了一个空字符:
return retToken += '[=10=]';
这个字符在调试器中是不可见的,这意味着它看起来像是在比较,例如,"AREG"
和 "AREG"
而实际上是在比较 "AREG"
and "AREG[=14=]"
.
这些是不相等的;它们的长度甚至都不一样。
去掉不必要的空字符。
(可能还有其他错误,但这应该有望解决您的比较问题。)
我有一项大学作业是为给定的假设指令集编写汇编程序。我已经实现了它,当我调试时,我实现的 std::find()
函数给出了奇怪的结果。请帮忙。
#include <bits/stdc++.h>
//imperative keywords
std::list<std::string> Mn_imp = { "READ","PRINT","MOVER","MOVEM","ADD","SUB","MUL","DIV" };
//declarative keywords
std::list<std::string> Mn_dcl = { "DS","DS" };
//assembler directives
std::list<std::string> Mn_drc = { "START","STOP","LTORG","EQU" };
struct Row {
std::string name;
long LC_val;
Row(std::string _name, long LC) : name(_name), LC_val(LC) { }
bool operator==(const Row& row) {
return ((this->name == row.name) && (this->LC_val == row.LC_val));
}
};
long LOCCTR = 0;
std::vector<Row> SYMTAB;
std::vector<Row> LITTAB;
std::vector<int> POOLTAB;
std::string getToken(std::string& buffer) {
std::string retToken;
int i = 0;
while (1) {
if (i == buffer.size()) {
buffer.clear();
break;
}
else if (buffer[i] == ' ' || buffer[i] == ',') {
i++;
std::string newString(buffer.begin() + i, buffer.end());
buffer.clear();
buffer = newString;
break;
}
retToken += buffer[i];
i++;
}
return retToken += '[=10=]';
}
bool getNumber(char* str, long* num_ptr) {
bool flag = false;
int i = 0;
*num_ptr = 0;
char ch = ' ';
while (ch != '[=10=]') {
ch = *(str + i);
if (ch >= '0' && ch <= '9') {
*num_ptr = (*num_ptr) * 10 + (long)(ch - 48);
flag = true;
}
i++;
}
return flag;
}
short process_imp(std::vector<std::string> statement) {
auto isRegister = [](const std::string& token) {
return (token == "AREG" || token == "BREG" || token == "CREG" || token == "DREG");
};
auto find = [](std::string str, char c) {
for (const auto& ch : str) {
if (ch == c) {
return true;
}
}
return false;
};
//first argument
if (!isRegister(statement[1])) {
if (find(statement[1], '=')) { //isLiteral
if (std::find(LITTAB.begin(), LITTAB.end(), Row(statement[1], -1)) != LITTAB.end()) { //check for presence
LITTAB.push_back(Row(statement[1], -1));
}
}
else if (statement[1][1] == 'F') { //isNumber
long number = 0;
getNumber(const_cast<char*>(statement[1].c_str()), &number);
}
else { //isVariable
for (const auto& row : SYMTAB) {
if (row.name == statement[1]) {
return 0;
}
}
SYMTAB.push_back(Row(statement[1], -1));
return 0;
}
}
//second argument
if (!isRegister(statement[2])) {
if (find(statement[2], '=')) { //isLiteral
if (std::find(LITTAB.begin(), LITTAB.end(), Row(statement[2], -1)) != LITTAB.end()) { //check for presence
LITTAB.push_back(Row(statement[2], -1));
}
}
else if (statement[2][1] == 'F') { //isNumber
long number = 0;
getNumber(const_cast<char*>(statement[2].c_str()), &number);
}
else { //isVariable
for (auto& row : SYMTAB) {
if (row.name == statement[2]) {
return 0;
}
}
SYMTAB.push_back(Row(statement[2], -1));
return 0;
}
}
return 0;
}
short process_drc(std::vector<std::string> statement) {
if (statement.front() == std::string("START")) {
if (statement.size() > 1) {
getNumber(const_cast<char*>(statement[1].c_str()), &LOCCTR);
}
}
else if (statement.front() == std::string("LTORG")) {
int i = POOLTAB.back();
for (; i < LITTAB.size(); i++) {
LITTAB[i].LC_val = LOCCTR++;
}
POOLTAB.push_back(LITTAB.size());
}
else if (statement.front() == std::string("EQU")) {
for (auto& row : SYMTAB) {
if (row.name == statement[0]) {
for (auto& _row : SYMTAB) {
if (_row.name == statement[2]) {
row.LC_val = _row.LC_val;
return 0;
}
}
}
}
}
else if (statement.front() == "STOP") {
return 1;
}
}
short process_dcl(std::vector<std::string> statement) {
for (auto& row : SYMTAB) {
if (row.name == statement[0]) {
row.LC_val = LOCCTR++;
return 0;
}
}
SYMTAB.push_back(Row(statement[0], LOCCTR));
LOCCTR++;
return 0;
}
int process_line(std::string line) {
auto find = [](std::list<std::string> list, std::string str) { //could have used std::find()
for (const auto& var : list) {
if (std::string(var) == str) {
return true;
}
}
return false;
};
int retVal = 0;
std::vector<std::string> token_vec;
while (line != "") {
token_vec.push_back(getToken(line));
}
//start processing the tokenised array
auto token = token_vec.begin();
std::string tok = token_vec.front();
//pop the label
if (tok[tok.size() - 1] == ':') {
SYMTAB.push_back(Row(tok, LOCCTR));
token_vec.pop_back();
}
//find the type of statement
unsigned short type = 0;
if (std::find(Mn_imp.begin(), Mn_imp.end(), tok) != Mn_imp.end()) {
type = 1;
}
else if (std::find(Mn_drc.begin(), Mn_drc.end(), tok) != Mn_drc.end()) {
type = 2;
}
else {
type = 3;
}
switch (type) {
case 1: //imperative statement
retVal = process_imp(token_vec);
break;
case 2: //assembler directive
retVal = process_drc(token_vec);
break;
case 3: //declarative statement
retVal = process_dcl(token_vec);
break;
//default: (not needed)
}
return retVal;
}
int main(int argc, const char** argv) {
std::vector<std::string> code;
std::ifstream infile;
infile.open(argv[1]);
while (!infile.eof()) {
std::string str;
std::getline(infile, str);
code.push_back(str);
}
infile.close();
//Now we have the code in a string vector
//check for a proper end
if (code.back() != "STOP") {
std::cerr << "Where do I stop?? Perhaps you forgot to put an end (STOP) statement?\n";
return -1;
}
//if code is proper then begin pass1
for (int i = 0; ; i++) {
auto line = code[i];
short success = process_line(line);
if (success == -1) {
std::cerr << "Something wrong at line number " << i + 1 << std::endl;
break;
}
else if (success == 0) {
//silence is golden :P
}
else if (success == 1) {
std::cout << "Pass1 completed successfully :)" << std::endl;
break;
}
}
return 0;
}
奇怪的结果是指在 stl 字符串 class 中重载的运算符 == 似乎不起作用。问题是,我尝试编写自己的查找函数:
lambda 函数:
for(auto& item : list) {
if (item == str) //str was passed to this lambda function
{ printf("purr"); }
}
即使 item
和 str
相等,它也没有进入,正如调试器显示的那样
喜欢,std::find,它总是去 type = 3
您在解析时向标记添加了一个空字符:
return retToken += '[=10=]';
这个字符在调试器中是不可见的,这意味着它看起来像是在比较,例如,"AREG"
和 "AREG"
而实际上是在比较 "AREG"
and "AREG[=14=]"
.
这些是不相等的;它们的长度甚至都不一样。
去掉不必要的空字符。
(可能还有其他错误,但这应该有望解决您的比较问题。)