Regarding Structs and Using Them With Array's - c++

I'm trying to write a program that will take every line from a text file and load the value into an array. For some reason however, when I try create a dynamic array and try to put information in any position beyond 0, the information from from position zero gets copied over and I can't seem to understand why. Specifically in this program its in the readInventory function I have written. Basically, why can't I copy one struct to the other?
Sample from file
A009 Strawberries_Case 0 12.50 8
4028 STRAWBERRIES_PINT 0 0.99 104
4383 MINNEOLAS 1 0.79 187.3
4261 Rice_1_LB_Bag 0 0.49 107
Code from program
#include <iostream>
#include <string>
#include <cstring>
#include <iomanip>
#include <fstream>
using namespace std;
struct Product
{
string PLU;
string name;
int salesType;
double unitPrice/*rice per pound*/;
double inventory;
};
struct ItemSold
{
string PLU;
string name;
double cost;
};
Product *inventoryLevels = new Product[100];
ItemSold *itemsSold = new ItemSold[100];
bool readInventory(string filename, int &numberOfItems);
double checkout(int inventoryLength);
double price(string PLU, double units);
int typeCheck(string PLU, int inventoryLength);
string nameCheck(string PLU, int inventoryLength);
int main()
{
int numberOfItems = 0;
string filename = "products.txt";
int total;
if (readInventory(filename, numberOfItems))
{
cout << "Inventory file has errors, please make changes before continuing" << endl << endl;
}
total = checkout(numberOfItems);
cout << total;
system("pause");
}
double checkout(int inventoryLength)
{ // Function that will be used to perform the checkout by the user
string PLU = "1";
double units/*pounds*/;
int salesType;
int counter = 0;
int temp;
double total = 0;
while (PLU != "0")
{
cout << "Enter a PLU: ";
cin >> PLU;
itemsSold[counter].PLU = PLU;
if (PLU == "0")
{
// do nothing
}
else
{
itemsSold[counter].name = nameCheck(PLU, inventoryLength);
if (typeCheck(PLU, inventoryLength) == 0)
{
cout << " Enter the number of units being bought: ";
cin >> units;
while (units > inventoryLevels[counter].inventory)
{
cout << "You have entered in more units than we have on hand \n Please reduce the number of units being bought\n";
cout << " Enter the number of units being bought: ";
cin >> units;
}
itemsSold[counter].cost = price(PLU, units);
inventoryLevels[counter].inventory -= units;
}
else
{
cout << "Enter the number of pounds of the item being bought: ";
cin >> units;
itemsSold[counter].cost = price(PLU, units);
while (units > inventoryLevels[counter].inventory)
{
cout << "You have entered in more pounds than we have on hand \n Please reduce the number of pounds being bought\n";
cout << "Enter the number of pounds of the item being bought: ";
cin >> units;
}
inventoryLevels[counter].inventory -= units;
}
counter++;
}
}
temp = counter;
while (temp >= 0)
{
total += itemsSold[temp].cost;
temp--;
}
return total;
}
string nameCheck(string PLU, int inventoryLength)
{
for (int k = 0; k < inventoryLength; k++)
{
if (inventoryLevels[k].PLU == PLU)
{
return inventoryLevels[k].name;
}
}
return "We are currently out of stock of this item.";
}
int typeCheck(string PLU, int inventoryLength)
{
for (int k = 0; k < inventoryLength ; k++)
{
if (inventoryLevels[k].PLU == PLU)
{
return inventoryLevels[k].salesType;
}
}
}
double price(string PLU, double units)
{ //
double price;
for (int k = 0; k < 100; k++)
{
if (inventoryLevels[k].PLU == PLU)
{
price = units * (inventoryLevels[k].unitPrice);
return price;
}
}
}
bool readInventory(string filename, int &numberOfItems)
{
// File object
fstream inventory;
// Some temp variable used to validate information is still in file while it is being transfered to array
//string temp;
// Open the inventory file
inventory.open(filename);
// Will temporarily hold the properties of an item until loaded onto the array
Product temp;
// Counter will allow for a new item to be stored onto the next available location in the array
int counter = 0;
// Will demonstrate whether or not there is an error
int error = 0;
// Store items and their properties in the global array
while (inventory >> temp.PLU >> temp.name >> temp.salesType >> temp.unitPrice >> temp.inventory)
{
// Checks to see if they
if ((temp.PLU.at(0) > 57) || (temp.PLU.at(1) > 57) || (temp.PLU.at(2) > 57) || (temp.PLU.at(3) > 57))
{
error++;
}
else
{
inventoryLevels[numberOfItems].PLU = temp.PLU;
inventoryLevels[numberOfItems].name = temp.name;
inventoryLevels[numberOfItems].salesType = temp.salesType;
inventoryLevels[numberOfItems].unitPrice = temp.unitPrice;
inventoryLevels[numberOfItems].inventory = temp.inventory;
numberOfItems++;
counter++;
}
}
// If there is no error return true
if (error == 0)
{
return false;
}
// If there is an error return false
else if (error > 0)
{
return true;
}
}

When you assign values here,
while (inventory >> temp.PLU >> temp.name >> temp.salesType >> temp.unitPrice >> temp.inventory)
Am I right to assume that the input file is in the format (since you're assigning each line to the variables?
line 1: Some string you want assigned to PLU
line 2: Some string you want assigned to name
line 3: Some Int you want assigned to salestype
..........
..........
line n:string PLU

Related

C++ Infinite while loop if given wrong type for condition

[UPDATED] I have the following code in C++ (skipping the non-necessary details):
#include <iostream>
using namespace std;
int main() {
double value;
double sum = 0;
double max, min;
string msg = "Enter next value (-1) to end: ";
int validCounter = 0;
do{
cout << msg;
cin >> value; // Values assumed to be numbers
}
while (value <= 0 and value != -1);
if (value > 0.0){sum+= value, max = value, min = value, validCounter = 1;} // Initial values of min, max, validCounter = 1
while (value != -1){
cout << msg;
cin >> value;
// Only take positive values into consideration for stats
if (value > 0) {
validCounter++;
sum += value;
if (value > max) { max = value; }
if (value < min) { min = value; }
}
}
cout << to_string(validCounter) + " valid value(s) entered" << endl;
if (validCounter > 0){
cout << "Minimum: " + to_string(min) << endl;
cout << "Maximum: " + to_string(max) << endl;
cout << "Moyenne: " + to_string(sum/validCounter) << endl;
}
return 0;
}
However when prompted to enter a value (supposed to be a number for simplicity, this is a beginners program) if the value entered is not a double the while loop starts to display the input prompt infinitely. Why is this? Is it due to the fact that comparing String != -1 (or any other non int/double type) causing the loop to reiterate? I am quite confused here.
replace
do{
cout << msg;
cin >> value; // Values assumed to be numbers
}
while (value <= 0 and value != -1);
by
do {
cout << msg;
if (!(cin >> value)) {
string dummy;
cin.clear(); // to be able to read double
cin >> dummy; // to remove the non float
value = 0;
}
while (value <= 0 and value != -1);
you need to clear the error to be able to read again, then to bypass the wrong input, may be you can also just read a character, decide what to do in case of an error
Example :
#include <iostream>
using namespace std;
int main()
{
double value;
do {
cout << "value please" << endl;
if (!(cin >> value)) {
string dummy;
cin.clear();
cin >> dummy;
value = 0;
}
} while (value <= 0 and value != -1);
cout << "valid double :" << value << endl;
return 0;
}
Compilation and execution :
% ./a.out
value please
aze
value please
-12
value please
12
valid double :12

Multiple file project & Function in C++

I am trying to practice the multiple file project (creating .cpp files and also .h files) and functions together.I have some functions for different kinds of shapes which is in different .cpp files and a .h file (my Functions.h) with the prototypes of those functions. I created another .cpp file (tools.cpp) where I have all bunch of functions (such as- getInt, getFloat, getBool, getBoundedInt, getWidth etc) so that I can also use that one in my other projects as well and also for that tools.cpp file. I have tools.h file with the prototypes.
Now, I want to make another function (allFunctionController) which will handle all these different kinds of function (like- taking user input, checking input valid or invalid, help function for user, call the shape functions etc). And, there would be another function to allow user to repeat all these things and my main function will only call this one. The screenshot that I provided would be more clear to understand.
[screenshot]
tools.cpp :-
// Tools.cpp
#include"Tools.h"
#include<string>
#include<iostream>
using namespace std;
namespace tools
{
int width( int value )
{
bool isNegative = value < 0;
int spaceForSign;
if ( isNegative )
{
spaceForSign = 1;
value = -value;
}
else
spaceForSign = 0;
int digitCount = 0;
int digits = value;
do
{
// pull one digit off and count it;
++digitCount;
// if I wanted to look at the digit before throwing away:
int digit = digits % 10;
digits = digits / 10; // remove one digit
} while ( digits > 0 );
return digitCount;
}
char getChar(string prompt)
{
while (true)
{
char userInput;
cout << prompt;
cin >> userInput;
cin.ignore(999,'\n');
if ( !cin.fail() ) return userInput;
cin.clear();
cin.ignore(999,'\n');
cout << "try again" << endl;
}
}
int getInt(string prompt)
{
while (true)
{
int userInput;
cout << prompt;
cin >> userInput;
cin.ignore(999,'\n');
if ( !cin.fail() ) return userInput;
cout << "input failure, try again";
cin.clear();
cin.ignore(999,'\n');
}
}
int getBoundedInt( string prompt, int lowBound, int highBound )
{
while (true)
{
int userInput = getInt(prompt);
if ( lowBound <= userInput && userInput <= highBound )
return userInput;
cout << "must be in range " << lowBound << " to "
<< highBound << ", try again" << endl;
}
}
float getFloat(string prompt)
{
while (true)
{
float userInput;
cout << prompt;
cin >> userInput;
cin.ignore(999,'\n');
if ( !cin.fail() ) return userInput;
cout << "input failure, try again";
cin.clear();
cin.ignore(999,'\n');
}
}
string getString(string prompt)
{
while (true)
{
string userInput;
cout << prompt;
cin >> userInput;
cin.ignore(999,'\n');
if ( !cin.fail() ) return userInput;
cout << "input failure, try again";
cin.clear();
cin.ignore(999,'\n');
}
}
string getLine(string prompt)
{
while (true)
{
string userInput;
cout << prompt;
getline(cin, userInput);
if ( !cin.fail() ) return userInput;
cout << "input failure, try again";
cin.clear();
cin.ignore(999,'\n'); // whatever caused fail
}
}
bool isLowerCase( char c )
{
return 'a' <= c && c <= 'z';
}
bool isUpperCase( char c )
{
return 'A' <= c && c <= 'Z';
}
bool isLetter( char c )
{
return isLowerCase(c) || isUpperCase(c);
}
char getLetter(string prompt)
{
while (true)
{
char userInput = getChar(prompt);
if ( isLetter(userInput) )
return userInput;
cout << "letters only, please" << endl;
}
}
bool getBool(string prompt)
{
while (true)
{
switch ( getChar(prompt) )
{
case 'y': case 'Y': return true;
case 'n': case 'N': return false;
}
cout << "y or n please" << endl;
}
}
}
tools.h:-
// Tools.h
#ifndef TOOLS_LOCK
#define TOOLS_LOCK
#include<string>
namespace tools
{
int getInt(std::string prompt);
int width( int value );
char getChar(std::string prompt);
int getInt(std::string prompt);
int getBoundedInt( std::string prompt, int lowBound, int highBound );
float getFloat(std::string prompt);
std::string getString(std::string prompt);
std::string getLine(std::string prompt);
bool isLowerCase( char c );
bool isUpperCase( char c );
bool isLetter( char c );
char getLetter(std::string prompt);
bool getBool(std::string prompt);
}
#endif
My functions.h:-
// My functions.h
namespace myFunctions
{
void allFunctionController ();
void solidRectangle (int size);
void hollowRectangle (int userChoiceOfSize);
void solidTriangleFacingNorthEast (int size);
void hollowTriangleFacingNorthEast (int size);
void solidTriangleFacingSouthWest (int size);
void hollowTriangleFacingSouthWest (int size);
}
I am only adding here the hollow and solid rectangle code. But there are more shape function in my project.
hollowRectangle.cpp:-
#include"My functions.h"
#include<iostream>
using namespace std;
namespace myFunctions
{
void hollowRectangle (int size)
{
int row, column;
for (row = 1; row <= size; row++)
{
if (row > 1 && row < size)
{
cout << "*";
for (column = 2; column < size; column++)
{
cout << ' ';
}
cout << "*";
}
else
{
for (column = 1; column <= size; column++)
{
cout << "*";
}
}
}
cout << endl;
cout << endl;
cout << "Please press enter to finish...";
cin.ignore(999,'\n');
return;
}
}
solidRectangle.cpp:-
// Program for the solid rectangle
#include"My functions.h"
#include<iostream>
using namespace std;
namespace myFunctions
{
int solidRectangle (int size)
{
int row, column;
for (row = 1; row <= size; row++)
{
for (column = 1; column <= size; column++)
{
cout << "*";
}
cout << endl;
}
cout << endl;
cout << "Please press enter to finish...";
cin.ignore(999,'\n');
return 0;
}
}
allFunctionController:- I screwed up here.
// This function will control all other functions.
#include"My functions.h"
#include"Tools.h"
#include<iostream>
using namespace std;
void allFunctionController ()
{
using namespace tools;
{
int size = getBoundedInt ("Please enter the size", 1, 75);
}
}
using namespace myFunctions;
{
void getHelp ()
{
int size,userInput;
cin >> userInput;
switch (userInput)
{
case 1:
solidRectangle (size);
}
}
}
I want to know how to handle all these header files and use the function in my allFunctionController function.
I didn't write my main function yet. Please let me know if there is anything wrong in my posting either code or attachment. Thanks in advance.

Access reading violation when trying to use existing struct array

I am writing a program for my class. My program is supposed to create a passenger list. obviously, the list has to be created first, and that option in my program works fine. However when trying to access the second function(pressing B) gives me the following error in the debugger:
Exception thrown at 0x00CD4A76 in ConsoleApplication13.exe: 0xC0000005: Access violation reading location 0x00000000.
I guess that means I am trying to read into an unallocated area in the memory, therefore, the struct array I am using was not created. I am confused since the first option does work, and I am passing the same pointer to both functions therefore the pointer points to the array created in function A.
#include <iostream>
#include <string>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
struct date
{
int year;
int day;
int month;
};
struct seat
{
int row;
char place;
};
struct pass
{
char * passname;
date bookdate;
seat location;
};
int lastindex;
int initList(pass *p, int x);
int addPass(pass *p, date *D, pass *newpass, int length);
void main()
{
pass *p = {};
int length = 0;
char choice;
do {
cout << "Welcome to FlightDesigner2017.\nEnter one of the following keys to continue:\nA: Create a list of passengers.\nB: Add a passenger to the flight.\n";
cin >> choice;
switch (choice)
{
case 'A':
{
int x;
cout << "How many passengers are on your flight? \n";
cin >> x;
length = initList(p, x);
break;
}
case 'B':
{
pass *newpass=0;
date *D = 0;
switch (addPass(p, D, newpass, length))
{
case '1':
cout << "Passenger successfully added."; break;
case '-3':
cout << "No seats available."; break;
case '-1':
cout << "Seat taken. Try again."; break;
case '-2':
cout << "Passenger is already on the flight."; break;
}
break;
}
}
}
while (choice=!0);
}
int addPass(pass *p, date *D, pass *newpass, int length)
{
#define TAKEN -1
#define SAMENAME -2
#define NOSEATS -3
#define SUCCESS 1
for (int init = 0; init < length; init++)
{
int counter=0;
for (int j = 0; j < length; j++) //empty seats check
{
if (strcmp(p[j].passname , NULL)!=0)
counter++;
}
if (counter == length)
return NOSEATS;
cout << "Enter a seat and row (seat A to F, row 1 to 50): \n"; //taken check
cin >> newpass->location.place >> newpass->location.row;
cout << "\nWhat is the flight date (DD/MM/YYYY)? \n";
cin >> D->day >> D->month >> D->year;
for (int k = 0; k < length; k++)
{
if (D->day == p[k].bookdate.day && D->month == p[k].bookdate.month && D->year == p[k].bookdate.year
&& p[k].location.place == newpass->location.place && p[k].location.row == newpass->location.row)
return TAKEN;
}
cout << "What is the passenger name? \n"; // name check
cin >> newpass->passname;
for (int i = 0; i < length; i++)
{
if (strcmp(newpass->passname,p[i].passname)==0)
return SAMENAME;
}
strcpy(newpass->passname, p[init].passname);
p[init].location.place = newpass->location.place;
p[init].location.row = newpass->location.row;
p[init].bookdate.year = D->year;
p[init].bookdate.month = D->month;
p[init].bookdate.day = D->day;
char ans;
cout << "Enter another passenger? (Y/N)\n";
cin >> ans;
if (ans == 'N')
return SUCCESS;
}
return SUCCESS;
}
int initList(pass *p, int length)
{
p = new pass[length];
for (int i = 0; i < length; i++)
p[i].passname = NULL;
return length;
}
Any explanation on how can I fix this error will help. thanks in advance.

Why is my function endlessly looping

#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
void add(string names[], int section[], int grade[]);
void printRecords(const string names[], const int sections[], const int grades[], int size);
void insertionSort(int numbers[], int size);
void display(const int numbers[], int size);
int main(){
//command
string command;
//add
string names[20] = { "" };
int sections[20];
int grades[20];
cout << "Enter a command (add, print, drop, sort, average, quit):\n";
cin >> command;
while (command != "quit"){
if (command == "add"){
add(names,sections, grades);
}
else if (command == "print"){
printRecords(names, sections, grades, 20);
}
else if (command == "drop"){
cout << command;
}
else if (command == "sort"){
cout << command;
}
else if (command == "average"){
cout << command;
}
else if (command == "smallest"){
cout << command;
}
else{
cout << "Invalid command.\n";
}
cin >> command;
}
cout << "Quitting the program.\n";
return 0;
}
void printRecords(const string names[], const int sections[], const int grades[], int size) {
int i;
for (i = 0; i < size; i = i + 1) {
cout << "[" << i << "]:\t";
cout << setw(20) << left << names[i];
cout << setw(5) << sections[i];
cout << setw(10) << grades[i];
cout << "\n";
}
return;
}
void insertionSort(int numbers[], int size) {
int i;
int j;
int toInsert;
// outer loop i is the element we are to insert in to the sorted portion.
// [0, i-1] is the sorted range.
for (i = 1; i < size; i = i + 1) {
toInsert = numbers[i];
j = i - 1;
while (j >= 0 && numbers[j] > toInsert) {
numbers[j + 1] = numbers[j];
j = j - 1;
}
// either j >= 0 and numbers[j] <= toInsert
// or j = -1 here
// we want to store toInsert at numbers[j+1]
numbers[j + 1] = toInsert;
}
return;
}
void add(string names[], int sections[], int grades[]){
int i = 0;
while (names[i] != "" && i < 20){
i = i + 1;
}
cin >> names[i];
cin >> sections[i];
cin >> grades[i];
return;
}
I only need the user to enter a new set of information only once when the function is called.
The add function is what i care about the most. Why is it endlessly lopping?
it is suppose add one student’s record (name, section and grade) after the last record in the 
current spreadsheet. Your spreadsheet should be able to hold up to 20 student records. If 
there are already 20 student records, your code should prompt “Spreadsheet is full. Can 
not add.”
Change cin >> command into getline(cin, command).
Here, this should fix it. What's going on is exactly what Chnossos suspects. When you cin >> the input buffer is not cleared of the newline character unless you call cin.ignore() to ignore it. However if there is no newline character you will end up waiting for it, making you enter extra input to get there.
Now, getline(cin, var) consumes the newline character, so you don't need to ignore after using this function or else you would also be waiting for more data.
I didn't look over it too terribly hard, but I coded this and it is working, thus I believe that you were just getting too many newlines and not consuming enough, thus it seemed like an infinite loop.
There are more eloquent ways to do this, but the basic gist is for strings to use getline() and for other types you can continue to use cin >> if you use cin.ignore() afterwards.
I would suggest you look this up more, also. Here is the code.
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
void add(string names[], int section[], int grade[]);
void printRecords(const string names[], const int sections[], const int grades[], int size);
void insertionSort(int numbers[], int size);
void display(const int numbers[], int size);
int main(){
//command
string command;
//add
string names[20] = { "" };
int sections[20];
int grades[20];
cout << "Enter a command (add, print, drop, sort, average, quit):\n";
getline(cin, command);
while (command != "quit"){
if (command == "add"){
add(names,sections, grades);
}
else if (command == "print"){
printRecords(names, sections, grades, 20);
}
else if (command == "drop"){
cout << command;
}
else if (command == "sort"){
cout << command;
}
else if (command == "average"){
cout << command;
}
else if (command == "smallest"){
cout << command;
}
else{
cout << "Invalid command.\n";
}
getline(cin, command);
}
cout << "Quitting the program.\n";
return 0;
}
void printRecords(const string names[], const int sections[], const int grades[], int size) {
int i;
for (i = 0; i < size; i = i + 1) {
cout << "[" << i << "]:\t";
cout << setw(20) << left << names[i];
cout << setw(5) << sections[i];
cout << setw(10) << grades[i];
cout << "\n";
}
return;
}
void insertionSort(int numbers[], int size) {
int i;
int j;
int toInsert;
// outer loop i is the element we are to insert in to the sorted portion.
// [0, i-1] is the sorted range.
for (i = 1; i < size; i = i + 1) {
toInsert = numbers[i];
j = i - 1;
while (j >= 0 && numbers[j] > toInsert) {
numbers[j + 1] = numbers[j];
j = j - 1;
}
// either j >= 0 and numbers[j] <= toInsert
// or j = -1 here
// we want to store toInsert at numbers[j+1]
numbers[j + 1] = toInsert;
}
return;
}
void add(string names[], int sections[], int grades[]){
int i = 0;
while (names[i] != "" && i < 20){
i = i + 1;
}
getline(cin, names[i]);
cin >> sections[i];
cin.ignore();
cin >> grades[i];
cin.ignore();
return;
}
The problem is that if you attempt to read into an integer, e.g. cin >> sections[i];, but you typed characters that aren't digits, then this operation fails, and cin is put into a fail state.
After that, cin remains in a fail state until you cancel that state by doing cin.clear(). This operation does not remove the problem characters from the stream either, so you usually want to combine the clear() with another read operation to read and discard the problem characters.
If you only ever type integers when your program expects integers, then your code will not "endlessly loop". Obviously you have typed in words when it was expecting integers though.
To fix this there are two things to do. First of all, always test your input functions for failure. After doing cin >> command;, also do:
if ( !cin )
{
break; // exit instead of infinitely looping
}
But it is good to detect the failure state as soon as it occurred. Inside the add function, after the last cin, you should do:
if ( !cin )
{
cout << "Invalid input entered - discarding entry\n";
names[i] = "";
cin.clear();
string junk;
getline(cin, junk);
}
(There are other ways to ignore junk but I think this one is easy to understand).
Finally, the add function uses formatted extraction (i.e. >>), so you cannot tell if the person presses Enter or not. If you want to make it so that them pressing Enter always means they've finished inputting the current entry (and invalid entry is to be discarded), then you will need to use std::getline to store the whole line in a string, and then use a stringstream to do formatted extraction from that line.
For example, the add function could be:
void add(string names[], int sections[], int grades[])
{
int i = 0;
while (names[i] != "" && i < 20){
i = i + 1;
if ( i == 20 )
return;
string line;
getline(cin, line);
istringstream iss(line);
iss >> names[i] >> sections[i] >> grades[i];
if ( !iss )
{
names[i] = "";
cerr << "Invalid entry ignored.\n";
}
}
You may need #include <sstream> for this. Note that in this version you don't need to discard the "junk", as the junk is in the stringstream which is being destroyed anyway.
As a rule of thumb, if you are mixing string and integer input, then using getline plus a stringstream will make your program more user-friendly.

Unable to detect what line is causing a syntax error

Howdy! I'm working on an old project from one of my programming courses and having some issues tracking down which line in my code is causing a syntax error.
When I attempt to compile the code, Visual Studio tells me that there is a syntax error towards the end of main on the line containing this function call:
sortData(carray, numRec, sortby);
I dont think that's the case, because commenting out that call only moves the error to the next line of code.
I can't tell what is causing the error and am hoping a veteran eye could help.
I've include all of the code as I suspect the error is being caused in one of the function calls.
ohbijuan
P.S. Also - Does anyone know if the compiler compiles top to bottom or whether it actually follows function calls during the compile process?
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;
//customer struct
struct customer
{
int id;
string fname, lname;
double totalQuantity, totalPurchases, totalProfit;
};
//Error Codes
const int INPUT_FILE_FAIL_NO_CONTINUE = 2;
const int INPUT_FILE_DATA_ERROR = 3;
//Global Constants
const int arraySize = 200;
const int numType = 5; //# of the types of coffee we currently offer
//Coffee prices per pound
const double colombWhole = 3.75;
const double colombRetail = 4.85;
const double konaWhole = 4.25;
const double konaRetail = 5.25;
const double ethiopWhole = 4.30;
const double ethiopRetail = 5.75;
const double jamaWhole = 5.25;
const double jamaRetail = 7.75;
const double brazWhole = 4.65;
const double brazRetail = 5.90;
//Function prototypes
int readData (ifstream &infile, customer carray[], int size);
//PRE: The address of the ifstream object, the addres of the array of customer structs and the size of
// the array is passed in
//POST: All of the customer data is read in AND the totalQuantity, totalPurchases and totalProfit for
// each customer is calculated. The number of records read is returned.
void sortData (customer carray[], int recordcount, int sortfield);
//PRE: The address of the array of customers, the number of customer records in the array and the field
// on which to be sorted is passed into the function.
//POST: The array is sorted on the basis of the specified field in ascending order
int findMax (const customer carray[], int startRange, int recordcount, int sortfield);
//PRE: The address of the array of customers, the field to sort on and a range of values is passed in
//POST: The address of the largest value is returned
int main()
{
//Array of customer structs
customer crecords[arraySize];
//Initialize the members of our struct to zero
for (int i = 0; i < arraySize; i++)
{
crecords[i].totalProfit = 0;
crecords[i].totalPurchases = 0;
crecords[i].totalQuantity = 0;
}
//Declare filestream objects
ifstream ifile;
ofstream ofile1, ofile2, ofile3;
//user responses
char pquit = 'Y';
char specAnother;
int sortby;
string ifilename;
//Ask user for name of input file
cout << "Please enter the name of the input file: " ;
cin >> ifilename;
//Attempt to open the input file
ifile.open(ifilename.c_str());
while (ifile.fail())
{
cout << endl << "The input file could not be found. Would you like to specify "
<< "another file?" << endl << "(Enter Y or N):";
cin >> specAnother; //Ask user if they want to specify another
if (specAnother == 'N' || specAnother == 'n')
{
exit(INPUT_FILE_FAIL_NO_CONTINUE);
}
else
{
cout << endl << "Please enter the name of the new input file: " ;
cin >> ifilename;
}
ifile.clear(); //Clear the flags, else the input file fail flag will perpetually return true
ifile.open(ifilename.c_str());
}
//File opened successfully, let's begin reading in data and also keep track of the # of
//records read
int numRec = readData(ifile, crecords, arraySize);
cout << "Finished reading " << numRec << " records" << endl;
do
{
//Ask user how they would like to sort the data for the report
cout << endl << "What would you like to sort on?" << endl;
cout << "1) Sort by POUNDS bought" << endl
<< "2) Sort by PURCHASE AMOUNT" << endl
<< "3) Sort by PROFIT" << endl;
cin >> sortby;
if (sortby > 3 || sortby < 1)
{
cout << "You entered an invalid sorting method, try again" << endl
<< "Enter an option:";
cin >> sortby;
}
cout << "You entered " << sortby << endl;
}
//Sort Data
sortData(carray, numRec, sortby);
return 0;
}
//Function Definitions
int readData (ifstream &infile, customer carray[], int size)
{
int x = 0, coffeeType, quantity;
double currentSale, internalCost, profitOnSale;
while (infile >> carray[x].id && x < size)
{
infile >> carray[x].fname >> carray[x].lname;
while (infile >> coffeeType && coffeeType != 0)
{
infile >> quantity;
switch(coffeeType)
{
case 1:
carray[x].totalQuantity += quantity;
currentSale = quantity * colombRetail;
carray[x].totalPurchases += currentSale;
internalCost = quantity * colombWhole;
profitOnSale = currentSale - internalCost;
carray[x].totalProfit += profitOnSale;
break;
case 2:
carray[x].totalQuantity += quantity;
currentSale = quantity * konaRetail;
carray[x].totalPurchases += currentSale;
internalCost = quantity * konaWhole;
profitOnSale = currentSale - internalCost;
carray[x].totalProfit += profitOnSale;
break;
case 3:
carray[x].totalQuantity += quantity;
currentSale = quantity * ethiopRetail;
carray[x].totalPurchases += currentSale;
internalCost = quantity * ethiopWhole;
profitOnSale = currentSale - internalCost;
carray[x].totalProfit += profitOnSale;
break;
case 4:
carray[x].totalQuantity += quantity;
currentSale = quantity * jamaRetail;
carray[x].totalPurchases += currentSale;
internalCost = quantity * jamaWhole;
profitOnSale = currentSale - internalCost;
carray[x].totalProfit += profitOnSale;
break;
case 5:
carray[x].totalQuantity += quantity;
currentSale = quantity * brazRetail;
carray[x].totalPurchases += currentSale;
internalCost = quantity * brazWhole;
profitOnSale = currentSale - internalCost;
carray[x].totalProfit += profitOnSale;
break;
default:
cout <<"The input file contains an undeclared coffee type at record " << x
<<"Program terminating!" << endl;
//return exit(INPUT_FILE_DATA_ERROR);
}
}
x++; //At this point, we have encountered our sentinel value of 0 that indicates the end of our
//customer record. Let's move on to the next customer.
}
return x;
}
int findMax (const customer carray[], int startRange, int recordcount, int sortfield)
{
int maxLoc = startRange;
switch(sortfield)
{
case 1:
for (int i = startRange + 1; i <= recordcount; i++)
{
if (carray[maxLoc].totalQuantity < carray[i].totalQuantity)
maxLoc = i;
}
case 2:
for (int i = startRange + 1; i <= recordcount; i++)
{
if (carray[maxLoc].totalPurchases < carray[i].totalPurchases)
maxLoc = i;
}
case 3:
for (int i = startRange + 1; i <= recordcount; i++)
{
if (carray[maxLoc].totalProfit < carray[i].totalProfit)
maxLoc = i;
}
}
return maxLoc;
}
void sortData (customer carray[], int recordcount, int sortfield)
{
for (int i = 0; i < recordcount ; i++)
{
int max = findMax(carray, i, recordcount, sortfield);
swap(carray[i], carray[max]);
}
}
Your problem is that you have this:
do
{
// ...
}
without a trailing while (...); just before the call to sortData.
Where is while clause of your do..while statement?
do { … } requires a condition at the end, such as do { … } while (busy); If you just want to execute a piece of code in a block, just put that block there and remove the do.
Your do {} is missing a while clause after the brackets, that would result in a syntax error.
Another thing I also noticed -- the findMax switch statement is missing a default tag, and it's also missing break statements. Not sure if that's your intention or not, but it's usually not for most switches.
where is your while after do ????
do {
// something
} while(condition);
this is the correct syntax