EXC_BAD_ACCESS в программе лотереи - PullRequest
2 голосов
/ 12 февраля 2012

У меня есть «лотерейная» программа на C ++, которую я использую для «рисования из шляпы». Я получаю сигнал EXC_BAD_ACCESS, когда пытаюсь его использовать. Вот функция:

vector<int> speedRaffle(vector<Player>players,int pNum){
    vector<int> spdtics,order;
    int ticnum,randy;
    vector<int>::iterator iter = spdtics.begin();
    for (int k=0;k<pNum;k++){
        for (int i=0; i<pNum; i++) {
            for (int j=0; j<pow(players[i].speed,2); j++){
                for (int io=0; io<order.size(); io++) {
                    if(order[io]!=i){
                        spdtics.push_back(i);
                        ticnum++;
                    }
                }
            }
        }
        randy=random() % ticnum;
        for(int i=0;i<randy;i++){
            iter++;

        }
        order[k]=*iter; //Thread 1: Program received signal: "EXC_BAD_ACCESS". 
        iter=spdtics.begin();

    }
return order;
}

Эта функция должна принимать все скорости игроков и возводить их в квадрат. Затем он помещает столько (квадраты скоростей) «лотерейных билетов» в spdtics. Затем он случайным образом вытягивает один «билет» из spdtics и приводит в порядок номер игрока, которому принадлежал билет. Затем это повторяется снова, пока все игроки не будут разыграны, не вытягивая одного и того же игрока дважды. Возвращает порядок, в котором игроки выиграли.

Класс Player содержит скорость int. Я называю эту функцию так:

order=speedRaffle(players,pNum);

, где игроки - вектор, а pNum - int. Что я делаю не так?

1 Ответ

1 голос
/ 12 февраля 2012

1.Вы пытаетесь получить доступ к элементу по индексу k в пустом векторе order

Он падает, потому что вектор order пуст при вызове order[k] = *iter;, вместо этого следует использовать функцию push_back: order.push_back(*iter);.

2.Вы используете цикл для «перемещения» итератора вместо простого advance вызова

advance(iter, randy - 1);, который имеет тот же эффект, что и этот цикл: for(int i=0;i<randy;i++){ iter++; }.

3.Вы вызываете pow в каждой отдельной итерации

for (int j=0; j<pow(players[i].speed,2); j++)

Обратите внимание, что это будет намного быстрее:

int maxspeed = pow(players[i].speed,2);
for (int j = 0; j < maxspeed; j++)

4.Доступ к элементам в векторе можно получить напрямую с помощью индекса
. В этом случае вам вообще не нужен итератор.

5.Передача вектора по значению вместо передачи по ссылке

vector<int> speedRaffle(vector<Player>players,int pNum)

Обратите внимание, что копия вектора players создается каждый раз, когда вы вызываете эту функцию.Вы не хотите этого делать.Вы также не хотите изменять этот вектор внутри функции, поэтому объявление этого аргумента как const было бы намного лучше:

vector<int> speedRaffle(const vector<Player>& players, int pNum)

6.Ваш код не делает то, что вам нужно, чтобы сделать

«Он должен взять все скорости игроков и возвести их в квадрат. Затем он складывает это количество (квадраты скоростей)»разыгрывать билеты "в spdtics". Затем он случайным образом вытягивает один "билет" из spdtics и помещает номер игрока, которому принадлежал билет, в порядок. Затем он повторяется до тех пор, пока все игроки не будут разыграны, не вытягивая одного игрока дважды.Он возвращает порядок, в котором игроки выиграли. "

В соответствии с этим ваша функция должна выглядеть следующим образом:

vector<int> speedRaffle(vector<Player>& players)
{
    // create vector of tickets:
    set<int> ticketOwners;
    vector<int> spdtics;
    for (int i = 0; i < players.size(); i++)
    {
        ticketOwners.insert(i);
        int maxspeed = pow(players[i].speed,2);
        for (int j = 0; j < maxspeed; j++)
        {
            spdtics.push_back(i);
        }
    }
    // draw ticket for every player:
    vector<int> order;
    while (!ticketOwners.empty())
    {
        set<int>::const_iterator to;
        int randy;
        do
        {
            randy = random() % spdtics.size();
            to = ticketOwners.find(spdtics[randy]);
        }
        while (to == ticketOwners.end());
        spdtics.erase(spdtics.begin() + randy);
        order.push_back(*to);
        ticketOwners.erase(to);
    }
    return order;
}

Также обратите внимание, что вам не нужно pNum аргумент, если он равен players.size().

Надеюсь, это поможет вам.

...