struct print issue

Pages: 12
hello all I was having trouble with this structure that has data from a file read into it and im tring to print the contents of that structure but for some reason when i try to call back the original array "lines" it says that it is undefined.Where did go wrong on this ? ?

here is the file:
6
Team A,3,13,0
Team B,15,1,1
team C,9,7,1
Team D,10,6,1
Team E,7,9,0
Team F,11,5,1

here is the code:
if (input) {
input >> amt;
teamInfo * lines = new teamInfo[amt];

for (int i = 0; i < xamt; i++)
{
input.getline(mark[i].name, sizeof(teamInfo::name), ',');
input >> lines[i].w;
input.ignore(',');
input >> lines[i].l;
input.ignore(',');
input >> lines[i].pf;
}

input.close();
}
............

if (choice == A)
{
for (int i = 0; i < x; i++)
{
cout << lines[i].w;
}
}




Last edited on
The variable lines is declared within the scope of the open/closing braces of the if statement
1
2
3
if (input) {

}
When the closing brace is reached, the variable goes out of scope and no longer exists. (The memory allocated with new is still there, but there's no way to reach it, unless you stored the address somewhere outside that block).
ohh wups i see but now when i print it, all i see is memory garbage i dont think they are addresses.
You need to show more of the code. Please also use code tags
<> formatting button.
http://www.cplusplus.com/articles/jEywvCM9/
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
#include <iostream>
#include <iomanip>
#include <cctype>
#include <cstdlib>
#include <fstream>
#include <cstring>
using namespace std;

struct list{
	char name[40];
	int w;
	int l;
	bool pf;
};



int main() {
	int choice;
	ifstream input;
	int twins;
	int x;
	char filename[25];
	do
	{
		input.clear();
		cout << "Please enter the name of the input file." << endl;
		cout << "Filename: ";
		cin >> filename;
		input.open(filename);
		if (!input) {
			cout << "That is not a valid file.  Try again!\n";
		}
	} while (!input);

	
		input >> x;
		list * mark = new list[x];

		for (int i = 0; i < x; i++)
		{
			input.getline(mark[i].name, 40, ',');
			input >> mark[i].w;
			input.ignore(',');
			input >> mark[i].l;
			input.ignore(',');
			input >> mark[i].pf;
		}
		for (int i = 0; i < x; i++)
		{
			cout << mark[i].w;
			cout << mark[i].l<< endl;;
			cout << mark[i].pf;
		}
		input.close();
	

	do
	{
		cout << "Select one of the follwing choices: " << endl;
		cout << "\t1 - View the team Win/Loss records" << endl;
		cout << "\t2 - Show the teams with the least x wins" << endl;
		cout << "\t3 - List teams that made the playoffs" << endl;
		cout << "\t4 - Print the teams and their Win Loss Differentials" << endl;
		cout << "\t5 - Sort the teams by their Win Loss Differentials" << endl;
		cout << "\t0 - Exit the Program" << endl;
		cout << "----------------------------------------------------" << endl;
		cout << "Choice: ";
		cin >> choice;
		if (choice == 1)
		{
			cout << "Team W-L:" << endl;
			for (int i = 1; i < x; i++)
			{
				cout << mark[i].wins << endl;
			}
		}

my apologies for not knowing about the format.
Thanks for that.

Now this is getting more complete, there is a need to address some of the fine details, dotting the i's and crossing the t's as it were.

One thing which stands out is the use of input.ignore(','); at lines 44 and 46.

You might instead have done this:
1
2
char dummy;
input >> dummy.

that simply reads the first non-whitespace character into the variable, which has no further use.

On the other hand to use ignore(), there are a number of choices, the once you used ignores a fixed number of characters from the file. How many? Well the ASCII code for the character ',' is decimal 44, so that code will read and ignore the next 44 characters from the file, which is definitely not what you want.

You could just use input.ignore(); with no parameter, to ignore a single character - but it doesn't check whether it is whitespace or not. Another possibility is to use a number and a delimiter,
input.ignore(10, ','); which will ignore up to 10 characters, or until the delimiter ',' is found.
see http://www.cplusplus.com/reference/istream/istream/ignore/

I've gone into detail here, because you also need to ignore the newline character '\n' in two places
1. after reading the count x at line 37
2. after reading the bool pf at line 47.



alright that worked but for some reason the organization of the data dowsnt match that way it looks in the file, would i just need a \n after each of the bool statements? Also im not sure how i would exclude the \n in x because im only reading it into an dynamic array as a size.
Last edited on
oh wait i figured it out, but thank you very much!!
okay it all working great now but I have one last thing, when it comes to listing all the team names I need to separate them with commas and I am certain that I have to use a for loop but I'm unsure how to get rid of the last comma at the end.
also how would i compute ad store the win loss differential of each team?
when it comes to listing all the team names I need to separate them with commas and I am certain that I have to use a for loop but I'm unsure how to get rid of the last comma at the end.

This is a common type of situation. Here's a typical example scenario
1
2
3
4
5
6
7
    int arr[5] = { 2, 3, 8, 17, 6 };
    for (int i=0; i<5; ++i)
    {
        if (i > 0) 
            cout << ", ";
        cout << arr[i];
    }


Or a slight variation:
1
2
3
4
5
6
    const int size = 5;
    int arr[size] = { 2, 3, 8, 17, 6 };
    for (int i=0; i<size; ++i)
    {
        cout << arr[i] << (i==size-1 ? "\n" : ", ");
    }


also how would i compute ad store the win loss differential of each team?

I assume you mean the difference between w ans l here
1
2
3
4
5
6
struct list{
	char name[40];
	int w;
	int l;
	bool pf;
};


One possibility is to add another member to the struct:
1
2
3
4
5
6
7
struct list{
    char name[40];
    int w;
    int l;
    bool pf;
    int diff;
};
and then you'd have to calculate and store the value of diff, presumably just after reading that team's data from the file.

Another way, which is more C++ style, is to not bother with storing that value at all. Instead, define a member function like this:
1
2
3
4
5
6
7
struct TeamList {
    char namerino[20];
    int  winerino;
    int  losserino;
    bool thePLAYOFFS;
    int diff() { return winerino - losserino; }
};

and then when you want to get the value of the difference figure, instead of
 
    mark[i].diff // member variable 
it would be
 
    mark[i].diff() // member function 


Sorry about the change of variable names - I've been copying and pasting code from different places.


oh okay no worries but what if i need to implement the diff into an array that is the size of the data thats in the first line. Im trying to create a function that will organize the w/l diff in ascending order.
Last edited on
what if i need to implement the diff into an array
Well, create a separate array then, and store the value w-l into it.

Im trying to create a function that will organize the w/l diff in ascending order.
Ok, then sort the array. But here's question. Do you just want those values in ascending order, but are not interested in the name of the team which the data belongs to?
no i also need to have the name of the teams to be sorted with regard to their w/d differential
no i also need to have the name of the teams to be sorted with regard to their w/d differential


Yes - that's rather what I expected. In that case it would be much better to keep the value is the same struct with the other data, then the whole thing can be sorted in one go. Otherwise you end up having to sort multiple arrays in parallel, which is not really hard, but can be a bit clumsy and error-prone.

Still - if this is an exercise which you have been told to do in a particular way, then you don't have much choice.
ok so i created this function but now I need it to to be implemented into this if statement:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
else if (choice == 4)
		{
			for (int i = 0; i < x; i++)
			{
				
				if (mark[i].diff() > 0)
				{
					cout << mark[i].name << " +" << mark[i].diff() << endl;
				}
				else
				{
					cout << mark[i].name << " " << mark[i].diff() << endl;
				}
			}
		}



For some reason it isnt actually changing the order at all. Do i need to actualy compare the whole entire struct? also here is the function defenition:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
void teamSort(list[], int length)
{
	list temp;
	for (int i = 1; i < length; i++)
	{
		for (int j = 0; j < length - i; j++)
			if (list[j].diff() > list[j + 1].diff())
			{
				temp = list[j];
				list[j] = list[j + 1];
				list[j + 1] = temp;
			}
	}
}
The function teamSort() looks reasonable to me - though I've not tried to test it.
Does your program actually call that function, or is that what you are asking about?
Last edited on
yes it actually calls the function in a different if statement where i enter 5, but what its supposed to do is assort the order of the w/l diff in ascending order. When i enter 4 itll list just whats in the file and then when i enter 5 itll assort the order so when i enter 4 again it will print in the order i made it display in.
Last edited on
On second thoughts, I couldn't get your teamSort() function to compile. It looks broken to me.

I changed the header from
 
void teamSort(list[], int length)
to
 
void teamSort(list array[], int length)

and corresponding changes throughout.

You also might want to consider the showpos/noshowpos manipulator
1
2
3
4
5
    cout << showpos;
    for (int i = 0; i < x; i++)
    {
        cout << mark[i].name << " " << mark[i].diff() << endl;
    }

http://www.cplusplus.com/reference/ios/showpos/
Last edited on
Pages: 12