`std::find()` 用字符串产生奇怪的结果
Posted
技术标签:
【中文标题】`std::find()` 用字符串产生奇怪的结果【英文标题】:`std::find()` producing weird results with strings 【发布时间】:2020-04-11 09:31:18 【问题描述】:我的大学作业是为给定的假设指令集编写汇编程序。我已经实现了它,当我调试时,我实现的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 += '\0';
bool getNumber(char* str, long* num_ptr)
bool flag = false;
int i = 0;
*num_ptr = 0;
char ch = ' ';
while (ch != '\0')
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 字符串类中重载的 operator== 似乎不起作用。问题是,我尝试编写自己的查找函数:
lambda 函数:
for(auto& item : list)
if (item == str) //str was passed to this lambda function
printf("purr");
即使 item
和 str
相等,它也从未进入,正如调试器显示的那样
就像 std::find 一样,它总是转到 type = 3
【问题讨论】:
请比“给出奇怪的结果”更具体。您预计会发生什么,实际会发生什么? 非常注意=
和==
之间的区别。
***.com/a/31816096/430766
@bitmask,是的,我知道。完成代码后,我通常将其替换为标题。非常感谢。这种习惯实际上源于竞争性编码。????
我能够以某种方式摆脱写using namespace std
的烦人习惯。这个习惯也会过去:)
【参考方案1】:
您在解析时向标记添加了一个空字符:
return retToken += '\0';
这个字符在调试器中是不可见的,这意味着它看起来像是在比较 "AREG"
和 "AREG"
而实际上是在比较 "AREG"
和 "AREG\0"
。
这些是不相等的;它们的长度甚至都不一样。
去掉不必要的空字符。
(可能还有其他错误,但这应该可以解决您的比较问题。)
【讨论】:
叫做debuggin:ericlippert.com/2014/03/05/how-to-debug-small-programs以上是关于`std::find()` 用字符串产生奇怪的结果的主要内容,如果未能解决你的问题,请参考以下文章