0

New programmer here. I need to write a program using dynamic arrays to simulate an election. The program should first ask for a number of candidates, then take the candidate names and the number of votes received. Lastly, find the winner and print out the results.

I want to see if I've used the dynamic arrays correctly, and in what ways my code could be improved. I feel like I used a few too many for loops here. When I previously wrote this program, I created a candidate class to store each name and vote, however I do not believe you are able to create an object when using a dynamic array.

Any feedback or better insight on how to better use dynamic arrays is appreciated!

#include <iostream>
using namespace std;

void electionResults(double *votes, string *names, int candidates)
{
    double total_votes;
    int max = 0;
    int winner;
    // double Percentage[canidates];

    // counts the total number of votes
    for (int i = 0; i < candidates; i++)
    {
        total_votes += votes[i];
    }

    // determines who has the most votes
    for (int i = 0; i < candidates; i++)
    {
        if (votes[i] > max)
        {
            max = votes[i];
            winner = i;
        }
    }

    // prints results
    cout << "Result of the Election********" << endl;
    cout << "Name of Candidate"
         << "\t"
         << "Votes Received"
         << "\t"
         << "Percentage" << endl;
    for (int i = 0; i < candidates; i++)
    {
        cout << names[i] << "\t\t\t";
        cout << votes[i] << "\t\t";
        cout << (votes[i] * 100) / total_votes << "%" << endl;
    }

    cout << "Total Votes: " << total_votes << "\n";
    for (int i = 0; i < candidates; i++)
    {
        if (winner == i)
        {
            cout << "The winner is " << names[i] << "\n";
        }
    }
}

int main()
{
    string name;
    double votes;
    int Num_candidates;
    // dynamic array declerations
    double *voting_Array;
    string *name_Array;

    cout << "Enter the number of candidates\n";
    cin >> Num_candidates;

    voting_Array = new double[Num_candidates];
    name_Array = new string[Num_candidates];

    for (int i = 0; i < Num_candidates; i++)
    {
        cout << "Enter candidate's " << i + 1 << " last name \n";
        cin >> name;
        name_Array[i] = name;
    }

    for (int i = 0; i < Num_candidates; i++)
    {
        cout << "Enter votes for " << name_Array[i] << " ";
        cin >> votes;
        voting_Array[i] = votes;
    }

    electionResults(voting_Array, name_Array, Num_candidates);

    voting_Array = NULL;
    name_Array = NULL;
    return 0;
}       
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    "*I want to see ... in what ways my code could be improved*" - that is not what StackOverflow is meant for. This is a Q&A site. It is OK to ask if the dynamic array usage is correctly, but if the code actually works (ie, you get the result you are expecting), and you just want to improve the code, then ask about that on [CodeReview](https://codereview.stackexchange.com) instead. "*I do not believe you are able to create an object when using a dynamic array*" - of course you can create objects in arrays. – Remy Lebeau Oct 18 '22 at 00:16
  • 1
    If you need a dynamic array, then use [std::vector](https://en.cppreference.com/w/cpp/container/vector). *Not* manual memory management. – Jesper Juhl Oct 18 '22 at 00:18
  • 1
    [Why is "using namespace std;" considered bad practice?](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) – Jesper Juhl Oct 18 '22 at 00:19
  • `voting_Array = NULL;` this leaks memory :O~ – Fantastic Mr Fox Oct 18 '22 at 00:20
  • Okay, thank you for the reply and another resource to add! – huntr_gathr Oct 18 '22 at 00:20
  • `double total_votes;` is an *unitialized* variable, so `total_votes += votes[i];` afterwards is *undefined behavior*. `int winner;` is also unintialized – Remy Lebeau Oct 18 '22 at 00:20
  • You can make dynamic arrays of custom classes, but the classes usually need a [default constructor](https://en.cppreference.com/w/cpp/language/default_constructor). Without a default constructor you cannot make instances without having to provide arguments, something that's tricky to do with an array of unknown size. – user4581301 Oct 18 '22 at 00:21
  • https://en.cppreference.com/w/cpp/language/ub – Jesper Juhl Oct 18 '22 at 00:25
  • @FantasticMrFox ah yes forgot to use delete[] for both arrays :0 – huntr_gathr Oct 18 '22 at 00:30
  • Don't use `NULL` in modern C++. Use [nullptr](https://en.cppreference.com/w/cpp/language/nullptr). – Jesper Juhl Oct 18 '22 at 00:33
  • Before you post at [codereview.se], make sure to read [A guide to Code Review for Stack Overflow users](//codereview.meta.stackexchange.com/a/5778), as some things are done differently over there - e.g. question titles should simply say what the code *does*, as the question is always, "How can I improve this?". Be sure that the code works correctly; include your unit tests if possible. You'll likely get some suggestions on making it more efficient, easier to read, and better tested. – Toby Speight Oct 18 '22 at 06:59

1 Answers1

1

There are some issues with your electionResults() function.

double total_votes; is an uninitialized variable, so total_votes += votes[i]; afterwards is undefined beehvior. Same with int winner;

Also, since votes is an array of doubles, max should also be a double, not an int. But then, can you really have fractions of a vote? Perhaps votes should be an array of ints instead?

That being said, your use of dynamic arrays is almost correct. You are creating, filling, and displaying the arrays correctly, but where you are going wrong is freeing the arrays. Since the arrays are allocated with new[], you need to use delete[] to free them, eg:

voting_Array = new double[Num_candidates];
name_Array = new string[Num_candidates];
...
delete[] voting_Array;
delete[] name_Array;

Though, you really should be using std::vector insted of new[]/delete[] directly. Let vector handle the dynamic memory for you.

And yes, you can create objects in arrays.

Try something more like this:

#include <iostream>
#include <vector>
#include <limits>
using namespace std;

struct Candidate
{
    string name;
    double/*unsigned int*/ votes;
}

void electionResults(const vector<Candidate> &candidates)
{
    // count the total number of votes and
    // determine who has the most votes

    double/*unsigned int*/ total_votes = candidates[0].votes;
    double/*unsigned int*/ max_votes = candidates[0].votes;
    size_t winner = 0;

    for (size_t i = 1; i < candidates.size(); ++i)
    {
        total_votes += candidates[i].votes;

        if (candidates[i].votes > max_votes)
        {
            max_votes = candidates[i].votes;
            winner = i;
        }
    }

    // prints results
    cout << "Result of the Election********" << endl;
    cout << "Name of Candidate"
         << "\t"
         << "Votes Received"
         << "\t"
         << "Percentage" << endl;
    for (size_t i = 0; i < candidates.size(); ++i)
    {
        cout << candidates[i].name << "\t\t\t";
        cout << candidates[i].votes << "\t\t";
        cout << (double(candidates[i].votes) * 100.0 / total votes) << "%" << endl;
    }

    cout << "Total Votes: " << total_votes << "\n";
    cout << "The winner is " << candidates[winner].name << "\n";
}

int main()
{
    size_t Num_candidates;

    do
    {
        cout << "Enter the number of candidates\n";

        if (cin >> Num_candidates)
        {
            if (Num_candidates > 0)
                break;

            cout << "At least 1 candidate is needed!\n";
        }
        else
        {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "Invalid number entered!\n";
        }
    }
    while (true);

    vector<candidate> voting_Array(Num_candidates);

    for (size_t i = 0; i < Num_candidates; ++i)
    {
        cout << "Enter candidate's " << i + 1 << " last name \n";
        cin >> voting_Array[i].name;
    }

    for (size_t i = 0; i < Num_candidates; ++i)
    {
        do
        {
            cout << "Enter votes for " << voting_Array[i].name << " ";

            if (cin >> voting_Array[i].votes)
            {
                if (voting_Array[i].votes >= 0)
                    break;

                cout << "Votes cant be negative!\n";
            }
            else
            {
                cin.clear();
                cin.ignore(numeric_limits<streamsize>::max(), '\n');
                cout << "Invalid number entered!\n";
            }
        }
        while (true);
    }

    electionResults(voting_Array);

    return 0;
}       
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770