The local baseball team is computerizing its records. Write a program that computes batting averages and other statistics.

There are 20 players on the team, identified by the player ID 1 through 20.

You will have two input files: roster.txt and statistics.txt

1) The Roster File (roster.txt) -
This file contains 21 lines, first line is an integer indicating the season. The rest is in the format “player ID last name first name” (separated by a space) for each player, as follows:

2012
4 Smith Sam
15 Jones Bob
5 Miller Miles
3 Carter John
11 Apbee Cory
9 Jackson James
2 Zutter Tommy
18 Buzz Bee
8 Duncan Michael
20 Tso Terry
12 Lenn Lance
1 Johnson Albert
6 Knight Owl
19 Neon Bret
13 Ora Adam
16 Elfin Victor
7 Hoo Frank
17 Greene Martin
10 Crane David
14 Rutter Jack

(2) The Statistic File (statistics.txt) -
This file contains the game-by game statistics for the players as a “player ID number, hits, walks, outs”

15 3 2 1
10 2 1 1
9 5 2 1
3 2 2 1
19 1 2 3
20 1 1 1
5 3 1 3
1 2 2 3
11 0 2 2
12 6 3 2
8 3 0 0
7 1 2 3
19 2 2 1
6 5 2 0
5 1 1 1
15 2 5 3
11 1 1 3
14 4 2 3
9 0 1 2
5 1 1 1
15 3 2 1
9 5 2 1
3 2 2 1
20 1 1 1
5 3 1 3
19 1 2 3
12 6 3 2
8 3 0 0
7 1 2 3
19 2 2 1

Here is an example:

3 2 1 1

The example above indicates that during a particular game in the season, player number 3 made 2 hits, 1 walk, and 1 out. Notice, that means they were at bat 4 times.

There might be several lines in the file for the same player. (A player can play more than one game in a season.) The file is organized by the batting line-ups (it is not sorted by player number).

Each player’s batting average is computed by adding the player’s total number of hits, then dividing by the total number of times at bat.

A walk does not count as either a hit or a time at bat when the batting average is being calculated.

When your statistics file contains no data, print message to output file saying, “The 2012 baseball season was cancelled” and end the execution.

Define a struct type PlayerInfo:

struct PlayerInfo
{
     int PlayerID;
     string LastName;                
     string FirstName;                      
     int Hits, Walks, Outs;
     double Batting, OnBase;
}; 

Create an array of PlayerInfo structs to hold the players’ data. The array is local to main function and passes to other functions as argument.

PlayerInfo Player[20];

Requirements: (your program must follow this logic) Functions must be called in this order inside main function.

  1. In the main function, you will call a function GetPlayer to read from Roster file and store the player names and id into the array and return the year for the season.

    int GetPlayer ( PlayerInfo [ ] );
    

(player in first line will store in index of 0, second line in index of 1, third line in index of 2, and etc.)

  1. Call a SortPlayerID function to sort them by Player ID. (e.g. use bubble sort or selection sort)

  2. Call a PrintRoster function to send the roster for the team with player ID in order to an output file

  3. Then call a GetStatistics function to read the statistics file, updating each player’s statistics of hits, walks and outs.
    Hints – you need to keep the player identification numbers with the player names and the data in the struct. When you read a player’s game line, look up the player in the array of structs before you adding up the hits, walks and outs (Player ID can identify the index of the array)

  4. A function to calculate each player’s batting average and on base average and store them.
    (remember to do casting in order to retain the factional part)

batting average = (hits) / (hits + outs)
on base average = (hits + walks) / (total at bats)

  1. Call a SortPlayerName function to sort the players by last name

  2. A function to Send the players’ statistics to the output file including their Batting Average, On Base Average, in DL list, the best hitter, the worst hitter, the best base runner and the worst base runner. (Note: A player is in the Disable List if he didn’t play at all in the entire season.)

Sample of an output file:

Baseball Season 2012
--------------------------------
Johnson Albert Player 1
Zutter Tommy Player 2
Miller Miles Player 3
and etc……
Tso Terry Player 20

The alphabetical list of players with each player’s statistics (partial list)
Player Number Hits Walks Outs Batting Average On Base Average In Disable List
-------------------------------------------------------------------------------------------------------------------------------------------------------
Apbee Cory 11 xx xx xx 0.xx 0.xx
Buzz Bee 18 xx xx xx 0.xx 0.xx
Carter John 3 Yes
Crane David 10 xx xx xx 0.xx 0.xx
and etc……

Give the last name(s) and batting average of the best hitter (i.e. highest batting average).
Give the last name(s) and on-base average of the best base runner
Give the last name(s) and batting average of the worst hitter
Give the last name(s) and on-base average of the worst base runner

If there is a tie for best or worst, Print all the players’ names.

Example: (might not be true for your input file)
The best hitter with batting average of 0.68: Jones
The worst hitter with batting average of 0.04: Miller, Smith

Here is my solution:

#include <fstream>
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

#define infile "Roster.txt"
#define outfile "Statistic.txt"

int GetPlayer(PlayerInfo[]);

struct PlayerInfo
{
     int PlayerID;
     string LastName;
     string FirstName;
     int Hits, Walks, Outs;
     double Batting, OnBase;
};

int GetPlayer(PlayerInfo[])
{
    PlayerInfo playerid = {20};
    PlayerInfo firstname = {20};
    PlayerInfo lastname = {20};
    cin >> playerid >> firstname >> lastname;
    return 0;
}

void SortPlayerID()
{
    int PlayerIDs[20];
    int index = 0;
    for(int i = index+1; i > 0; i++)
    {
        if(PlayerIDs[i] < PlayerIDs[index])
        {
            PlayerIDs[i] = PlayerIDs[index];
            PlayerIDs[index] = PlayerIDs[i];
        }
        index++;
    }
}

void PrintRoster()
{
    PlayerInfo PlayerIDs = {20};
    cout << "     Baseball Season 2012    ";
    cout << "--------------------------------";
    cout << PlayerIDs << endl;
}

int GetStatistics()
{
    int hits, walks, outs, total;
    PlayerInfo playerid = {20};
    PlayerInfo firstname = {20};
    PlayerInfo lastname = {20};
    total = hits + walks + outs;
    return 20;
}

int Calculate()
{
    double batting_avg, onbase_avg;
    int hits;
    int walks;
    int outs;
    int total = hits + walks + outs;
    batting_avg = int((hits)/(hits + outs));
    onbase_avg = int((hits + walks)/(total));
    return 0;
}

void SortPlayerName()
{
    int lastnames[20];
    int index = 0;
    for(int i = index+1; i > 0; i++)
    {
        if(lastnames[i] < lastnames[index])
        {
            lastnames[i] = lastnames[index];
            lastnames[index] = lastnames[i];
        }
        index++;
    }
}

void DisplayStatistics(char disabled_list)
{
     double highest_batting;
     double highest_onbase;
     double lowest_batting;
     double lowest_onbase;
     PlayerInfo PlayerID = {20};
     PlayerInfo LastName = {20};
     PlayerInfo FirstName = {20};
     PlayerInfo Hits, Walks, Outs;
     PlayerInfo Batting, OnBase;
     cout << "Player  " << "Number  " << "Hits    " << "Walks       " << "Outs        " << "Batting Average     " << "On Base Average     " << "In Disable List" << endl;
     cout << LastName << FirstName << "\t" << PlayerID << "\t" << Hits << "\t" << Walks << "\t" << Outs << "\t" << Batting << "\t" << OnBase << disabled_list << endl;
     for(int i; i > 0; i++)
     {
         if(highest_batting < Batting)
         {
             cout << "The best hitter with batting average of " << Batting << ": " << LastName << endl;
         }
         else if(highest_onbase < OnBase)
         {
             cout << "The best base runner with on-base average of " << OnBase << ": " << LastName << endl;
         }
         else if(lowest_batting > OnBase)
         {
             cout << "The worst hitter with batting average of " << Batting << ": " << LastName << endl;
         }
         else if(lowest_onbase < OnBase)
         {
             cout << "The worst base runner with on-base average of " << OnBase << ": " << LastName << endl;
         }
         else if(LastName == disabled_list)
         {
             cout << "Yes" << endl;
         }
     }
}

int main()
{
    ifstream team;
    ofstream stats;
    char disabled_list;
    PlayerInfo Player[20];
    PlayerInfo PlayerID;
    PlayerInfo LastName;
    PlayerInfo FirstName;
    PlayerInfo Hits, Walks, Outs;
    PlayerInfo Batting, OnBase;

    team.open(infile);
    if(team.fail())
    {
        cout << "The 2012 baseball season was cancelled" << endl;
        return -1;
    }

    stats.open(outfile);
    if(stats.fail())
    {
        cout << "The 2012 baseball season was cancelled" << endl;
        team.close();
        return -1;
    }

    while(!team.eof())
    {
        GetPlayer(Player);
        SortPlayerID();
        PrintRoster();
        GetStatistics();
        Calculate();
        SortPlayerName();
        DisplayStatistics(disabled_list);
    }

    team.close();
    stats.close();

    return 0;
}

I'm not sure if I am doing the functions correctly. Is there anything I need to change?

Did you compile the program? Are there any compiler errors? If yes, then list a few of them. If not, did you try to run the program? Does the program produce the correct results?

I'm not sure if I am doing the functions correctly. Is there anything I need to change?

You're not and there is.

Consider the GetPlayer function:

int GetPlayer(PlayerInfo[])
{
    PlayerInfo playerid = {20};
    PlayerInfo firstname = {20};
    PlayerInfo lastname = {20};
    cin >> playerid >> firstname >> lastname;
    return 0;
}

The first line int GetPlayer( PlayerInfo[] ) is OK for a function declaration, but not for a function definition. If you want to do things with the array of PlayerInfo objects, then you need to give it a name:

// We've provided the name "players" so that we can reference the array inside the function
int GetPlayer( PlayerInfo players[] )  
{
    // Contents of function
}

Now, for the actual contents of the GetPlayers function, remember that this function has to do a whole bunch of things. What you have at the moment almost certainly doens't compile, but in any case it's only doing what it does for one thing. So lets look at the question again:

You will have two input files: roster.txt and statistics.txt

1) The Roster File (roster.txt) -
This file contains 21 lines, first line is an integer indicating the season. The rest is in the format “player ID last name first name” (separated by a space) for each player

and

In the main function, you will call a function GetPlayer to read from Roster file and store the player names and id into the array and return the year for the season.

So, start by writing a list of the things that your function has to do using comments:

int GetPlayer( PlayerInfo players[] )
{
    // Open the roster.txt file

    // Read the year from the first line

    // for each line in the file (you're going to need a loop of some sort here)
        // Read the player ID
        // Read the player first name
        // Read the player second name

        // Add the details to the next slot in the "players" array

    // Return the year that we read at the start
}

So, you have a kind of "map" for what you're going to need to do in the function. Now, go back to the beginning and start adding some code:

int GetPlayer( PlayerInfo players[] )
{
    // Open the roster.txt file
    std::ifstream inputFile( "roster.txt" );
    if ( ! inputFile.is_open() )
    {
        std::cerr << "ERROR: Failed to open \"roster.txt\" for input!" << std::endl;
        return -1;   // Return a negative year on failure
    }

    // Read the year from the file...
    //
    // OK, it's all you from here :o)
}

Finally, remember that pretty much all the functions that you make for this excercise are going to need to have the array of PlayerInfo passed into them. So, you should end up with things like:

void SortPlayerID( PlayerInfo players[] )
{
}

void PrintRoster( PlayerInfo players[] )
{
}

void GetStatistics( PlayerInfo players[] )
{
}

// And so on...

Hope that helps a little. Have fun.

Here is my updated solution:

#include <fstream>
#include <iostream>
#include <string>
using namespace std;

#define infile "Roster.txt"
#define outfile "Statistic.txt"

int GetPlayer(PlayerInfo[]);

struct PlayerInfo
{
     int PlayerID;
     string LastName;
     string FirstName;
     int Hits, Walks, Outs;
     double Batting, OnBase;
};

int GetPlayer(PlayerInfo players[])
{
    players[20];
    PlayerInfo playerid[20];
    PlayerInfo firstname[20];
    PlayerInfo lastname[20];

    ifstream inputFile("Roster.txt");

    if(!inputFile.is_open())
    {
        cout << "ERROR: Failed to open \"roster.txt\" for input!" << endl;
        return -1;
    }
    for(int i; i < players; i++)
    {
        inputFile >> playerid >> firstname >> lastname;
        players += inputFile;
    }
    return 0;
}

void SortPlayerID(PlayerInfo players[])
{
    players[20];
    PlayerInfo PlayerIDs[20];
    int index = 0;
    for(int i = index+1; i > 0; i++)
    {
        if(PlayerIDs[i] < PlayerIDs[index])
        {
            PlayerIDs[i] = PlayerIDs[index];
            PlayerIDs[index] = players[i];
            players[i] = PlayerIDs[i];
        }
        index++;
    }
}

void PrintRoster(PlayerInfo players[])
{
    players[20];
    PlayerInfo PlayerIDs[20];
    cout << "     Baseball Season 2012    ";
    cout << "--------------------------------";
    cout << PlayerIDs << endl;
}

int GetStatistics(PlayerInfo players[])
{
    players[20];
    PlayerInfo hits, walks, outs;
    PlayerInfo playerid[20];
    PlayerInfo firstname[20];
    PlayerInfo lastname[20];
    int total;
    total = hits + walks + outs;
    return 20;
}

int Calculate(PlayerInfo players[])
{
    players[20];
    PlayerInfo batting_avg, onbase_avg;
    PlayerInfo hits, walks, outs;
    int total = hits + walks + outs;
    batting_avg = int((hits)/(hits + outs));
    onbase_avg = int((hits + walks)/(total));
    return 0;
}

void SortPlayerName(PlayerInfo players[])
{
    players[20];
    PlayerInfo lastnames[20];
    int index = 0;
    for(int i = index+1; i > 0; i++)
    {
        if(lastnames[i] < lastnames[index])
        {
            lastnames[i] = lastnames[index];
            lastnames[index] = players[i];
            players[i] = lastnames[i];
        }
        index++;
    }
}

void DisplayStatistics(PlayerInfo players[])
{
     char disabled_list;
     double highest_batting;
     double highest_onbase;
     double lowest_batting;
     double lowest_onbase;
     players[20];
     PlayerInfo PlayerID[20];
     PlayerInfo LastName[20];
     PlayerInfo FirstName[20];
     PlayerInfo Hits, Walks, Outs;
     PlayerInfo Batting, OnBase;
     cout << "Player  " << "Number  " << "Hits    " << "Walks       " << "Outs        " << "Batting Average     " << "On Base Average     " << "In Disable List" << endl;
     cout << LastName << FirstName << "\t" << PlayerID << "\t" << Hits << "\t" << Walks << "\t" << Outs << "\t" << Batting << "\t" << OnBase << disabled_list << endl;
     for(int i; i > 0; i++)
     {
         if(highest_batting < Batting)
         {
             cout << "The best hitter with batting average of " << Batting << ": " << LastName << endl;
         }
         else if(highest_onbase < OnBase)
         {
             cout << "The best base runner with on-base average of " << OnBase << ": " << LastName << endl;
         }
         else if(lowest_batting > OnBase)
         {
             cout << "The worst hitter with batting average of " << Batting << ": " << LastName << endl;
         }
         else if(lowest_onbase < OnBase)
         {
             cout << "The worst base runner with on-base average of " << OnBase << ": " << LastName << endl;
         }
         else if(LastName == disabled_list)
         {
             cout << "Yes" << endl;
         }
     }
}

int main()
{
    ifstream team;
    ofstream stats;
    char disabled_list;
    PlayerInfo Player[20];
    PlayerInfo PlayerID[20];
    PlayerInfo LastName[20];
    PlayerInfo FirstName[20];
    PlayerInfo Hits, Walks, Outs;
    PlayerInfo Batting, OnBase;

    team.open(infile);
    if(team.fail())
    {
        cout << "The 2012 baseball season was cancelled" << endl;
        return -1;
    }

    stats.open(outfile);
    if(stats.fail())
    {
        cout << "The 2012 baseball season was cancelled" << endl;
        team.close();
        return -1;
    }

    while(!team.eof())
    {
        GetPlayer(Player);
        SortPlayerID(Player);
        PrintRoster(Player);
        GetStatistics(Player);
        Calculate(Player);
        SortPlayerName(Player);
        DisplayStatistics(Player);
    }

    team.close();
    stats.close();

    return 0;
}

My code is giving these compiler errors: No operator matches these operands. It it happening with these: <<, <, >, ==, +, +=. Is there anything I can do to fix them?

line 36: You're attempting to input a c++ class. > operator must be used on a POD (Plain Old Data) type such as an int, float, double, std::string or char*, unless you override the > operator, which you have not done.

line 22: You didn't specify a data type of the array. Should read PlayerInfo players[20]

lines 23, 24 and 25. Delete these lines, you don't need those arrays. The array declared on line 22 contains all that information so there's no need to declare separate arrays for them.

line 34: you need to initialize variable i, e.g. for(i = 0; ...

line 36: This should be like this: inputFile >> players[i].playerid >> players[i].firstname >> players[i].lastname;

Still concentrating on your GetPlayer function. Try answering the questions in the comments

int GetPlayer(PlayerInfo players[])
{
    players[20];               // Why have you declared this arrray?
    PlayerInfo playerid[20];   // This is another array of 20 PlayerInfo objects, is that what you want?
    PlayerInfo firstname[20];  // Same here...
    PlayerInfo lastname[20];   // ...And here
    ifstream inputFile("Roster.txt");
    if(!inputFile.is_open())
    {
        cout << "ERROR: Failed to open \"roster.txt\" for input!" << endl;
        return -1;
    }

    // In this loop you don't give "i" an initial value, what do you think this will do?
    // You also have "i < players", what do you think this means?
    for(int i; i < players; i++)
    {
        // This is causing your compilation errors, because all the variables are arrays of
        // PlayerInfo objects. Do you think it makes sense to read a single variable
        // directly into an array of PlayerInfo objects?
        inputFile >> playerid >> firstname >> lastname;
        players += inputFile;
    }

    // You're returning zero.  Is this what the question says the function GetPlayer should do?
    return 0;
}

Here is my updated code, I fixed the compiler errors in the GetPlayer function. Is that function correct? Is there anything I need to change in the SortPlayerID function?:

#include <fstream>
#include <iostream>
#include <string>
using namespace std;

#define infile "Roster.txt"
#define outfile "Statistic.txt"

int GetPlayer(PlayerInfo []);

struct PlayerInfo
{
     int PlayerID;
     string LastName;
     string FirstName;
     int Hits, Walks, Outs;
     double Batting, OnBase;
};

int GetPlayer(PlayerInfo players[20])
{
    ifstream inputFile("Roster.txt");

    if(!inputFile.is_open())
    {
        cout << "ERROR: Failed to open \"roster.txt\" for input!" << endl;
        return -1;
    }
    for(int i = 0; i < 20; i++)
    {
        inputFile >> players[i].PlayerID >> players[i].FirstName >> players[i].LastName;
    }
    return 1;
}

void SortPlayerID(PlayerInfo players[20])
{
    int index = 0;
    for(int i = index+1; i > 0; i++)
    {
        if(players[i].PlayerID < players[index].PlayerID)
        {
            players[i].PlayerID  = players[index].PlayerID;
            players[index].PlayerID = players[i].PlayerID;
        }
        index++;
    }
}

void PrintRoster(PlayerInfo players[20])
{
    cout << "     Baseball Season 2012    ";
    cout << "--------------------------------";
    cout << players[20].PlayerID << endl;
}

int GetStatistics(PlayerInfo players[20])
{
    int total;
    total = players[20].Hits + players[20].Walks + players[20].Outs;
    return 20;
}

int Calculate(PlayerInfo players[20])
{
    int total = players[20].Hits + players[20].Walks + players[20].Outs;
    players[20].Batting = int((players[20].Hits)/(players[20].Hits + players[20].Outs));
    players[20].OnBase = int((players[20].Hits + players[20].Walks)/(total));
    return 0;
}

void SortPlayerName(PlayerInfo players[20])
{
    int index = 0;
    for(int i = index+1; i > 0; i++)
    {
        if(players[i].LastName < players[index].LastName)
        {
            players[i].LastName = players[index].LastName;
            players[index].LastName = players[i].LastName;
        }
        index++;
    }
}

void DisplayStatistics(PlayerInfo players[20])
{
     string disabled_list;
     double highest_batting;
     double highest_onbase;
     double lowest_batting;
     double lowest_onbase;
     cout << "Player  " << "Number  " << "Hits    " << "Walks       " << "Outs        " << "Batting Average     " << "On Base Average     " << "In Disable List" << endl;
     cout << players[20].LastName << players[20].FirstName << "\t" << players[20].PlayerID << "\t" << players[20].Hits << "\t" 
         << players[20].Walks << "\t" << players[20].Outs << "\t" << players[20].Batting << "\t" << players[20].OnBase << disabled_list << endl;
     for(int i; i > 0; i++)
     {
         if(highest_batting < players[20].Batting)
         {
             cout << "The best hitter with batting average of " << players[20].Batting << ": " << players[20].LastName << endl;
         }
         else if(highest_onbase < players[20].OnBase)
         {
             cout << "The best base runner with on-base average of " << players[20].OnBase << ": " << players[20].LastName << endl;
         }
         else if(lowest_batting > players[20].OnBase)
         {
             cout << "The worst hitter with batting average of " << players[20].Batting << ": " << players[20].LastName << endl;
         }
         else if(lowest_onbase < players[20].OnBase)
         {
             cout << "The worst base runner with on-base average of " << players[20].OnBase << ": " << players[20].LastName << endl;
         }
         else if(players[20].LastName == disabled_list)
         {
             cout << "Yes" << endl;
         }
     }
}

int main()
{
    ifstream team;
    ofstream stats;
    char disabled_list;
    PlayerInfo Player[20];
    PlayerInfo PlayerID[20];
    PlayerInfo LastName[20];
    PlayerInfo FirstName[20];
    PlayerInfo Hits, Walks, Outs;
    PlayerInfo Batting, OnBase;

    team.open(infile);
    if(team.fail())
    {
        cout << "The 2012 baseball season was cancelled" << endl;
        return -1;
    }

    stats.open(outfile);
    if(stats.fail())
    {
        cout << "The 2012 baseball season was cancelled" << endl;
        team.close();
        return -1;
    }

    while(!team.eof())
    {
        GetPlayer(Player);
        SortPlayerID(Player);
        PrintRoster(Player);
        GetStatistics(Player);
        Calculate(Player);
        SortPlayerName(Player);
        DisplayStatistics(Player);
    }

    team.close();
    stats.close();

    return 0;
}
This article has been dead for over six months. Start a new discussion instead.