简体   繁体   English

C ++使用find_first_not_of(char *)删除矢量元素

[英]C++ Removing vector elements with find_first_not_of(char*)

I'm making a chess game and trying to add valid positions to a vector. 我正在做一个国际象棋游戏,试图向向量添加有效位置。 The specific piece I'm working on is the knight, and some of the positions I've hardcoded are off the board, depending on the knight's position on the board. 我正在处理的特定部分是骑士,而我已经硬编码的某些位置不在板上,这取决于骑士在板上的位置。 My coordinate system uses AH for rows and 0-8 for columns. 我的坐标系将AH用于行,将0-8用于列。

I have defined a character array of valid characters (AH and 0-8) and I'm using find_first_not_of to identify, and remove coordinate pairs that are invalid. 我已经定义了一个有效字符(AH和0-8)的字符数组,并且正在使用find_first_not_of进行标识,并删除无效的坐标对。 For example: 例如:

Valid: A1 有效:A1

Invalid: ?3 - remove this 无效:?3-删除此

Question: Why is it that my function removes some coordinate pairs that are invalid and don't fit the pattern, but not others? 问题:为什么我的函数会删除一些无效且不适合该模式的坐标对,而不会删除其他坐标对? For example, using position A2 as input, @4 and @0 are successfully removed. 例如,使用位置A2作为输入,可以成功删除@ 4和@ 0。 However the remaining available positions are C3, C1, B4, ?3, B0, ?1. 然而,剩余的可用位置是C3,C1,B4,θ3,B0,θ1。

If the input is H2, then F3, F1, G0, G4 are available positions and J3, J1, I4, I0 are successfully removed, giving the desired result of only valid positions. 如果输入为H2,则F3,F1,G0,G4是可用位置,并且J3,J1,I4,I0被成功删除,仅给出了有效位置的期望结果。

Problem: My output is correct some of the time and incorrect other times given the same method of removing invalid positions. 问题:给定相同的删除无效头寸的方法,我的输出有时是正确的,而其他时候是不正确的。

Parent class Piece.cpp: 父类Piece.cpp:

char Piece::valids[16] = {
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
    '0', '1', '2', '3', '4', '5', '6', '7'
 };

void Piece::removeInvalids(vector<string>& v)
{
    for (short i = 0; i < v.size(); i++)
    {
        string s = v.at(i);
        size_t found = s.find_first_not_of(valids);
        if (found != string::npos)
        {
            cout << v.at(i) << endl;
            swap(v.at(i), v.back());
            v.pop_back();
        }
    }
}

Child class Knight.h: 子类别Knight.h:

vector<string> getAvailPositions(Piece **all)
{
    vector<string> v;
    stringstream ss;
    ss << static_cast<char>(position[0] + 2)
            << static_cast<char>(position[1] + 1);
    v.push_back(ss.str());
    stringstream ss2;
    ss2 << static_cast<char>(position[0] + 2)
            << static_cast<char>(position[1] - 1);
    v.push_back(ss2.str());
    stringstream ss3;
    ss3 << static_cast<char>(position[0] + 1)
            << static_cast<char>(position[1] + 2);
    v.push_back(ss3.str());
    stringstream ss4;
    ss4 << static_cast<char>(position[0] - 1)
            << static_cast<char>(position[1] + 2);
    v.push_back(ss4.str());
    stringstream ss5;
    ss5 << static_cast<char>(position[0] + 1)
            << static_cast<char>(position[1] - 2);
    v.push_back(ss5.str());
    stringstream ss6;
    ss6 << static_cast<char>(position[0] - 1)
            << static_cast<char>(position[1] - 2);
    v.push_back(ss6.str());
    stringstream ss7;
    ss7 << static_cast<char>(position[0] - 2)
            << static_cast<char>(position[1] - 1);
    v.push_back(ss7.str());
    stringstream ss8;
    ss8 << static_cast<char>(position[0] - 2)
            << static_cast<char>(position[1] + 1);
    v.push_back(ss8.str());
    removeInvalids(v);
    return v;
}

Please let me know if any changes to this post should be made for you to better assist me, thank you. 请让我知道是否需要对此职位进行任何更改,以便更好地为我提供帮助,谢谢。

You should rethink your design--it's complicated and inefficient. 您应该重新考虑您的设计-它是复杂且低效的。 How about this: 这个怎么样:

typedef std::array<char, 2> Position;

vector<Position> Knight::getAvailPositions() const
{
    vector<Position> v;
    v.reserve(8);
    for (char a : {2, -2}) {
        for (char b : {1, -1}) {
            v.emplace_back(position[0] + a, position[1] + b);
            v.emplace_back(position[0] + b, position[1] + a);
        }
    }
    removeInvalids(v);
    return v;
}

bool invalid(Position p)
{
    return p[0] < 'A' || p[0] > 'H' || p[1] < '0' || p[1] > '7';
}

void Piece::removeInvalids(vector<Position>& v)
{
    v.erase(std::remove_if(v.begin(), v.end(), invalid), v.end());
}

This avoids an absolute ton of dynamic memory allocations that were hiding inside all those strings & stringstreams. 这避免了隐藏在所有这些字符串和字符串流内部的绝对大量的动态内存分配。 Now you have just one per getAvailPositions() call. 现在,每个getAvailPositions()调用只有一个。 Plus it's less code. 加上更少的代码。

The reason it's only correct sometimes is because you're swapping the current vector element with the element at the end and then moving on to the next element. 有时它只是正确的原因是因为您将当前向量元素与结尾的元素交换,然后继续进行下一个元素。 If the element at the end of the vector was invalid, you were just slipping an invalid into the middle of your vector and skipping it. 如果向量结尾处的元素无效,则只是将一个无效值滑入向量的中间并跳过它。

In your example, when it removes @4, it pulls ?3 into the middle of the vector and then moves on to looking at b0, without ever even questioning ?3. 在您的示例中,当它删除@ 4时,它将?3拉到向量的中间,然后继续看b0,甚至都没有质疑过?3。 You will want to rework your logic of removing the element from the middle of the vector if you want to keep using the code the way you are now. 如果您想继续使用现在的代码,则需要重新设计从向量中间删除元素的逻辑。

Although, as has been pointed out by other answers, there are more efficient ways of writing this code. 尽管,正如其他答案所指出的那样,还有更有效的方式编写此代码。

DR you are correct about my code, this seems to solve the problem by adding this one line: DR,您对我的代码是正确的,这似乎可以通过添加以下这一行来解决问题:

void Piece::removeInvalids(vector<string>& v)
{
    for (short i = 0; i < v.size(); i++)
    {
        string s = v.at(i);
        size_t found = s.find_first_not_of(valids);
        if (found != string::npos)
        {
            cout << v.at(i) << endl;
            swap(v.at(i), v.back());
            v.pop_back();
            i = 0;
        }
    }
}

to make it restart the loop. 使它重新启动循环。 I'm going to keep it this way for now because I have until June 2nd to finish this project and document it lol. 我将暂时保留这种方式,因为我必须在6月2日之前完成该项目并将其记录下来。 I'm sure my teacher will explain as a learning experience to the class how awful it is, but we have not talked in much depth about performance yet, that will be the focus of the next course I take on C++. 我确定我的老师会向全班解释作为学习经历,这是多么的糟糕,但是我们还没有深入讨论性能问题,这将是我学习C ++下一门课程的重点。 I can modify this program when I take CSC-17C and tune the performance. 当我使用CSC-17C并调整性能时,可以修改此程序。

Thank you all for your quick responses! 谢谢大家的快速回复!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM