0

The c++ code below works fine for some inputs, but it is stuck at test 9 (number of inputs here is 6000) where it gives me this message "Process returned -1073741571 (0xC00000FD)".

This code reads information for n babies (their gender and name). Next it counts the appearances of each name then sorts the list of structures according to the appearances. Finally, it removes the duplicates and prints the top m female names and top m male names.

What does this error mean and what do I need to change to eliminate this error?

#include <iostream>
#include <fstream>
#include <algorithm>
#include <string.h>

using namespace std;
ifstream fin("input.txt");
struct baby
{
    string gender,name;
    int cnt;
};
bool cmp(baby a,baby b)
{
    if (a.cnt>b.cnt)
        return true;
    else if (a.cnt==b.cnt && a.name<b.name)
        return true;
    return false;
}
int howmany(baby babies[],int n,int i)
{

    int cnt=0;
    for (int j=0; j<n; j++)
    {
        if (babies[i].name==babies[j].name && babies[i].gender==babies[j].gender)
        {
            cnt++;
        }
    }
    return cnt;
}
void getData(baby babies[],int n)
{
    for (int i=0; i<n; i++)
    {
        fin>>babies[i].gender>>babies[i].name;

    }
}
int removeDuplicates(baby babies[],int n)
{
    int j=0;
    for (int i=0; i<n-1; i++)
    {
        if (babies[i].name!=babies[i+1].name)
            babies[j++]=babies[i];
    }
    babies[j++]=babies[n-1];
    return j; 
}
int main()
{
    int n,i,top,j;
    fin>>n>>top;
    baby babies[50000];
    getData(babies,n);  
    for (i=0; i<n; i++)
    {
        babies[i].cnt=howmany(babies,n,i); 
    }
    sort(babies,babies+n,cmp); 
    j=removeDuplicates(babies,n); 
    int cnt=0;
    for (int i=0; i<j; i++)
    {
        if (cnt<top)
        {
            if (babies[i].gender=="F")
            {
                cout<<babies[i].name<<" "; 
                cnt++;
            }
        }
    }
    cout<<endl;
    cnt=0;
    for (int i=0; i<j; i++)
    {
        if (cnt<top)
        {
            if (babies[i].gender=="M")
            {
                cout<<babies[i].name<<" "; 
                cnt++;
            }
        }
    }
    return 0;
}
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
UserL00
  • 37
  • 1
  • 8
  • 1
    And when you used your debugger to run your program, what did you see? This is precisely what a debugger is for. If you don't know how to use a debugger this is a good opportunity to learn how to use it to run your program one line at a time, monitor all variables and their values as they change, and analyse your program's logical execution flow. Knowing how to use a debugger is a required skill for every C++ developer, no exceptions. With your debugger's help you should be able to quickly find all bugs in this and all future programs you write, without having to ask anyone for help. – Sam Varshavchik May 25 '20 at 16:24
  • Typically a debugger will stop dead as spoon as the program crashes and allow you to inspect the crash site. The actual bug might not be anywhere near the crash, but knowing what happened is a good first step to finding out why it happened. – user4581301 May 25 '20 at 16:26
  • Semi-related: `baby babies[50000];` is a lot of babies. Are you sure you have enough Automatic storage? – user4581301 May 25 '20 at 16:27
  • also as a side note [why_is using namespace std considered bad practice](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – yaodav May 25 '20 at 16:32
  • *The c++ code below works fine for some inputs, but it is stuck at test 9 (number of inputs here is 6000* -- What does "test 9" mean? Is this question from an "online judge" website? Also, you're using `std::sort`, but did you realize that there is a `std::count_if` that you could use to count the number of babies? There is also `std::unique` to "remove" the duplicates? Basically your code would be 75% smaller if you used these functions (in addition to changing your array to `std::vector`). – PaulMcKenzie May 25 '20 at 16:43

1 Answers1

0

As you can see in Window's NT status reference, error code 0xC00000FD means stack overflow (usually caused by infinite recursion). In your case, it seems that you simply allocate a far too large array on the stack (line 57, baby babies[50000];), which is an array of size 50000*20=1000000. The simplest solution will be a dynamic allocation

baby* babies = new baby[50000];
// Your code here
delete[] babies;

A better solution would be to use std::vector which is a dynamic array that can grow and shrink. The simplest thing to do is to take a vector of size 50000, this way:

#include <vector>
...
std::vector<baby> babies(50000);

However, this is a poor solution as your pre-allocate 50000 elements even though you probably need much much less, and a better solution would be to add an element on-demand, using .push_back(element) method, or in your case, allocate n elements to the vector (impossible in a stack-allocated array).

I added your code with some modifications of mine:

#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;
ifstream fin("input.txt");

struct baby
{
    string gender;
    string name;
    int cnt = 0;
};

bool cmp(const baby& a, const baby& b)
{
    if (a.cnt > b.cnt) {
        return true;
    }
    return a.cnt == b.cnt && a.name < b.name;
}

bool are_equal(const baby& lhs, const baby& rhs)
{
    return lhs.gender == rhs.gender && lhs.name == rhs.name;
}

int howmany(const std::vector<baby>& babies, int i)
{

    int cnt = 0;
    for (int j = 0; j < babies.size(); j++)
    {
        if (babies[i].name == babies[j].name && babies[i].gender == babies[j].gender)
        {
            cnt++;
        }
    }
    return cnt;
}

void getData(std::vector<baby>& babies)
{
    for (int i = 0; i < babies.size(); i++)
    {
        fin >> babies[i].gender >> babies[i].name;
    }
}

int removeDuplicates(std::vector<baby>& babies)
{
    int j = 0;
    for (int i = 0; i < babies.size() - 1; i++)
    {
        if (babies[i].name != babies[i + 1].name) {
            babies[j++] = babies[i];
        }
    }
    babies[j++] = babies.back();
    return j;
}

void remove_duplicates_improved(std::vector<baby>& babies)
{
    babies.erase(babies.begin(), std::unique(babies.begin(), babies.end(), are_equal));
}

int main()
{
    int n;
    int top;
    fin >> n >> top;
    std::vector<baby> babies(n);
    getData(babies);
    for (int i = 0; i < n; i++)
    {
        babies[i].cnt = howmany(babies, i);
    }
    sort(babies.begin(), babies.begin() + n, cmp);

    remove_duplicates_improved(babies);
    int cnt = 0;
    for (int i = 0; i < babies.size(); i++)
    {
        if (cnt < top)
        {
            if (babies[i].gender == "F")
            {
                cout << babies[i].name << " ";
                cnt++;
            }
        }
    }
    cout << endl;
    cnt = 0;
    for (int i = 0; i < babies.size(); i++)
    {
        if (cnt < top)
        {
            if (babies[i].gender == "M")
            {
                cout << babies[i].name << " ";
                cnt++;
            }
        }
    }
    return 0;
}

Good luck

Michael
  • 932
  • 6
  • 15
  • As you gain experience with C++, you will find `std::vector` is orders of magnitude less advanced than self-managed dynamic allocation. Another simple solution applicable to this case is to statically allocate `babies`. – user4581301 May 25 '20 at 16:35
  • 1
    100% agree with you but usually, such questions (array of babies) arise from people learning C++ and most textbooks/universities teach `STL` with structures, far later than dynamic allocation. – Michael May 25 '20 at 16:36
  • @Michael -- We don't know if the OP is learning this from school, or from a bad/outdated web-site or book. Thus it is better to give the C++ best solution, which in this case is `std::vector`. – PaulMcKenzie May 25 '20 at 16:38
  • makes sense, I'll edit – Michael May 25 '20 at 16:39
  • I tried using "static" and it didn't work. I also tried to dynamically allocate the array and it didn't work wither. Even the modified code you sent me doesn't show any output at all. I know 50000 is a big number but the exercise says that the size of the array must be 50000. – UserL00 May 25 '20 at 19:34
  • @Leticia Very easy to have multiple problems, but 50000 `baby`s on the stack is almost certainly the cause of the stack overflow. Each `baby` is upwards of 50 bytes assuming you're using a compiler produced in the last 10-15 years.50 times 50000 is 2.5 MB. Windows generally offers 1 1MB stack. You have to get `babies` off the stack and then hunt and kill other bugs that may be in your code.. – user4581301 May 25 '20 at 19:41
  • So what do you suggest to me I really need this code. – UserL00 May 25 '20 at 19:56