Passing Structures to Arrays

So I know that there are topics about this already, but I have seen none that help with my specific problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <cstdlib>
#include <fstream>
using namespace std;

const int games = 10; //total games played/person
const int stat = 5; //total amount of stored stats
const int players = 3; //amount of players in the file

struct playerInfo {
	string name;
	//GAME X; completions; attempts; yards; touchdowns; interceptions
	int matrix[games][stat];
};

void printPlayer(int player, struct playerInfo) {
	cout << n1.matrix[1][2];
}

void printPlayerStats(int player) {

}

void printPasserRatings() {

}

int main() {
	//Three players
	playerInfo n1;
	playerInfo n2;
	playerInfo n3;

	ifstream inFile;
	inFile.open("QBInfo.txt", ios::in);

	string trash = "";

	if (inFile.fail()) {
		cout << "ERROR OPENING FILE";
		exit(1);
	}
	else {
		while (inFile) {
			getline(inFile, trash); //takes in the first "3" to be ignored
			for (int player = 0; player < players; player++) {
				//switch to get which name for which player
				switch (player) {
				case 0: getline(inFile, n1.name);
					break;
				case 1: getline(inFile, n2.name);
					break;
				case 2: getline(inFile, n3.name);
					break;
				}
				for (int game = 0; game < games; game++) {
					switch (player) {
					case 0: inFile >> n1.matrix[game][0] >> n1.matrix[game][1] >> n1.matrix[game][2] >> n1.matrix[game][3] >> n1.matrix[game][4];
						break;
					case 1: inFile >> n2.matrix[game][0] >> n2.matrix[game][1] >> n2.matrix[game][2] >> n2.matrix[game][3] >> n2.matrix[game][4];
						break;
					case 2: inFile >> n3.matrix[game][0] >> n3.matrix[game][1] >> n3.matrix[game][2] >> n3.matrix[game][3] >> n3.matrix[game][4];
						break;
					}
				}
			}
			inFile.close();
		}
	}

	int choice = -1;
	int player = 0;

	while (choice != 4) {
		do {
			cout << "1. Print Player\n2. Print Player Stats\n3. Print Passer Ratings\n4. Exit\nEnter and option: ";
			cin >> choice;
			cout << endl;
		} while (choice > 4 || choice < 1);

		switch (choice) {
		case 1: cin >> player; printPlayer(player, n1, n2, n3);
				break;
		case 2: cin >> player; printPlayerStats(player);
				break;
			case 3: printPasserRatings();
				break;
			case 4: return 0;
		}
	}

	cin.clear();
	cin.ignore(255, '\n');
	cin.get();
	return 0;
}


So this is what I have already, the three functions are still in the works because I don't know how to send multiple structure variables to a function at once to be used. As you can see, I'm taking in values from a txt file and storing them in them in the structure because those are the instructions on my assignment. I then don't know how to send both n1, n2 and n3 over to a function to then use a switch statement to test which player is being mentioned and then displaying their information.

Lastly, is there a more effective way of using struct variables than what I'm doing with my input. I keep having to use switch statements for everything, but is there a simpler way of getting around this? Thanks for the help!
Last edited on
int matrix[games][stat]

I'm tempted to changed this is std::map<int, std::vector<int>> where the int map key is the game number and the std::vector<int> map value is the corresponding player stats for given game.
However before I proceed any further I'd like to know (a) are you allowed and/or willing to use std::map in this case and (b) how QBInfo.txt looks like. Can you post it here or, if too big, somewhere on-line?
... or even std::map<int, GameStats> where
1
2
3
4
5
6
7
8
struct GameStats
{
    int m_completions;
    int m_attempts;
    int m_yards;
    int m_touchdowns;
    int m_interceptions;
};

Last edited on
I'm guessing the input file looks like this:
3
Fred Bloggs
  57  46  44  23  50
  98  26  66  37  71
  79   4  18  11  22
  79  48  46  37  72
  17  50  63  69  53
  38  36  78  46  79
  96  47  71  61  26
  43  91  31  40  21
  76  65  13  76  81
  82  94  44  47  40
Suzy Smythe
  91  10  36  84  94
  10  18  76  63  78
  35  34  88  54  49
  58  59  45  27  77
  86  36  47  96  52
  33  70  14  88  52
  76  89  64  23  50
  24  27  75  39  62
  46  84  37  67  25
  68  73  32  56  60
Linda Jones
  24  57  61  19  62
  53  49  50  55  51
  80   8  70   0  92
  44  27  47  38  12
  18  53  47  81   2
   1  12  20  91  17
  91  51  12  66  48
  30  80  38  61  31
  16  52  25  59  78
  78   4  61  16  86

and proceeding on that basis, I read and displayed the data like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <cstdlib>
#include <fstream>

using namespace std;

const int games   = 10; //  total games played/person
const int stat    = 5;  //  total amount of stored stats
const int players = 3;  //  amount of players in the file

struct playerInfo {
    string name;
    //GAME X; completions; attempts; yards; touchdowns; interceptions
    int matrix[games][stat];
};

void printPlayer(const playerInfo& p)    
{
    cout << p.name << '\n';
    static string heading[stat] { "completions", "attempts", "yards", "touchdowns", "interceptions" };

    cout << " GAME";
    for (int col = 0; col<stat; ++col)
        cout << setw(14) << heading[col];
    cout << '\n'; 

    for (int row = 0; row < games; ++row)
    {
        cout << setw(5) << row+1;
        for (int col =0; col<stat; ++col)
            cout << setw(14) << p.matrix[row][col];
        cout << '\n';
    }
    cout <<  '\n';
}

int main() 
{
    playerInfo players[players];                        // array of players

    ifstream inFile("QBInfo.txt");

    if (inFile.fail()) {
        cout << "ERROR OPENING FILE";
        return 1;
    }
    
    int count = 0;
        
    if (inFile >> count)                                // read number of players
    {
        inFile.ignore(100, '\n');                       // discard rest of line
    } 
    
    for (int n=0; n<count; ++n)
    {
        getline(inFile, players[n].name);               // read name
        for (int game = 0; game < games; game++)        // read stats
        {
            for (int col = 0; col <stat; ++col)
                inFile >> players[n].matrix[game][col];
        }
        inFile.ignore(100, '\n');                       // discard rest of line
    }
    
    inFile.close();
    

    for (int i=0; i<count; ++i)                         // print all players
        printPlayer(players[i]);

}
The file looks just like what Chervil put, except with different numbers and names of course. Also I don't even know what std::map is, and my teacher wants us to use the concepts taught in class to get this done. Specifically she wants us to use structs and enums, bit I have no idea how I'd fit enums into this. Continuing with what Chervil put, I'll test the code later and see if I can work it in to do what I want it to for my assignment. Looks like you send over an array and then change it to the struct with a variable name by reference? Figuring that I've never seen this done before, I should probably go through the debugger and check out what's even happening there. And thanks for the help everyone!
Oops - I see a rather undesirable name clash in the code I posted. Don't know why I didn't spot this before.
 
playerInfo players[players];  


Even if the compiler can figure this out, its a really bad idea to have two completely different variables sharing the same name.
I might suggest changing
 
const int players = 3;
to
 
const int numplayers = 3;


and then the offending line becomes:
 
playerInfo players[numplayers];  

The choice of actual names are up to you of course
This works perfectly Chervil, thanks for the help! Now I just need to implement the rest of my functions and create the menu interface, which is easy stuff now that I can get all the information from the file into arrays and send that data to functions without errors or data loss.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <cstdlib>
#include <fstream>
using namespace std;

const int games = 10; //total games played/person
const int stat = 5; //total amount of stored stats
const int players = 3; //amount of players in the file

struct playerInfo {
	string name; //player name
	//GAME X; completions; attempts; yards; touchdowns; interceptions
	int matrix[games][stat]; //array of stats/game
};

void printPlayer(const playerInfo& p) {
	//Display the name of the player and initialize the header array
	cout << '\n' << p.name << '\n';
	static string heading[stat] = { "Completions", "Attempts", "Yards", "Touchdowns", "Interceptions" };

	//Display header
	cout << " GAME";
	for (int col = 0; col < stat; ++col)
		cout << setw(14) << heading[col];
	cout << '\n';

	//Print all the stats
	for (int row = 0; row < games; ++row) {
		cout << setw(5) << row + 1;
		for (int col = 0; col < stat; ++col)
			cout << setw(14) << p.matrix[row][col];
		cout << '\n';
	}
	cout << '\n';
}

void printPlayerStats(const playerInfo& p) {
	//initialize arrays for storing stat vals, and the headers
	int totalStats[stat] = {0, 0, 0, 0, 0};
	static string heading[stat] = { "Completions", "Attempts", "Yards", "Touchdowns", "Interceptions" };

	//Take in values to the array
	for (int row = 0; row < games; row++) {
		for (int col = 0; col < stat; col++) {
			if (row == 0) //first row check
				totalStats[col] = p.matrix[row][col];
			else
				totalStats[col] += p.matrix[row][col];
		}
	}
	cout << '\n' << p.name << '\n'; //display the name

	//Print the total stats
	for (int x = 0; x < stat; x++) 
		cout << heading[x] << ": " << totalStats[x] << endl;
	cout << endl;
}

double boundaries(double x) {
	//defaults the passer rating back to a default state if it passes a certain number
	if (x > 2.375)
		x = 2.375;

	if (x < 0.0)
		x = 0.0;

	return x; //returns the new number
}

void printPasserRatings(const playerInfo& p) {
	double totalStats[stat];

	for (int row = 0; row < games; row++) {
		for (int col = 0; col < stat; col++) {
			if (row == 0)
				totalStats[col] = p.matrix[row][col];
			else
				totalStats[col] += p.matrix[row][col];
		}
	}

	//Calculates every variable to the equation for a seamless calculating experience
	//totalStats[0] = Completions, [1] = Attempts, [2] = Yards, [3] = Touchdowns, [4] = Interceptions
	double a = ((totalStats[0] / totalStats[1]) - 0.3) * 5.0; a = boundaries(a);
	double b = ((totalStats[2] / totalStats[1]) - 3.0) * .25; b = boundaries(b);
	double c = (totalStats[3] / totalStats[1]) * 20.0; c = boundaries(c);
	double d = 2.375 - ((totalStats[4] / totalStats[1]) * 25.0); d = boundaries(d);

	cout << '\n' << p.name << '\n'; //print players name
	cout << "Passer Rating: " << ((a + b + c + d) / 0.06) << '\n'; //print the players passer rating
}

int main() {
	//Three players
	playerInfo playerKeeper[players];

	ifstream inFile("QBInfo.txt");

	//checks if you can't open te file
	if (inFile.fail()) {
		cout << "ERROR OPENING FILE";
		return 0;
	}

	int count = 0;

	if (inFile >> count)  //read number of players
		inFile.ignore(100, '\n');  //discard rest of line

	for (int n = 0; n < count; ++n) {
		getline(inFile, playerKeeper[n].name);  //read name
		for (int game = 0; game < games; game++) {  //read stats
			for (int col = 0; col < stat; ++col)
				inFile >> playerKeeper[n].matrix[game][col];
		}
		inFile.ignore(100, '\n');  //discard rest of line
	}

	inFile.close(); //closes the file since it no longer needs to be in use, or read in values

	//switch ladders for the infinite menu loop deal
	int choice = -1;
	int player = 0;

	while (choice != 4) {
		do {
			cout << "1. Print Player\n2. Print Player Stats\n3. Print Passer Ratings\n4. Exit\nEnter an option: ";
			cin >> choice;
			cout << endl;
		} while (choice > 4 || choice < 1);

		switch (choice) {
		case 1:
			cin >> player;
			printPlayer(playerKeeper[player - 1]);
			break;
		case 2:
			cin >> player;
			printPlayerStats(playerKeeper[player - 1]);
			break;
		case 3:
			for (int ply = 0; ply < players; ply++) {
				printPasserRatings(playerKeeper[ply]);
			}
			cout << endl;
			break;
		case 4:
			return 0; //closes the program
			break;
		}
	}

	cin.clear();
	cin.ignore(255, '\n');
	cin.get();
	return 0;
}


^The completed code for anyone that wants it!
Use the file text that Chervil wrote above i you want to run it!
Last edited on
With your while do while switch, it's easier to put the switch in a loop based on a bool Quit variable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bool Quit = false;
while (!Quit) {
     // call function to showmenu

     switch (choice) {
          // cases
          // ....
         case 4:
               Quit = true;
                break;

         //always provide default case to catch bad input
         default:
               std::cout << "Bad Input Try again\n";
               break;
    }


}
Topic archived. No new replies allowed.