0

I was writing a program for homework.

It's about simulating two people playing a card game.

At first, Mr.Y has n cards while Mr.P has m cards and the cards they have are unique.

Mr.Y plays first, and here's how you play the game:

  • First, you pick a number x, if the number is among the cards of your competitor, you take it.
  • Then, if you already have the card you got, you throw both the card on your hand and the card you just got.
  • Then, your competitor does the same thing (he picks a number w).

That's the end of the first round.

The game ends when one of the people ran out of cards.

Also, if the game doesn't end in k rounds, it automatically ends.

The program has to output:

A number l, which represents in how many rounds will the game end.

The cards Mr.Y and Mr.P have when a round ends.

I have tried to simulate the game using vector but the code raises a segmentation fault when I tried to execute it.

Here's my code:

#include<bits/stdc++.h>
using namespace std;
int n,m,k,w,x,a;
vector<int> y,p;
vector<vector<int>> ymoves;
vector<vector<int>> pmoves;
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>a;
        y.push_back(a);
    }
    for(int i=0;i<m;i++){
        cin>>a;
        y.push_back(a);
    }
    cin>>k;
    bool b=1;
    for(int i=0;i<k;i++){
        cin>>x>>w;
        for(int j=0;j<p.size();j++){
            if(p[j]==x){
                y.push_back(x);
                p.erase(p.begin()+j);
                break;
            }
        }
        for(int j=0;j<y.size()-1;j++){
            if(y[j]==x){
                y.erase(y.begin()+j);
                y.pop_back();
                break;
            }
        }
        for(int j=0;j<y.size();j++){
            if(y[j]==w){
                p.push_back(w);
                y.erase(y.begin()+j);
                break;
            }
        }
        for(int j=0;j<p.size()-1;j++){
            if(p[j]==w){
                p.erase(p.begin()+j);
                p.pop_back();
                break;
            }
        }
        copy(y.begin(),y.end(),ymoves[i].begin());
        copy(p.begin(),p.end(),pmoves[i].begin());
        if(y.empty()||p.empty()){
            b=0;
            cout<<i<<'\n';
            for(int j=0;j<i;j++){
                cout<<ymoves[j].size()<<' ';
                for(int l=0;l<ymoves[j].size();l++)cout<<ymoves[j].at(l)<<' ';
                cout<<'\n';
                cout<<pmoves[j].size()<<' ';
                for(int l=0;l<pmoves[j].size();l++)cout<<pmoves[j].at(l)<<' ';
                cout<<'\n';
            }
            break;
        }
    }
    if(b){
        cout<<k<<'\n';
        for(int j=0;j<k;j++){
            cout<<ymoves[j].size()<<' ';
            for(int l=0;l<ymoves[j].size();l++)cout<<ymoves[j].at(l)<<' ';
            cout<<'\n';
            cout<<pmoves[j].size()<<' ';
            for(int l=0;l<pmoves[j].size();l++)cout<<pmoves[j].at(l)<<' ';
            cout<<'\n';
        }
    }
}
  • 1
    Is that the only problem in the program? – Rachel_Gardner Dec 28 '19 at 08:52
  • I still can't run it. – Rachel_Gardner Dec 28 '19 at 08:53
  • A debugger can tell you where exactly a segfault occurs. – Evg Dec 28 '19 at 08:54
  • I found the part causing the segmentation fault, it's at the `y.erase(y.begin()+j);` part. – Rachel_Gardner Dec 28 '19 at 09:03
  • But how should I fix it? – Rachel_Gardner Dec 28 '19 at 09:03
  • 2
    @Evg `A debugger can tell you where exactly a segfault occurs` this is true, but the place where the segfault happens does not need to be the place that is causing the segfault. It could indeed appear at a place in the code that would be fine if the application would not be in an undefined stated due to an earlier UB. – t.niese Dec 28 '19 at 09:10
  • Not related to your question but [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – t.niese Dec 28 '19 at 09:16
  • 2
    And do your self a favor and give the variables meaningful names that express what they are used for, reading and understanding code that consists only out of one-letter variables is _"horrible"_. That will not only help you to understand where you might do something wrong but it is even more important for someone to understand the code that didn't write it. – t.niese Dec 28 '19 at 09:21
  • @t.niese Thanks for your advice. – Rachel_Gardner Dec 28 '19 at 09:25
  • 1
    @Evg `ymoves` itself is already empty, so `ymoves[i]` itself is already invalid. – t.niese Dec 28 '19 at 09:44

1 Answers1

1

One problem that will cause undefined behavior and can as of that result in a segmentation fault any time at and from that point is:

copy(y.begin(), y.end(), ymoves[i].begin());
copy(p.begin(), p.end(), pmoves[i].begin());

Both ymoves and pmoves are initialized with a size of 0. So doing ymoves[i]/pmoves[i] results into an out of bounds access, which causes UB.

As you define ymoves and pmoves globally (which does not make to much sense in your case and should be avoided in general) you need to use resize() as soon as you know how large k is:

cin>>k;
ymoves.resize(k);
pmoves.resize(k);

But that still would result in undefined behavior at the point where you do copy. As the vecotrs that are stored in pmoves/ymoves are also initialized with the size of 0 but if you use copy you have to ensure that the target is large enough to hold the data.

So you need to do a resize on those:

ymoves[i].resize(y.size());
pmoves[i].resize(p.size());

copy(y.begin(),y.end(),ymoves[i].begin());
copy(p.begin(),p.end(),pmoves[i].begin());

But I'm not really sure if doing a copy here is the correct way and I don't know if overwriting the existing values is what you want to do.

Two other errors are: for(int j=0;j<p.size()-1;j++){ and for(int j=0;j<y.size()-1;j++){, size() returns a signed value, so if p.size() is 0 you will have a problem, and thats exactly what happens in your code. Those loops should only be done if p.size() is not zero.

But due to the not optimal naming of your variables, it is hard to figure out if that part is correct and if there are more parts that are problematic. But that's at least the most obvious reason that causes UB.

t.niese
  • 39,256
  • 9
  • 74
  • 101
  • I found the part causing the segmentation fault, it's at the `y.erase(y.begin()+j);` ,`p.erase(p.begin()+j);`part.But why? – Rachel_Gardner Dec 28 '19 at 10:10
  • @Rachel_Gardner As I said understanding your code is not really possible due to the naming (and also because your application does not give any clue in the terminal what values are expected right now, it is just an empty console waiting for data where I have to guess what it is). Did you apply the changes I suggested? `y.erase(y.begin()+j);` does not look to me as if it is the reason for the segfault, just the place where it occurs. You would need to provide at least a set of input data that will allow reproducing the problem. – t.niese Dec 28 '19 at 10:19
  • Sorry for the inconvenience I've brought, here's the code and the input data:https://repl.it/@Horikita/1 – Rachel_Gardner Dec 28 '19 at 10:30
  • @Rachel_Gardner I updated the question regarding another problem you have. But that is getting out of the scope of what SO is for. Each question should target one problem, and it is not to do a full code review. – t.niese Dec 28 '19 at 10:51