Errors with Variables in Function

Okay, I have one question split up into three parts. I have a school assignment that requires me to read input from a .txt and input each line into a struct array and then print that stuff a certain way depending on what the user wants. I have all my functions working (mostly) but when I try to insert variables into them I'm getting problems. My ifstream is not translating properly from main to its usage in the function and my int value is having troubles that I didn't even know existed.
Here's the code

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

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

const int MAX_FLIGHTS = 100;

struct Flight {
	string from;
	string to;
	string seatClass;
	double price;
	int flightIndex;
};

int readTickets(ifstream, int &, Flight);
void printTickets(Flight, int);
void printTicketsFromTo(Flight, int);
int findCheapestTicket(Flight, int);

int main()
{
Flight flights[MAX_FLIGHTS];
int nFlights = 0;
    ifstream fin;
        fin.open("tickets.txt");
        if (!fin){
            cout << "The file could not open." << endl;
    return 1;
    }
    readTickets(fin, &nFlights, flights);


	return 0;
}

int readTickets(ifstream fin, int &nFlights, Flight flights[0]){
	while(fin.good()); {
		getline(fin, flights[nFlights].from, '\n') &&
			getline(fin, flights[nFlights].to, '\n') &&
			fin >> flights[nFlights].seatClass >> ws &&
			fin >> flights[nFlights].price >> ws;
        flights[nFlights].flightIndex = nFlights;
        nFlights++;
	}
return nFlights;
}

void printTickets(Flight flights[0], int maxflights){
	int currentFlights = 0;
	
	cout << "From              To                Seat type  Price " << endl;
	while (currentFlights < maxflights) {
		cout << setw(18) << flights[currentFlights].from << flights[currentFlights].to
		<< setw(11) << flights[currentFlights].seatClass << setw(6) << flights[currentFlights].price << endl;
		currentFlights++;
	}
}

void printTicketsFromTo(Flight flights[0], int maxflights){
	string fromCity,
		toCity;
	int currentFlights = 0;
	cout << "Enter departure city: ";
	cin >> fromCity;
	cout << "Enter arrival city: ";
	cin >> toCity;
	cout << "From              To                Seat type  Price " << endl;
	while (currentFlights < maxflights) {
		if (fromCity == flights[currentFlights].from && toCity == flights[currentFlights].to) {
			cout << setw(18) << flights[currentFlights].from << flights[currentFlights].to
			<< setw(11) << flights[currentFlights].seatClass << setw(6) << flights[currentFlights].price << endl;
		}
	currentFlights++;
	}
	cout << "-------------------------------------------";
}

void findCheapestTicket(Flight flights[0], int maxflights){
	bool swap;
	int temp;
	do{
		swap = false;
		for (int i = 0; i < maxflights; i++) {
			if (flights[i].price > flights[i + 1].price) {
				temp = flights[i].flightIndex;
				flights[i].flightIndex = flights[i + 1].flightIndex;
				flights[i + 1].flightIndex = temp;
				swap = true;
			}
		}
	} while (swap);
}


I haven't finished the main code yet but that's not a problem. The three errors are:
error: use of deleted function 'std::basic_ifstream<_CharT, _Traits>::basic_ifstream(const std::basic_ifstream<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]'|
error: invalid conversion from 'int*' to 'int' [-fpermissive]
error: cannot bind rvalue '(int) (&nFlights)' to 'int&'

I'm using the CodeBlocks IDE. Any input on these three problems would be really helpful!
Last edited on
Lines 18 and 39 should be
ifstream &
not just
ifstream


readTickets() is expecting a single Flight object (according to line 18)
You are sending a whole array of it on line 33.
No idea what you are doing with it on line 39.


I haven't checked anything else.
Ok. What I want it to do is the getline for flights[nFlights] until the file ends, return the number of nFlights so I know how many structs I have in the array, and then use nFlights as my max for everywhere else that I'm counting through my struct array. Unfortunately, if on line 39 I just do readTickets(Flight flights) then it gives me an error for lines 41-44 where it doesn't understand flights[nFlights]. So my thought is I can initialize it at 0 on line 39 and then it will count up in the while loop. Also, the problems it's giving me with int &nFlights are leaving me clueless. I've never seen these before.
Last edited on
If I remove the & in front of nFlights in line 33 then I get the following error:
undefined reference to `readTickets(std::basic_ifstream<char, std::char_traits<char> >&, int&, Flight)'
However, the two errors of invalid conversion and rvalue binding go away.
Last edited on
Hello malibuwiley,

Your program uses an input file. You need to post the input file or a fair sample, so that everyone can see and use the same information.

What I am looking at the problems start at line 33. The second parameter is sending the address of the int not its value. On line 39 the second parameter is passing the variable by reference, so it is meant to use the variable defined in "main" and if the value is changed in the function it will be changed in "main".

The third parameter of line 39 is expecting a single element of the array, but you are sending the whole array not a single element.

In the function:
1
2
3
4
5
6
7
8
9
10
11
12
13
int readTickets(ifstream fin, int &nFlights, Flight flights[0])
{
    while (fin.good());
    {
        getline(fin, flights[nFlights].from, '\n') &&
            getline(fin, flights[nFlights].to, '\n') &&
            fin >> flights[nFlights].seatClass >> ws &&
            fin >> flights[nFlights].price >> ws;
        flights[nFlights].flightIndex = nFlights;
        nFlights++;
    }
    return nFlights;
}

There is a problem with the while condition. "fin" will always be good until the file stream is closed even if the "eof" bit is set. The first "std::getline()" or all of the inputs should be in the while condition, but at least the first "std::getline()".

In lines 7 and 8 I believe the "ws" is in the wrong place, but it is not needed with formatted input in the first place. A line like fin >> flights[nFlights].price will ignore any leading white space until it finds something that is not a white space.

After line 8 I would use fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>. or something similar to eat the "\n" at the end.

Something to start with while I go over the program.

Andy
Hello malibuwiley,

There is more that need changed than just 1 & from the second parameter.

In the end I had to change the prototype, function call and the function definition on line 39.

I am not sure what to make up for the input file, but I will give it a try and run the code.

Andy
The input file:
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
Austin
Houston
E
109.99

Austin
New York
B
352

Washington D.C.
Seattle
PE
139.2

Austin
New York
E
94

Dallas
Austin
1st
93.5

Washington D.C.
Seattle
E
110

Chicago
Las Vegas
B
149

Austin
New York
1st
210


Unfortunately, I have to work basically within the headers I have. It's a requirement from the teacher, so my code can't be quite as concise as it might otherwise be. Also, I tried
 
while (!fin.eof)

and
 
while (fin.!eof)

and neither worked. The IDE had a lot of trouble understanding the exclamation point.
 
    readTickets(fin, nFlights, flights[0]);

Is the change you're talking about for the int removing the & symbol from in front of nFlights? If so, what do I do about the errors "invalid conversion from 'int*' to 'int' [-fpermissive]" and "cannot bind rvalue '(int)(& nFlights)' to 'int&'"?
It appears the most obvious thing has yet to be said: the semi-colon you have on your OP's line 40 makes it an infinite loop [apologies if I missed it], regardless of whether you use 'eof' or 'good', which you don't need to use either of because there's a better option altogether -- instead of,
1
2
3
4
5
6
7
8
	while(fin.good()); {
		getline(fin, flights[nFlights].from, '\n') &&
			getline(fin, flights[nFlights].to, '\n') &&
			fin >> flights[nFlights].seatClass >> ws &&
			fin >> flights[nFlights].price >> ws;
        flights[nFlights].flightIndex = nFlights;
        nFlights++;
	}

Have it loop based on the successful extraction of data:
1
2
3
4
5
6
7
8
	while(
		getline(fin, flights[nFlights].from, '\n') &&
			getline(fin, flights[nFlights].to, '\n') &&
			fin >> flights[nFlights].seatClass >> ws &&
			fin >> flights[nFlights].price >> ws) {
        flights[nFlights].flightIndex = nFlights;
        nFlights++;
	}


Formatted a bit more sanely,
1
2
3
4
5
6
7
	while(getline(fin, flights[nFlights].from, '\n') &&
	      getline(fin, flights[nFlights].to, '\n') &&
	      fin >> flights[nFlights].seatClass >> ws &&
	      fin >> flights[nFlights].price >> ws) {
		flights[nFlights].flightIndex = nFlights;
		nFlights++;
	}
Last edited on
Ok. I've updated the code so everything is where it should be, including my sentinel while loop.
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

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

const int MAX_FLIGHTS = 100;

struct Flight {
	string from;
	string to;
	string seatClass;
	double price;
	int flightIndex;
};

int readTickets(ifstream &, int &, Flight);
void printTickets(Flight, int);
void printTicketsFromTo(Flight, int);
int findCheapestTicket(Flight, int);

int main()
{
Flight flights[MAX_FLIGHTS];
int nFlights = 0;
int userChoice = 0;
string fromChoice,
    toChoice;
    ifstream fin;
        fin.open("tickets.txt");
        if (!fin){
            cout << "The file could not open." << endl;
    return 1;
    }
    readTickets (&fin, &nFlights, flights[0]);
    cout << "Select the action: " << endl;
    cout << "1) Display all flights" << endl;
    cout << "2) Show the flights that depart from a given city" << endl;
    cout << "3) Find the cheapest ticket" << endl;
    cout << "4) Exit the program" << endl;
    cin >> userChoice;
    while (userChoice != 4)
    if (userChoice >= 1 || userChoice <= 3){
    switch(userChoice){
        case 1 :
         printTickets(flights, nFlights);
         cout << "Select the action: " << endl;
         cout << "1) Display all flights" << endl;
         cout << "2) Show the flights that depart from a given city" << endl;
         cout << "3) Find the cheapest ticket" << endl;
         cout << "4) Exit the program" << endl;
         cin >> userChoice;
         break;
        case 2 :
         printTicketsFromTo(flights, nFlights);
         cout << "Select the action: " << endl;
         cout << "1) Display all flights" << endl;
         cout << "2) Show the flights that depart from a given city" << endl;
         cout << "3) Find the cheapest ticket" << endl;
         cout << "4) Exit the program" << endl;
         cin >> userChoice;
         break;
        case 3 :
         findCheapestTicket(flights, nFlights);
         cout << "Select the action: " << endl;
         cout << "1) Display all flights" << endl;
         cout << "2) Show the flights that depart from a given city" << endl;
         cout << "3) Find the cheapest ticket" << endl;
         cout << "4) Exit the program" << endl;
         cin >> userChoice;
         break;
        default :
         cout << "Your decision was not present within the confines of the presented choices." << endl;
         cout << "Select the action: " << endl;
         cout << "1) Display all flights" << endl;
         cout << "2) Show the flights that depart from a given city" << endl;
         cout << "3) Find the cheapest ticket" << endl;
         cout << "4) Exit the program" << endl;
         cin >> userChoice;
        }
    }
    else
     cout << "Exiting the program";

	return 0;
}

int readTickets(ifstream &fin, int &nFlights, Flight flights[0]){
    while(getline(fin, flights[nFlights].from, '\n') &&
	      getline(fin, flights[nFlights].to, '\n') &&
	      fin >> flights[nFlights].seatClass >> ws &&
	      fin >> flights[nFlights].price >> ws) {
		flights[nFlights].flightIndex = nFlights;
		nFlights++;
	}
	return nFlights;
}

void printTickets(Flight flights[0], int maxflights){
	int currentFlights = 0;

	cout << "From              To                Seat type  Price " << endl;
	while (currentFlights < maxflights) {
		cout << setw(18) << flights[currentFlights].from << flights[currentFlights].to
		<< setw(11) << flights[currentFlights].seatClass << setw(6) << flights[currentFlights].price << endl;
		currentFlights++;
	}
}

void printTicketsFromTo(Flight flights[0], int maxflights){
	string fromCity,
		toCity;
	int currentFlights = 0;
	cout << "Enter departure city: ";
	cin >> fromCity;
	cout << "Enter arrival city: ";
	cin >> toCity;
	cout << "From              To                Seat type  Price " << endl;
	while (currentFlights < maxflights) {
		if (fromCity == flights[currentFlights].from && toCity == flights[currentFlights].to) {
			cout << setw(18) << flights[currentFlights].from << flights[currentFlights].to
			<< setw(11) << flights[currentFlights].seatClass << setw(6) << flights[currentFlights].price << endl;
		}
	currentFlights++;
	}
	cout << "-------------------------------------------";
}

void findCheapestTicket(Flight flights[0], int maxflights){
	bool swap;
	int temp;
	do{
		swap = false;
		for (int i = 0; i < maxflights; i++) {
			if (flights[i].price > flights[i + 1].price) {
				temp = flights[i].flightIndex;
				flights[i].flightIndex = flights[i + 1].flightIndex;
				flights[i + 1].flightIndex = temp;
				swap = true;
			}
		}
	} while (swap);
}

It has four error messages:
|36|error: invalid initialization of non-const reference of type 'std::ifstream& {aka std::basic_ifstream<char>&}' from an rvalue of type 'std::ifstream* {aka std::basic_ifstream<char>*}'
|47|error: could not convert '(Flight*)(& flights)' from 'Flight*' to 'Flight'
^ this error is repeated on line 56 and 65. I know if I initialize the struct array flights at 0 that the errors will go away. However, if I do that, will the programs work correctly by counting up flights[nFlights] or flights[currentFlights], or will the initialization at 0 screw up the function?
If I remove the &fin and enter fin on line 36, the error changes to:
error: invalid conversion from 'int*' to 'int' [-fpermissive]
Last edited on
When you do &fin (as a unary operator), you are taking the address of fin, and you're getting a pointer. This is a different type than a reference (ifstream&) -- it's just a bit confusing because both use the '&' symbol, but in two different ways. If the '&' symbol is with the type it means "reference to that type", and you can just pass fin to the function, not &fin.
Same with 'nFlights' -- just pass it as nFlights, not &nFlights.

If you're trying to pass an array, just make the function parameter look like:
1
2
3
4
void func(Flights arr[])
{
   // ...
}


See: http://www.cplusplus.com/doc/tutorial/arrays/
(arrays as parameters section)
Last edited on
If I rewrite the functions so that they don't loop and keep the loop in the main array, will that solve the problem?
Last edited on
Here is the syntax from the calling side and function side:
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
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

const int MAX_FLIGHTS = 100;

struct Flight {
	string from;
	string to;
	string seatClass;
	double price;
	int flightIndex;
};

int readTickets(ifstream&, int&, Flight[]);

int main()
{
    Flight flights[MAX_FLIGHTS];
    int nFlights = 0;
    
    ifstream fin("file.txt");
    readTickets(fin, nFlights, flights);
}

int readTickets(ifstream& fin, int& nFlights, Flight flights[]){
    // ...
    return 0;
}


If I rewrite the functions so that they don't loop and keep the loop in the main array, will that solve the problem?
You mean to avoid passing the array as a parameter? Sure, you can do that, but just look at how I'm passing the array, or look at the tutorial for passing/using arrays.
Last edited on
Okay! There are no errors and the code now runs! There is just one last problem. My findCheapestTicket option in the switch does not do anything and freezes the program. If anyone could point out what part of the function is not working I would appreciate, because I barely understand the bubble sort or binary search that I put in.
Here is the part of the switch:
1
2
3
4
5
6
7
8
     case 3 :
         cout << "The cheapest ticket costs " << findCheapestTicket(flights, nFlights) << endl;
         cout << "Select the action: " << endl;
         cout << "1) Display all flights" << endl;
         cout << "2) Show the flights that depart from a given city" << endl;
         cout << "3) Find the cheapest ticket" << endl;
         cout << "4) Exit the program" << endl;
         cin >> userChoice;

and here is the updated function:
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
double findCheapestTicket(Flight flights[], int maxflights){
	bool swap;
	int temp;
    int size = 8,
        first = 0,
        last = size - 1,
        middle,
        position = -1,
        target = 0;
	bool found = false;
	do{
		swap = false;
		for (int i = 0; i < maxflights; i++) {
			if (flights[i].price > flights[i + 1].price) {
				temp = flights[i].flightIndex;
				flights[i].flightIndex = flights[i + 1].flightIndex;
				flights[i + 1].flightIndex = temp;
				swap = true;
			}
		}
	} while (swap);
    while (first <= last && !found){
        middle = (first + last) / 2;
        if (flights[middle].flightIndex == target) {
            found = true;
            position = middle;
        } else if (target < flights[middle].flightIndex){
            last = middle - 1;
        } else {
        first = middle + 1;
        }
    }
    return flights[position].price;
}

And then here is the exe:
1
2
3
4
5
6
7
Select the action:
1) Display all flights
2) Show the flights that depart from a given city
3) Find the cheapest ticket
4) Exit the program
3

Assuming that maxflights is the size of the array, then:

 
if (flights[i].price > flights[i + 1].price) {


accesses the element of the array one past its end!

What are the given requirements for finding the cheapest ticket? The easiest way is to keep details of the cheapest ticket as data is read from the file.

There's no need to have code to display the menu after each option. Use a loop a display it once.

Consider:

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
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;

const int MAX_FLIGHTS {100};

struct Flight {
	string from;
	string to;
	string seatClass;
	double price {};
	int flightIndex {};
};

size_t readTickets(ifstream&, Flight[], double&);
void printTickets(const Flight[], size_t);
void printTicketsFromTo(Flight[], size_t);

int main()
{
	ifstream fin;

	fin.open("tickets.txt");
	if (!fin) {
		cout << "The file could not open.\n";
		return 1;
	}

	Flight flights[MAX_FLIGHTS] {};
	double cheapest {};
	const auto nFlights {readTickets(fin, flights, cheapest)};

	while(true) {
		cout << "\n1) Display all flights\n";
		cout << "2) Show the flights that depart from a given city\n";
		cout << "3) Find the cheapest ticket\n";
		cout << "4) Exit the program\n";
		cout << "Select the action: ";

		int userChoice {};
		cin >> userChoice;

		switch (userChoice) {
			case 1:
				printTickets(flights, nFlights);
				break;

			case 2:
				printTicketsFromTo(flights, nFlights);
				break;

			case 3:
				cout << "The cheapest ticket price is " << cheapest << '\n';
				break;

			case 4:
				cout << "Exiting the program\n";
				return 0;

			default:
				cout << "Your decision was not present within the confines of the presented choices.\n";
		}
	}
}

size_t readTickets(ifstream& fin, Flight flights[], double& cheap) {
	size_t nFlights {};
	cheap = 999999999999.0;

	for (; getline(fin, flights[nFlights].from) &&
			getline(fin, flights[nFlights].to) &&
			fin >> flights[nFlights].seatClass >> ws &&
			fin >> flights[nFlights].price >> ws; ++nFlights) {
		if (flights[nFlights].price < cheap)
			cheap = flights[nFlights].price;

		flights[nFlights].flightIndex = nFlights;
	}

	return nFlights;
}

void printTickets(const Flight flights[], size_t maxflights) {
	cout << "From              To                Seat type  Price\n";

	for (size_t currentFlights {}; currentFlights < maxflights; ++currentFlights)
		cout << left << setw(18) << flights[currentFlights].from << setw(18) << flights[currentFlights].to
			<< setw(11) << flights[currentFlights].seatClass << setw(6) << flights[currentFlights].price << '\n';
}

void printTicketsFromTo(Flight flights[], size_t maxflights) {
	string fromCity, toCity;

	cout << "Enter departure city: ";
	getline(cin >> ws, fromCity);

	cout << "Enter arrival city: ";
	getline(cin, toCity);

	cout << "From              To                Seat type  Price " << endl;

	for (size_t currentFlights {}; currentFlights < maxflights; ++currentFlights)
		if (fromCity == flights[currentFlights].from && toCity == flights[currentFlights].to)
			cout << left << setw(18) << flights[currentFlights].from << setw(18) << flights[currentFlights].to
				<< setw(11) << flights[currentFlights].seatClass << setw(6) << flights[currentFlights].price << '\n';

	cout << "----------------------------------------------------\n";
}


Topic archived. No new replies allowed.