`std :: find ()` выдаёт странные результаты со строками - PullRequest
1 голос
/ 11 апреля 2020

У меня есть задание колледжа написать ассемблер для данного гипотетического набора инструкций. Я реализовал это, и когда я отлаживаю, реализованная мной функция 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, похоже, не работает. Дело в том, что я пытался написать свою собственную функцию поиска:

лямбда-функция:

for(auto& item : list) {
    if (item == str)         //str was passed to this lambda function
    { printf("purr"); }
}

она никогда не входила, даже если item и str были равны, как отладчик показал

Как и в случае с std :: find, он всегда идет к type = 3

1 Ответ

1 голос
/ 11 апреля 2020

Вы добавляете нулевой символ в токены при разборе:

return retToken += '\0';

Этот символ невидим в отладчике, что означает, что, похоже, вы сравниваете, например, "AREG" и "AREG" когда вы на самом деле сравниваете "AREG" и "AREG\0".
И они не равны; они даже не одинаковой длины.

Избавьтесь от ненужного нулевого символа.

(Возможно, есть и другие ошибки, но, надеюсь, это должно исправить проблему сравнения.)

...