I am using xcode. I compile fine and then once it runs it opens the file successfully and then reads two values but the values do not go into the variable, as such it then skips the for loop and closes the file and returns from main.
#include <stdio.h>
#include <iostream>
#include <fstream>
//salesman struct
struct Salesman
{
char firstname[64];
char lastname[64];
char middleinitial[1];
int averagecents;
int totalcents;
};
int main(int argc, const char * argv[]) {
//setup variables
const char* inputFilename = "TheSales.txt";
int numberPeople = 0, weeksToHandlePerPerson = 0;
int workweeklength = 5;
int totalcents = 0;
//open file
std::ifstream fileHandle;
fileHandle.open(inputFilename, std::ios::in | std::ios::app);
if(!fileHandle)
perror ( "Stream Failed to open because: " );
fileHandle >> numberPeople; <----- does not get value
fileHandle >> weeksToHandlePerPerson; <----- does not get value
//do calculations
for ( int i = 0; i < numberPeople; ++i ) <---- this gets skipped
{
Salesman nextsalesman;
fileHandle >> nextsalesman.firstname;
fileHandle >> nextsalesman.middleinitial;
fileHandle >> nextsalesman.lastname;
float t1, t2, t3, t4, t5;
fileHandle >> t1 >> t2 >> t3 >> t4 >> t5;
nextsalesman.totalcents = 100 * ( t1 + t2 + t3 + t4 + t5 );
nextsalesman.averagecents = nextsalesman.totalcents / workweeklength;
totalcents += nextsalesman.totalcents;
//print calculations calculateNumbers()
std::cout << "salesman " << i << " total: $" << nextsalesman.totalcents / 100 << "." << nextsalesman.totalcents % 100
<< " and average $" << nextsalesman.averagecents / 100 << "." << nextsalesman.averagecents % 100 << std::endl;
int averagecents = totalcents / ( numberPeople * weeksToHandlePerPerson );
std::cout << "total for all: " << totalcents / 100 << "." << totalcents % 100 << " and average for all $" <<
averagecents / 100 << "." << averagecents % 100 << std::endl;
}
fileHandle.close(); <---- this works
return 0; <---- then we return main.
}
File:
3
2
firstName1 A lastName1
20.00 25.00 30.90 40.00 55.50
20.00 25.00 30.90 40.00 55.50
firstname2 B lastName2
30.00 24.00 45.00 67.00 65.50
56.90 87.00 43.50 56.98 55.40
firstName3 C lastName3
62.00 34.50 12.50 34.00 34.90
70.00 80.00 90.00 65.00 39.00
where first int is number of employees and second is number of weeks and each week is 5 days.
Actual output:
Expected output:
(fake output but expected form)
salesman1 total: 23424 avg: 3654
salesman2 total: 234 avg: 1654
salesman3 total: 424 avg: 364.
total for all: 5345683 and average for all: 34564564
when the program used to work the output was correct.
Your code is fine and works for me.
Are you using a text editor that writes out a unicode Byte Order Marker at the start of TheSales.txt? If so, then it will confuse your program.
You can use notepad++ to strip the BOM, as described here:
http://www.larshaendler.com/2015/01/20/remove-bom-with-notepad/
(TextWrangler on OSX might be a good alternative)
Related
I'm sorry this is long but I don't know what I should do to solve the problem
For the 0s being outputted I'm guessing its the contents of the other file but in 0s I just don't know how to get rid of them
This is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Users
{
int user_id;
string fname;
string lname;
char gender;
int age;
int phone;
string address;
};
struct Contacts
{
int user_id;
int contact_with;
int contact_start;
int contact_end;
int distance;
};
void discard_line(ifstream &in)
{
char c;
do{
in.get(c);
}while(c != '\n');
}
void users(ifstream &userFile, int size, struct Users user[])
{
cout << "-----------------------------------------------------\n";
cout << "UserID\tFname\t Lname\tGender\tAge\tPhone\tAddress" << endl;
cout << "-----------------------------------------------------\n";
for(int i = 0; i < size; i++)
{
cout << user[i].user_id << "\t" << user[i].fname << "\t" << user[i].lname << "\t" << user[i].gender << "\t" << user[i].age << "\t" << user[i].phone << "\t" << user[i].address << endl;
}
//total number of users
}
void contacts(ifstream &contactfile, int size, struct Contacts contact[])
{
cout << "-----------------------------------------------------\n";
cout << "UserID\tCon/With\tDuration(s)\tDistance(cm)" << endl;
cout << "-----------------------------------------------------\n";
for(int i = 0; i < size; i++)
{
int duration = contact[i].contact_end - contact[i].contact_start;
cout << contact[i].user_id << "\t" << contact[i].contact_with << "\t\t" << duration << "\t\t" << contact[i].distance << endl;
}
}
int main()
{
int option;
const int SIZE = 1000;
int index = 0;
Users user[SIZE];
Contacts contact[SIZE];
ifstream userFile("users.txt");
ifstream contactFile("contacts.txt");
if(!userFile)
{
cout << "The file is not found" << endl;
exit(1);
}
if(!contactFile)
{
cout << "The file is not found" << endl;
exit(1);
}
discard_line(userFile);
discard_line(contactFile);
while(!userFile.eof())
{
userFile >> user[index].user_id >> user[index].fname >> user[index].lname >> user[index].gender >> user[index].age >> user[index].phone >> user[index].address;
index++;
}
while(!contactFile.eof())
{
contactFile >> contact[index].user_id >> contact[index].contact_with >> contact[index].contact_start >> contact[index].contact_end >> contact[index].distance;
index++;
}
users(userFile,index,user);
contacts(contactFile,index,contact);
return 0;
}
and the output is this:
-----------------------------------------------------
UserID Fname Lname Gender Age Phone Address
-----------------------------------------------------
1001 Ray Dixon M 46 9364652 Lokia
1002 Bryan Green M 18 9579302 Drekena
1003 Justin Dixon M 33 9353533 Lokia
1004 Lester Byrd M 45 9534695 Nasilai
1005 Santos Larson M 53 9093177 Vunuku
1006 Bryan Cobb M 42 9905139 Narocivo
1007 Eddie Watson M 20 9610408 Nabua
1008 Wesley Barton M 27 9801864 Nasigatoka
1009 Victor Mason M 50 9855386 Nukutubu
1010 Ellis Cobb M 24 9389406 Narocivo
1011 Diana Ross F 27 9940148 Vunuku
1012 Amanda Carter F 43 9506743 Nasilai
1013 Maria Edwards F 53 9798534 Narocivo
1014 Maria Jenkins F 34 9352516 Lomanikoro
1015 Louise Davis F 55 9812126 Nasilai
1016 Sandra Sanders F 29 9369570 Tavuya
1017 Bonnie Roberts F 40 9689234 Nukui
1018 Melissa Harris F 29 9321235 Drekena
1019 Marilyn Parker F 56 9409221 Nukui
1020 Bonnie Lopez F 43 9342939 Nasigatoka
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
I'm trying to remove the 0s but I dont know how to do that. However when I take out the reading for either file it shows the correct output without the 0s
while(!userFile.eof())
{
userFile >> user[index].user_id >> user[index].fname >> user[index].lname >> user[index].gender >> user[index].age >> user[index].phone >> user[index].address;
index++;
}
while(!contactFile.eof())
{
contactFile >> contact[index].user_id >> contact[index].contact_with >> contact[index].contact_start >> contact[index].contact_end >> contact[index].distance;
index++;
}
users(userFile,index,user);
contacts(contactFile,index,contact);
Assuming index starts at zero.
Assuming userFile has 10 lines
Assuming contactFile has 10 lines
when you populate your user array in the while(!userFile.eof()) you increment index to 10... but then when doing the while(!contactFile.eof()) your index is no longer starting at zero... but rather starting where it left off at 10 and continues to 20
you need an additional index...
int uIndex = 0;
int cIndex = 0;
while(!userFile.eof())
{
userFile >> user[uIndex].user_id >> user[uIndex].fname >> user[uIndex].lname >> user[uIndex].gender >> user[uIndex].age >> user[uIndex].phone >> user[uIndex].address;
uIndex++;
}
while(!contactFile.eof())
{
contactFile >> contact[cIndex].user_id >> contact[cIndex].contact_with >> contact[cIndex].contact_start >> contact[cIndex].contact_end >> contact[cIndex].distance;
cIndex++;
}
users(userFile,uIndex,user);
contacts(contactFile,cIndex,contact);
Why is the program skipping the first line of every new deptnum?
I am trying to read from a file that looks like:
1 Suits 0300 100 092
1 Coats 0200 060 065
1 Shirts 1000 012 013
2 Dresses 0400 060 065
2 Coats 0185 184 200
2 Shoes 0600 040 030
3 Jeans 0200 040 035
3 Shoes 0200 030 034
4 Jeans 0300 042 043
The deptnum is the first column.
And when I write to the other file I get:
Blinn Discount Apparel Company
Inventory Evaluation
10/12/2018
Unit Cost Extended
Quantity Cost Market Cost Market Lower Cost
Mens Dept
Suits 300 100.00 92.00 30000.00 27600.00
Coats 200 60.00 65.00 12000.00 13000.00
Shirts 1000 12.00 13.00 12000.00 13000.00
Total $54000.00 $53600.00 $53600.00
Womens Dept
Coats 185 184.00 200.00 34040.00 37000.00
Shoes 600 40.00 30.00 24000.00 18000.00
Total $112040.00 $108600.00 $108600.00
Girls Dept
Shoes 200 30.00 34.00 6000.00 6800.00
Total $118040.00 $115400.00 $115400.00
Boys Dept
Total $118040.00 $115400.00 $115400.00
Total Inventory $393000.00
It skipped Womens Dept -> Dresses, Girls Dept -> Jeans, and Boys Dept -> Jeans.
Here is my code:
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
ifstream inFile;
ofstream outFile;
int x = 1, deptnum, quant,cost,mkt,extcost,extmkt,totalcost = 0,totalmkt = 0,
lowcost,totalInv = 0;
char item [15];
inFile.open("blinn.dat");
outFile.open("blinn.dout");
if (!inFile)
cout <<"\n\t\t Can't open data file: blinn.dat\n";
else {
outFile <<"\n\t Blinn Discount Apparel Company\n";
outFile <<"\t Inventory Evaluation\n";
outFile <<"\t 10/12/2018\n";
outFile <<"\n\t\t\t\t\t\t Unit Cost\t\t\t Extended\n";
outFile <<"\t\t Quantity Cost Market Cost Market Lower Cost";
while (x < 5)
{
if (x == 1)
outFile << "\nMens Dept";
else if (x == 2)
outFile << "\nWomens Dept";
else if (x == 3)
outFile << "\nGirls Dept";
else if (x == 4)
outFile << "\nBoys Dept";
else
break;
while (inFile >> deptnum >> item >> quant >> cost >> mkt)
{
if (deptnum == x){
extcost = quant * cost;
extmkt = quant * mkt;
outFile << left << "\n " << setw(7)<< item << " "
<< right << setw(4)<< quant << " "
<< right << setw(4) << cost << ".00 "
<< right << setw(3) << mkt << ".00 "
<< right << setw(5) << extcost<< ".00 "
<< right << setw(5) << extmkt << ".00";
totalcost += extcost;
totalmkt += extmkt;
if (totalcost > totalmkt)
lowcost = totalmkt;
else
lowcost = totalcost;
}else
break;
}
outFile << right << "\n Total\t\t\t\t\t $" << totalcost << ".00 $"
<< totalmkt << ".00 $"<< lowcost << ".00";
x += 1;
totalInv += lowcost;
}
}
outFile << "\nTotal Inventory\t\t\t\t\t\t $"<< totalInv<< ".00";
inFile.close ();
outFile.close ();
return 0;
}
What is wrong with my logic?
There is a problem with your logic:
if (deptnum == x) {
// do something
}
else {
break;
}
To achieve the else branch, you have already read a line that deptnum != x (the first line of every new deptnum) so at the next iterator, the current line is discarded by the next input line.
I almost have it working however, it is seperating the last names that start in caps and the ones that do not.
Example file
LastName FirstName DaysofRental BalanceDue
Smith Joe 15 100.50
Doe John 10 95.20
Anderson Paul 30 20.00
O'Donell Miriam 10 24.30
Foster Sam 30 15.00
Zom Pete 10 20.00
Mock Chilly 100 30
smitty Chris 200 200
xu Conor 1 200
anilo steve 0 0
What "Sorted" file is outputing
LastName FirstName DaysofRental BalanceDue
Anderson Paul 30 $20.00
Doe John 10 $95.20
Foster Sam 30 $15.00
Mock Chilly 100 $30.00
O'Donell Miriam 10 $24.30
Smith Joe 15 $100.50
Zom Pete 10 $20.00
anilo steve 0 $0.00
smitty Chris 200 $200.00
xu Conor 1 $200.00
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <fstream>
#include <string.h>
using namespace std;
const int STRINGSIZE = 30;
const int LISTSIZE = 10;
const int HEADSIZE = 4;
typedef char STRING30[STRINGSIZE];
typedef STRING30 NAMES[LISTSIZE];
int main(int argc, char** argv)
{
ofstream outfile;
outfile.open("sorted.txt");
int count,
count2,
mindex;
int rdays[LISTSIZE],
hrdays;
double baldue[LISTSIZE],
totalbaldue,
hbaldue,
tempnum;
NAMES first,
last,
header;
STRING30 mname,
tempname;
ifstream in;
in.open("invoice1_test1.txt");
//Input Section
if(in.is_open())
{
in >> header[0]
>> header[1]
>> header[2]
>> header[3];
int count = 0;
while(!in.eof())
{
in >> last [count]
>> first[count]
>> rdays[count]
>> baldue[count];
count++;
}
in.close();
}
else
{
cout << "File failed to open" << endl;
}
for(count = 0; count < LISTSIZE; count++)
{
mindex = count;
strcpy(mname, last[count]);
for(count2 = count; count2 < LISTSIZE; count2++)
{
if(strcmp(last[count2], mname) == -1)
{
mindex = count2;
strcpy(mname, last[count2]);
}
}
strcpy(tempname, last[count]);
strcpy(last[count], mname);
strcpy(last[mindex], tempname);
strcpy(tempname, first[count]);
strcpy(first[count], first[mindex]);
strcpy(first[mindex], tempname);
tempnum = rdays[count];
rdays[count]= rdays[mindex];
rdays[mindex]= tempnum;
tempnum = baldue[count];
baldue[count] = baldue[mindex];
baldue[mindex] = tempnum;
}
outfile << setiosflags(ios::showpoint | ios::fixed) << setprecision(2);
outfile << left << setw(20) << header[0] << setw(20) << header[1] << setw(20) << header[2] << setw(20) << header[3] << endl;
for(int count = 0; count<LISTSIZE; count++)
{
outfile << left << setw(20) << last[count] << setw(20) << first[count] << setw(20) << rdays[count] << "$" << setw(20) << baldue[count] << endl;
}
Use if (strcmpi(last[count2], mname) < 0); for the comparison, instead of if (strcmp(last[count2], mname) ==-1);
strcmpi() functions same as strcmp() but it is not case sensitive.
Also add exit(1) if ifstream in fails to open.
Convert all names to uppercase before storing.
I'm trying to convert written code used by shared_ptr to unique_ptr because in the code of its usage seems shared_ptr unnecessary and it will be an exercise with smart pointers. As far as I can detect with debugger the problem is on v.at(i)->push_back(t);. So, as soon as a value entered, the program crashes.
Working code with shared_ptr:
#include <iostream>
#include <iomanip>
#include <memory> // For smart pointers
#include <vector> // For vector container
#include <locale> // For toupper()
using std::vector;
using std::shared_ptr;
int main()
{
vector <shared_ptr<vector<double>>>records; // Temperature records by days
size_t day{ 1 }; // Day number
char answer{}; // Response to prompt
double t{}; // A temperature
while (true) // Collect temperatures by day
{ // Vector to store current day's temperatures created on the heap
auto pDay = std::make_shared<vector<double>>();
records.push_back(pDay); // Save pointer in records vector
std::cout << "Enter the temperatures for day " << day++
<< " separated by spaces. Enter 1000 to end:\n";
while (true)
{ // Get temperatures for current day
std::cin >> t;
if (t == 1000.0) break;
pDay->push_back(t);
}
std::cout << "Enter another day's temperatures (Y or N)? ";
std::cin >> answer;
if (toupper(answer) == 'N') break;
}
double total{};
size_t count{};
day = 1;
std::cout << std::fixed << std::setprecision(2) << std::endl;
for (auto record : records)
{
std::cout << "\nTemperatures for day " << day++ << ":\n";
for (auto temp : *record)
{
total += temp;
std::cout << std::setw(6) << temp;
if (++count % 5 == 0) std::cout << std::endl;
}
std::cout << "\nAverage temperature: " << total / count << std::endl;
total = 0.0;
count = 0;
}
}
Output:
23 34 29 36 1000
Enter another day's temperatures (Y or N)? y
Enter the temperatures for day 2 separated by spaces. Enter 1000 to end:
34 35 45 43 44 40 37 35 1000
Enter another day's temperatures (Y or N)? y
Enter the temperatures for day 3 separated by spaces. Enter 1000 to end:
44 56 57 45 44 32 28 1000
Enter another day's temperatures (Y or N)? n
Temperatures for day 1:
23.00 34.00 29.00 36.00
Average temperature: 30.50
Temperatures for day 2:
34.00 35.00 45.00 43.00 44.00
40.00 37.00 35.00
Average temperature: 39.13
Temperatures for day 3:
44.00 56.00 57.00 45.00 44.00
32.00 28.00
Average temperature: 43.71
The converted code with unique_ptr:
#include <iostream>
#include <vector>
#include <memory>
#include <iomanip>
using std::vector;
int main()
{ // Function scope starts here
// a vector(outside) holding unique_ptrs to a vector(inside) which type is double
vector<std::unique_ptr<vector<double>>> v;
size_t day{ 1 };
char answer{};
double t{};
while (true)
{
size_t i{};
auto pDay = std::unique_ptr<vector<double>>();
v.push_back(std::move(pDay));
std::cout << "Enter the temperatures for day " << day++
<< " separated by spaces. Enter 1000 to end:\n";
while (true)
{
std::cin >> t;
if (t >= 1000.0) break;
v.at(i)->push_back(t);
++i;
}
//std::cout << v.at(0)->at(0) << std::endl;
std::cout << "Enter another day's temperatures (Y or N)? ";
std::cin >> answer;
if (toupper(answer) == 'N') break;
}
double total{};
size_t count{};
day = 1;
std::cout << std::fixed << std::setprecision(2) << std::endl;
for (auto const& record : v)
{
std::cout << "\nTemperatures for day " << day++ << ":\n";
for (auto temp : *record)
{
total += temp;
std::cout << std::setw(6) << temp;
if (++count % 5 == 0) std::cout << std::endl;
}
std::cout << "\nAverage temperature: " << total / count << std::endl;
total = 0.0;
count = 0;
}
} // Function scope ends here
Your std::unique_ptr<std::vector<double>> doesn't point at anything. You'd need to initialize it with a pointer to a vector.
After adding records in the relative file, I am trying to update one field (the balance) of a given record(client) that the user provide the account number. The update happens in the file, but it is not properly done. The output shows that the update has affected other data, and it comes also with garbage. I cannot figure out the cause of the problem. Your help will be appreciated. I am using Dev-C++. The code followed by the output is below.
#include <iostream> // cin, cout
#include <iomanip>
#include <fstream>
#include <conio.h>
using namespace std;
#define SIZE 10
struct client // Client record
{ int account; // from 1 to SIZE
char name[20];
double balance;
};
void show_file(char filename[]) // Sequential display of all records
{
client c;
int n=0;
void *ptr;
ifstream IS(filename, ios::in); // Open for sequential read
if(!IS) {cerr << filename<< " file open error." << endl; exit(1);}
cout << "\n\nSHOW_FILE: The contents of file " << filename;
while(ptr=IS.read((char *)&c, sizeof(c)))
{
cout <<'\n'<< setw(3)<< ++n << setw(6) << c.account <<setw(20)
<< c.name << setw(10) << c.balance;
}
IS.close();
}
int main(void)
{ client c;
void *ptr;
int n=0, acc,number_of_records=SIZE, field1;
double new_balance, field3;
char *fname = "credit.dat"; char field2;
cout << "\nMAKE_FILE: Creating a blank relative file " << fname
<< " containing " << number_of_records << " records.";
fstream iof(fname, ios:: in | ios::out | ios::binary );
if(!iof) {cerr << "File open error." << endl; exit(1);}
client blank={0, "", 0.0}; // Create an empty client record
while(number_of_records--)
iof.write((char *)&blank, sizeof(blank));
cout << "\n\n\nFile has been succesfully created!"; //file is still empty, no records yet.
cout<<"\n\nenter the 10 customers into the file: "<< fname<<endl<<endl;
cout << "\nAccount[1.." << SIZE
<< "], Name, Balance (0 0 0 to exit)= ";
cin >> c.account >> c.name >> c.balance;
while(0 < c.account) // && c.account <= maxrec)
{
iof.seekp((c.account-1) * sizeof(client)); // position the pointer
iof.write((char *)&c, sizeof(c));
cout << "Account[1.."<< SIZE
<< "], Name, Balance (0 0 0 to exit)= ";
cin >> c.account >> c.name >> c.balance;
}
cout << "\n\nAccount number to apply changes on balance(0 to exit) = ";
cin >> acc;
/// while(0 < acc && acc <= SIZE)
if (0<acc && acc <= SIZE)
{
//cout << "\nPositioning at " << (acc-1) * sizeof(client)<< endl;
iof.seekg((acc-1) * sizeof(client)); // position the pointer
iof.read((char *)&c, sizeof(c));
if(c.account)
cout <<'\n'<< setw(6) << c.account <<setw(20)
<< c.name << setw(10) << c.balance;
new_balance=c.balance+0.05*(c.balance); //calculation of the new balance by adding interests of 5%
cout<<"\n\n\nnew balance after the 5% interest:"<<new_balance<<endl;
c.balance=new_balance;
cout<<"current new balance: "<<c.balance<<endl; //just to check if it will be displayed
//WHERE THE PROBLEM IS...
iof.seekg(0, ios::cur); //trying to stay in the current position to apply
//change on current balance
iof<<c.account << c.name << c.balance; //trying to update record with new balance
}
else cout << "\nEmpty record";
iof.close();
cout<<"\n\nFILE after THE UPDATE: "<<endl;
show_file (fname);
cout << "\n\n";
system("pause");
return 0;
}
*********************output**************************
MAKE_FILE: Creating a blank relative file credit.dat containing 10 records.
File has been succesfully created!
enter the 10 customers into the file: credit.dat
Account[1..10], Name, Balance (0 0 0 to exit)= 1 aaaa 2399
Account[1..10], Name, Balance (0 0 0 to exit)= 2 bbbb 4000
Account[1..10], Name, Balance (0 0 0 to exit)= 3 cccc 50
Account[1..10], Name, Balance (0 0 0 to exit)= 4 dddd 5000
Account[1..10], Name, Balance (0 0 0 to exit)= 5 eeee 180
Account[1..10], Name, Balance (0 0 0 to exit)= 0 0 0
Account number to apply changes on balance(0 to exit) = 3
3 cccc 50
new balance after the 5% interest:52.5
current new balance: 52.5
FILE after THE UPDATE:
SHOW_FILE: The contents of file credit.dat
1 1 aaaa 2399
2 2 bbbb 4000
3 3 cccc 50
41667457843 c52.5♫' 5000
5 5 eeee 180
6 0 0
7 0 0
8 0 0
9 0 0
10 0 0
Press any key to continue . . .
Ha ha ha, we must be in the same class...
You use seekg() to position pointer to read and seekp() to position pointer to write.
Like this as you did earlier in your file:
iof.seekp((c.account-1) * sizeof(client)); // position the pointer
iof.write((char *)&c, sizeof(c));
seekg = seek to get
seekp = seek to put - requ
good luck!