Basically my program is giving me a load of errors with my filereading program when trying to compile. The goal is to get the user to enter the threshold number and the strings that are equal to or greater than that threshold number will be outputted. The program fails at that because there are several errors with the code. How to fix the errors within the code?
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
int read_airports(string cities[], int threshold);
int main()
{
ifstream fin;
fin.open("airports.txt");
if (fin.is_open())
{
string cities[20];
int count, threshold;
count = read_airports(cities, threshold);
while(!fin.eof())
{
fin >> threshold;
cout << "Enter a threshold number" << endl;
cin >> threshold;
if (fin.good())
{
if (cities >= threshold)
{
cout << cities << endl;
}
}
}
fin.close();
}
return 0;
}
int read_airports(string cities[], int threshold)
{
}
Here is the text file where this code is based off of.
LAX Los-Angeles 40
JFK New-York 39
IAH Houston 26
LCY London 34
PAR Paris 15
TYO Tokyo 11
SEL Seoul 5
YYZ Toronto 28
[Warning: none of this code has been tested at all.]
I would structure the code rather differently.
I would create a structure for the data about each airport/city:
struct airport {
std::string abbreviation;
std::string city_name;
int threshold;
};
Then I'd overload operator>> to read one of those records from a stream, and operator<< to write one to a stream:
std::istream &operator>>(std::istream &is, airport &ap) {
return is >> ap.abbreviation >> ap.city_name >> ap.threshold;
}
std::ostream &operator<<(std::ostream &os, airport const &ap) {
return os << ap.abbreviation << "\t" << ap.city_name << "\t" << ap.threshold;
}
Then I'd write code to desired data from a file of those to standard output:
std::ifstream infile("airportdata.txt");
std::cout << "Please enter minimum threshold value: ";
int threshold;
std::cin >> threshold;
std::copy_if(std::istream_iterator<airport>(infile), {},
std::ostream_iterator<airport>(std::cout, "\n"),
[=](airport const &ap) { return ap.threshold > threshold; });
Related
so I have a program that makes use of a Registration, UNIT, Result and Date class to store and output some details in a new file. The order is as follows: File is read into registration where some values are stored, and then the rest of the input is sent to an array of objects of results. When it is sent to results, it reads into a UNIT object, then into a variable 'mark', and then to a date object lastly. Once sent to date, the program reads the day month and year, and that is the final input. My output file produces the first set of units correctly, however, after that it is all messed up. Can someone explain where I have gone wrong, I'd imagine in my input syntax/logic? I will only post the .cpp input and output functions for the sake of readability and as everything compiles just fine, but if you do need the .h and .cpp files of all classes let me know. Thanks in advance.
Result.cpp input and output function:
void Registration::readFile(istream &input){
long studentid1;
unsigned semester1;
input >> studentid1 >> semester1 >> count;
SetStudentID(studentid1);
SetSemester(semester1);
for(unsigned i = 0; i < count; i++)
input >> results[i];
}
void Registration::writeFile(ostream & os) const{
os << "Student ID: " << GetStudentID() << '\n'
<< "Semester: " << GetSemester() << '\n';
for(unsigned i = 0; i < count; i++)
os << results[i] << '\n';
}
UNIT.cpp input and output functions:
void UNIT::SetUnit(istream &input){
string nam;
string idd;
unsigned cred;
getline(input,nam, '\n');
getline(input,idd,'\n');
input >> cred;
SetName(nam);
SetID(idd);
SetCredits(cred);
}
void UNIT::GetUnit(ostream & os) const{
os << " Unit ID: " << GetID() << '\n'
<< " Unit Name: " << GetName() << '\n'
<< " Credits: " << GetCredits() << '\n';
}
Result.cpp i/o functions:
void Result::SetResult(istream &input){
UNIT unitobj1;
unsigned marks1;
Date date1;
input >> unitobj1 >> marks1 >> date1;
SetUnit(unitobj1);
SetMarks(marks1);
SetDate(date1);
}
void Result::GetResult(ostream &os) const{
os << GetUnit() << " Marks: " << GetMarks() << '\n' << GetDate();
}
Date.cpp i/o:
void Date::SetDate(istream &input){
unsigned day1;
string month1;
unsigned year1;
input >> day1 >> month1 >> year1;
SetDay(day1);
SetMonth(month1);
SetYear(year1);
}
void Date::GetDate(ostream &os) const{
os << " Date: " << GetDay() << " " << GetMonth() << " " << GetYear() << '\n';
}
rinput.txt (input file):
102234 962 3
Data Structures and Abstractions
ICT283
3 90 30 June 2016
Applied ICT Research Skills
BSC250
3 92 29 April 1993
Games Technology
ICT292
3 76 4 August 1998
routputnew.txt (outputfile):
Student ID: 102234
Semester: 962
Unit ID: ICT283
Unit Name: Data Structures and Abstractions
Credits: 3
Marks: 90
Date: 30 June 2016
Unit ID: Applied ICT Research Skills
Unit Name:
Credits: 0
Marks: 90
Date: 3395525844 7402640
Unit ID: 3 92 29 April 1993
Unit Name: BSC250
Credits: 0
Marks: 90
Date: 3395525844 7402640
Number of units = 3
Total credits = 3473594268
OK, Even without seeing your full source code, I will help you.
You have 2 major problems
You do not check, if an extraction operation (>>) failed or not
You have a problem with the endline charachter after extracting without std::getline
So, what will happen. Assume the following simple test program
#include <iostream>
#include <sstream>
std::istringstream testDataStream{ R"(1 2
string1
3 4
string2)" };
int main() {
int i1{}, i2{}, i3{}, i4{};
std::string s1{}, s2{};
testDataStream >> i1 >> i2;
std::getline(testDataStream, s1);
testDataStream >> i3 >> i4;
std::getline(testDataStream, s2);
// more code . . .
return 0;
}
First we will read i1 and i2 with correct information. The extractor operator reads until the next whitespace, but does not consume the '\n' at the end of the line. It has read i1 and i2, skipping the white space. Then stop. No more activity. Nothing will consume the '\n'.
If you now call std::getline it will start to read after the value 2 and will find a '\n'. Then it stops reading and returns an empty string. So, after the call to std::getline the std::string s1 will be empty, the '\n' will be consumed and the next position to read from is "string1".
And now we try testDataStream >> i3 >> i4;. But there is no 3 and 4. Remember: The position to read is still at "string1". So the extraction operation will fail and the failbit of the stream will be set.
But you do never test the failbit and so the rest of the program silently fails.
You can and should check the result of each extraction operation.
This can simply be done with
if (testDataStream >> i1 >> i2) {
// Good. Continue standard operation
}
else {
// Bad. Show error message and do error handling
}
Why does this work? The chained extratcion operation returns a reference to the stream at the end. And the stream has an overloaded bool operator. See here and here.
So, to test the state of the stream you can write always simply if (someStream).
OK, understood. But how can we get rid of the trailing '\n' at the end of the string. For that we have the function ignore. See the documentation in the link.
To fix the avoe code snippet we need to add ignore 2 times:
#include <limits>
#include <iostream>
#include <sstream>
std::istringstream testDataStream{ R"(1 2
string1
3 4
string2)" };
int main() {
int i1{}, i2{}, i3{}, i4{};
std::string s1{}, s2{};
testDataStream >> i1 >> i2;
testDataStream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(testDataStream, s1);
testDataStream >> i3 >> i4;
testDataStream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(testDataStream, s2);
// more code . . .
return 0;
}
And to show you, how all this can be implemented, I prepared a full working example for you.
Please see:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <iterator>
#include <limits>
#include <array>
// Function to check, if we have a valid month
constexpr std::array<std::string_view, 12> Months{ "January", "February", "March","April", "May", "June", "July","August", "September", "October","November", "December" };
bool isInValidMonth(const std::string& m) { return std::find(Months.begin(), Months.end(), m) == Months.end(); }
struct Unit {
// Data for one semester/class unit for a student
std::string id{};
std::string name{};
unsigned int credit{};
unsigned int mark{};
unsigned int dateDay{};
std::string dateMonth{};
unsigned int dateYear{};
// This will check, if the data that we have read is ok, and if not, set the fail bit of the stream
std::istream& sanityCheck(std::istream& is) {
// Check for non plausible data. If there is unplausible data anywhere
if (!is || credit > 500 || mark > 100 || dateDay == 0U || dateDay > 31 || dateYear < 1920 || dateYear > 2100 || isInValidMonth(dateMonth)) {
// Set the streams failbit
is.setstate(std::ios::failbit);
std::cerr << "\n*** Error: Problem while reading unit data\n";
}
return is;
}
// Overide extractor. Get Unit data
friend std::istream& operator >> (std::istream& is, Unit& u)
{
if (std::getline(std::getline(is, u.name), u.id) >> u.credit >> u.mark >> u.dateDay >> u.dateMonth >> u.dateYear)
// Eat up the trailing '\n'
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return u.sanityCheck(is);
}
// Overwrite inserter. Write unit data
friend std::ostream& operator << (std::ostream& os, const Unit& u) {
return os << "\tUnit ID:\t" << u.id << "\n\tUnit name:\t" << u.name << "\n\tCredits:\t" << u.credit << "\n\tMarks:\t\t"
<< u.mark << "\n\tDate:\t\t" << u.dateDay << " " << u.dateMonth << " " << u.dateYear << "\n";
}
};
struct Student {
// Student data
unsigned long id{};
unsigned long semester{};
std::vector<Unit> unit{};
// Override extractor: Read Student Data
friend std::istream& operator >> (std::istream& is, Student& s) {
s.unit.clear();
// Here will store the number of units that we need to read
size_t numberOfUnits{};
// Read, id and semester and numberOfUnits and check, if that was successfull
if (is >> s.id >> s.semester >> numberOfUnits) {
// Eat up the trailing '\n'
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Read all units. Call the extractor operator n times, but only if everything OK
for (size_t i = 0U; i < numberOfUnits && is; ++i) {
// Read a unit and check, if OK
if (Unit temp{}; is >> temp) {
// If OK, append the new unit to the student
s.unit.push_back(std::move(temp));
}
}
}
// Sanity check. We expect to have numberOfUnits
if (!is && s.unit.size() != numberOfUnits) {
// Set the streams failbit
is.setstate(std::ios::failbit);
std::cerr << "\n*** Error: Problem while reading student data\n";
}
return is;
}
// Override inserter: Write student data
friend std::ostream& operator << (std::ostream& os, const Student& s) {
os << "\n\nStudent ID:\t" << s.id << "\nSemester:\t" << s.semester << "\n\n";
std::copy(s.unit.begin(), s.unit.end(), std::ostream_iterator<Unit>(os, "\n"));
return os;
}
};
struct Register {
std::vector<Student> students{};
// Override extractor: Read Student Data
friend std::istream& operator >> (std::istream& is, Register& r) {
for (Student s{}; is && is >> s; ) if (is) r.students.push_back(s);
return is;
}
// Override inserter: Write complete Register
friend std::ostream& operator << (std::ostream& os, const Register& r) {
std::copy(r.students.begin(),r.students.end(), std::ostream_iterator<Student>(os, "\n"));
return os;
}
};
std::istringstream inputStream{ R"(102234 962 3
Data Structures and Abstractions
ICT283
3 90 30 June 2016
Applied ICT Research Skills
BSC250
3 92 24 April 1993
Games Technology
ICT292
3 76 4 August 1998
222222 22 2
Data Structures and Abstractions 2
ICT222
3 90 30 June 2016
Applied ICT Research Skills 2
BSC222
2 2 2 February 1993
)" };
int main() {
Register r;
inputStream >> r;
std::cout << r;
return 0;
}
Have fun . . .
I have a text file with some data in it as shown below
Employee No. Name Rate per hour Hours worked
100 Rishi 800 40
101 Albert 700 35
102 Richard 500 30
103 Roni 600 45
104 Reena 900 40
I need to display the emp no,name and salary
now i managed to display the table exactly as it is
i know to calculate the salary i need to multiply the rate and hours worked
but my teacher told us to do it by ourselves
i only managed to display it as it is in the text file
#include <iostream>
#include<fstream>
using namespace std;
int main(int argc, char** argv)
{
char ch;
ifstream inFile;
inFile.open("C:\\Users\\dolej\\OneDrive\\Desktop\\assignment.txt");
if (!inFile)
{
cout << "Unable to open file";
}
while (!inFile.eof())
{
inFile >> noskipws >> ch; //reading from file
cout << ch;
}
inFile.close();
return 0;
}
There are roundabout 42 million solutions for your problem :-)
Let me explain what part of the code needs to be improved. The basic problem is that you read the input character by character. You should take advantage from the std::istream's ability to read whatver variable type that you want and for which an inserter operator >> exists. For nearly all build in types such an operator exists. So, if you want to read an int, then you can do that via int i{0}; std::cin >> i. Same with other type of variables.
Please read in a book about the iostream library.
Then there are other improvements. Always initialize all variables. Use uniform initializer {}. Initializing a std::ifstream can automatically open a file. It will be closed by the destructor automatically. Do not use while (!inFile.eof()). Use while(infile >> something) instead.
Then, as I said, read whole variables and not only one char.
Example easy solution:
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <iomanip>
int main()
{
std::ifstream infile{ "r:\\assignment.txt" };
if (infile)
{
// Read the header line
std::string header{};
std::getline(infile, header);
// Now we want to read all data in the text file
// Define variables, where we will store the data
int employeeNumber{ 0 };
std::string name{};
int ratePerHour{ 0 };
int hoursWorked{ 0 };
// Print the header
std::cout << header << '\n';
// Read all lines in a loop
while (infile >> employeeNumber >> name >> ratePerHour >> hoursWorked)
{
// calculate the result
const int salary{ ratePerHour * hoursWorked };
// Print table
std::cout << std::left << std::setw(16) << employeeNumber << std::setw(16) << name <<
std::setw(16) << ratePerHour << std::setw(16) << hoursWorked <<
" Salary --> " << salary << '\n';
}
}
return 0;
}
Then, since you are programmin in C++. Use Objects. Objects group related things together and defines methods to operate on the data. So you can define a class and with that a new data type. And becuase the inserter and extractor operator do not exist for this user specific type, you need to create them.
In your main, you can read the complete file in a simpel statement. Then calculate the result and the print it.
See:
#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <iomanip>
class Payroll
{
public:
Payroll() {}
void calculate() { salary = ratePerHour * hoursWorked; }
friend std::istream& operator >> (std::istream& is, Payroll& p) {
return is >> p.employeeNumber >> p.name >> p.ratePerHour >> p.hoursWorked;
}
friend std::ostream& operator << (std::ostream& os, const Payroll& p) {
return os << std::left << std::setw(16) << p.employeeNumber << std::setw(16) << p.name <<
std::setw(16) << p.ratePerHour << std::setw(16) << p.hoursWorked << std::setw(16) << p.salary;
}
private:
int employeeNumber{ 0 };
std::string name{};
int ratePerHour{ 0 };
int hoursWorked{ 0 };
int salary{ 0 };
};
int main()
{
// Define variable and automatically open it.
// Will be closed by destructor, when infile goes out of scope
std::ifstream infile{ "r:\\assignment.txt" };
// If the file is open ( !operator of ifstream is overlaoded )
if (infile)
{
// Read the header line
std::string header{};
std::getline(infile, header);
// Define a vector of Payroll. Use range the constructor of the vector to read all data from file
std::vector<Payroll> payroll{ std::istream_iterator<Payroll>(infile), std::istream_iterator<Payroll>() };
// For each payroll element in the vector of payrolls: Calculate the salary
std::for_each(payroll.begin(), payroll.end(), [](Payroll & p) {p.calculate(); });
// Output Result:
std::cout << header << " " << "Salary\n";
std::copy(payroll.begin(), payroll.end(), std::ostream_iterator<Payroll>(std::cout, "\n"));
}
return 0;
}
Take your time and try to understand line by line . . .
I'm new to C++. I have a file named test.txt with following data
2
Salman Khan
20 100000 4.75 1000
Aamir khan
30 200000 5.25 1000
where
the first line is the number of user records,
the second line is Name separated by space, and
the third line consists of years, amount, rate, amount per month that the user is qualified.
I want to calculate formula and show into a table.
so far i've done is as follow:
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
struct Customers
{
char first_name[50];
char last_name[30];
int years;
float amount;
float interest_rate;
float amount_per_month;
};
int main() {
Customers cus;
int sum = 0;
string x,line;
string fileName = "";
ifstream inFile;
string firstLine;
int numberOfCustomers = 0;
cout << "Enter File Name: \n";
cin >> fileName;
cout << "Reading File : '"+ fileName+"'" << endl;
inFile.open(fileName);
if (!inFile) {
cout << "Unable to open file";
exit(1); // terminate with error
}
if (inFile.good())
{
getline(inFile, firstLine);
numberOfCustomers = stoi(firstLine);
cout << "Available Loan Applications : " << numberOfCustomers << endl;
}
while (inFile >> x) {
cout << x << endl;
cin >> cus.first_name;
}
inFile.close();
return 0;
}
I'm trying to store data to structure and then calculate, i need help in storing data to structure.
You can use stream extraction and stream insertion operators to read/write custom datatypes:
#include <cstddef> // std::size_t
#include <cstdlib> // EXIT_FAILURE
#include <iterator> // std::istream_iterator<>
#include <vector> // std::vector<>
#include <string> // std::string
#include <fstream> // std::ifstream
#include <iostream> // std::cout, std::cerr, std::ostream, std::istream
using namespace std;
struct Customer {
string first_name, last_name;
int years;
float amount, interest_rate, amount_per_month;
};
// define a stream extraction operator that takes a Customer on the right hand side
// usage examples: std::cin >> customer;
// file >> customer;
istream& operator>>(istream &is, Customer &customer)
{
// don't write directly into the members of Customer to not leave
// the object in a flunky state if extraction fails for some value.
string first_name, last_name;
int years;
float amount, interest_rate, amount_per_month;
if (!(is >> first_name >> last_name >> years >> amount >> interest_rate >> amount_per_month))
return is; // if extraction of a value fails end here
// if we reach here all values have been read successfully and can be
// assigned to the customer:
customer = { first_name, last_name, years, amount, interest_rate, amount_per_month };
return is;
}
// define a stream insertion operator that takes a Customer on the right hand side
// usage examples: std::cout << customer;
// file << customer;
ostream& operator<<(ostream &os, Customer const &customer)
{
os << customer.first_name << ' ' << customer.last_name << '\n' << customer.years << ' '
<< customer.amount << ' ' << customer.interest_rate << ' ' << customer.amount_per_month;
return os;
}
int main()
{
cout << "Enter filename: ";
string fileName;
cin >> fileName;
ifstream inFile{ fileName }; // define variables as close to where they're
// used. Use the constructor where app-
// ropriate - here to open the file.
if (!inFile.is_open()) { // if the file couldn't be opened
cerr << "Unable to open \"" << fileName << "\" for reading!\n\n";
return EXIT_FAILURE; // exit main() returning a value that
} // indicates an error
cout << "Reading file \"" + fileName + "\":\n";
size_t numCustomers;
if (!(inFile >> numCustomers)) { // read the number of customers before-
// hand since this value is not part of
// a customer record.
cerr << "Couldn't read number of customers from \"" << fileName << "\"!\n\n";
return EXIT_FAILURE;
}
// use an istream_iterator that will use our stream extraction operator
// to read customers from inFile until it reaches EOF or an error occurs.
vector<Customer> Customers{ istream_iterator<Customer>{ inFile },
istream_iterator<Customer>{} };
if (numCustomers != Customers.size()) { // check if the number of customers
// specified in the file matches
// the number of customers we
// were able to extract.
cerr << "Number of customers specified in \"" << fileName
<< "\" does not match the number of customers read!\n\n";
return EXIT_FAILURE; // if the numbers don't match there was an error
} // while reading the records from the file
for (auto const &c : Customers) // just to check print the customers
std::cout << c << '\n';
}
Output:
Enter File Name: test.txt
Reading file "test.txt":
Salman Khan
20 100000 4.75 1000
Aamir khan
30 200000 5.25 1000
I tried earlier to use a for loop to put data in but became too problematic. So I tried to use a while loop, it works but when I tried to debug it it continued to put -858993460 into every slot. The .dat file is in the right spot and opens.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct record
{
int item_id;
string item_type;
float item_price;
int num_stock;
string item_title;
string item_author;
int year_published;
};
void read_all_records(record records[], int &valid_entries);
int num_inventory_of_type(record records[], string type, int &valid_entries);
const int max_array = 100;
int main()
{
int valid_entries = 0;
record records[max_array];
read_all_records(records, valid_entries);
cout << "Stock Report" << endl;
cout << "------------" << endl;
int book = num_inventory_of_type(records, "book", valid_entries);
cout << "Book's In Stock: " << book << endl;
int cd = num_inventory_of_type(records, "cd", valid_entries);
cout << "CD's In Stock: " << cd << endl;
int dvd = num_inventory_of_type(records, "dvd", valid_entries);
cout << "DVD's In Stock: " << dvd << endl;
return 0;
}
void read_all_records(record records[], int &valid_entries)
{
ifstream invfile;
invfile.open("inventory.dat");
if (!invfile.is_open())
{
cout<<"file open failed";
exit(1);
}
while(invfile.good() && valid_entries < max_array)
{
invfile >> records[valid_entries].item_id >> records[valid_entries].item_type
>> records[valid_entries].item_price >> records[valid_entries].num_stock
>> records[valid_entries].item_title >> records[valid_entries].item_author
>> records[valid_entries].year_published;
if(!invfile.good())
break;
valid_entries++;
}
invfile.close();
}
int num_inventory_of_type(record records[], string type, int &valid_entries)
{
int count = 0;
int holder = 0;
for (int count = 0; count<valid_entries; count++);
{
if (records[count].item_type == type)
{
holder+=records[count].num_stock;
}
}
return holder;
}
the .dat file is
123456
book
69.99
16
Problem_Solving_With_C++
Walter_Savitch
2011
123457
cd
9.99
32
Sigh_No_More
Mumford_and_Sons
2010
123458
dvd
17.99
15
Red_State
Kevin_Smith
2011
123459
cd
9.99
16
The_Church_Of_Rock_And_Roll
Foxy_Shazam
2012
123460
dvd
59.99
10
The_Walking_Dead_Season_1
Robert_Kirkman
2011
all are on new lines, no spaces.
Basically it should start, run the read_all_records function and put the .dat data into the array. However, I put the cout << records[count].item_id; in the while loop just to see if the data was actually going in, and I get -858993460 each time. After that it should run the next function 3 times and return how many of each books there are.
You used the integer type int on item_price. invfile >> records[count].item_price will then only extract 69 instead of 69.99, thus resulting in a error when you try to extract the year_published.
Use a float or double instead.
struct record
{
int item_id;
string item_type;
float item_price;
int num_stock;
string item_title;
string item_author;
int year_published;
};
/* skipped identical lines */
while(invfile.good() && count < max_array)
{
invfile >> records[count].item_id >> records[count].item_type
>> records[count].item_price >> records[count].num_stock
>> records[count].item_title >> records[count].item_author
>> records[count].year_published;
cout << records[count].item_price << endl;
if(!invfile.good())
break;
cout << records[count].item_id << endl;
count++;
}
invfile.close();
Note that you have an extra semicolon in for (int count = 0; count<max_array; count++);. I guess you didn't intend this, so remove it.
This isn't a direct answer to the problem, but perhaps it will go away after a refactoring:
std::istream& operator>>(std::istream& is, record& r) {
return is >> r.item_id >> r.item_type >> … >> r.year_published;
}
int main () {
if (std::ifstream invfile("inventory.dat")) {
std::vector<record> records((std::istream_iterator<record>(invfile)),
std::istream_iterator<record>());
num_inventory_of_type(records, "dvd");
num_inventory_of_type(records, "cd");
num_inventory_of_type(records, "book");
}
}
If you still want to print out each record as you read it, the code can be rearranged as follows:
std::vector<record> records;
for (std::istream_iterator<record> i(invfile);
i != std::istream_iterator<record>(); ++i)
{
records.push_back(*i);
std::cout << i->item_id << "\n";
}
You need to change int item_price; to a float so -> float item_price;
and as mentioned above you need to swap the count++; and cout << records[count].item_id line.
After these two changes it will work properly.
struct record
{
int item_id;
string item_type;
float item_price; // <--- Needs to be a float
int num_stock;
string item_title;
string item_author;
int year_published;
};
// This order is required because you are storing in the current 'count' record and then you need to print it. Then increment the count to store the next record
cout << records[count].item_id;
count++;
Why doesn't this code want to load all the values from a text file? It only loads the first object's items correctly but after that it starts going weird. Here is the code:
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
class Location
{
public:
Location()
{
locName = "No Name";
locDesc = "No Description";
locID = 0;
}
friend ostream& operator <<(ostream& outs, const Location & showMe)
{
// keeping output same as input...
outs << showMe.locName << endl;
outs << showMe.locDesc << endl;
outs << showMe.locID << endl;
return outs;
}
friend istream& operator >>(istream& ins, Location & inLoc)
{
getline(ins, inLoc.locName);
getline(ins, inLoc.locDesc);
ins >> inLoc.locID;
return ins;
}
private:
string locName;
string locDesc;
int locID;
};
int main()
{
ifstream inFile;
inFile.open("loc_data.txt");
if (inFile.fail())
{
cout << "\nCould not open the input file!";
exit(1);
}
Location fileLoc[10];
int i = 0;
while (inFile.good())
{
inFile >> fileLoc[i];
i++;
}
for (int j = 0; j < 10; j++)
cout << fileLoc[j];
return 0;
}
The input file is:
Town Hall
Main venue for functions
1
City Park
Outdoor venue
2
Train Station
Commuting point
3
Local Airport
Long distance travel
4
And the output is:
Town Hall
Main venue for functions
1
City Park
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
I have a suspucion that getline is responsible for this but do not know enough to be sure, however I would really like to know why this is happening and not just a 'fix'.
Your first problem is that this line doesn't extract the newline character:
ins >> inLoc.locID;
This means that the getline in for the second Location is extracting the rest of the line after 1 - i.e. an empty string - for the name.
This means that you are quickly getting out of sync with the lines that you want to read.
You should also consider changing your while loop, as it stands you check whether the stream is "good" before extracting a new location but you do not check whether the extraction was successful, you assume that the extraction works.
This works:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <sstream>
using namespace std;
class Location
{
public:
Location()
{
locName = "No Name";
locDesc = "No Description";
locID = 0;
}
friend ostream& operator <<(ostream& outs, const Location & showMe)
{
// keeping output same as input...
outs << showMe.locName << endl;
outs << showMe.locDesc << endl;
outs << showMe.locID << endl;
return outs;
}
friend istream& operator >>(istream& ins, Location & inLoc)
{
getline(ins, inLoc.locName);
getline(ins, inLoc.locDesc);
std::stringstream ss;
std::string s;
getline(ins, s);
ss << s;
ss >> inLoc.locID;
return ins;
}
private:
string locName;
string locDesc;
int locID;
};
int main()
{
ifstream inFile;
inFile.open("loc_data.txt");
if (inFile.fail())
{
cout << "\nCould not open the input file!";
exit(1);
}
Location fileLoc[10];
int i = 0;
while (inFile.good())
{
inFile >> fileLoc[i];
i++;
}
for (int j = 0; j < 10; j++)
cout << fileLoc[j];
return 0;
}
I believe the issue is with this line: ins >> inLoc.locID;
The problem is that when you read this value in with the >> operator it is leaving the next line charactor in the buffer, this then causes the read loop to end (as can be seen if you step through it).
To get around this i think you need to purposely empty this charactor from the buffer or use getline and convert the input (with validation i would hope!) to a number from a string.
Hope this helps,