Solved

# loop analyzing sales data

Posted on 2006-06-27
622 Views
I am supposed to import a data file and then display the data then state what is the highest sales amount and how many times it occurs and what is the second highest sales amount and how many times it occurs.

I can get the highest amount correctly and the second highest amount sometimes depending on where it is in the order of the data.

however i can not get the occurance times correct at all.

here is my code.
#include <iostream>
#include <iomanip>
#include <cmath>
#include <fstream>

using namespace std;

int main ()
{
int id, counter, counter2;
double sales;
double high_sales, temp, second_high_sales;
counter = 0;
counter2 = 0;
high_sales = 0;
second_high_sales = 0;

header = "  Acme Sales Report    ";

cout << fixed <<setprecision(2);

ifstream infile ("sales3.txt");

if (!infile){
cout << "Can not open file";
return 1;
}

while (infile >> id >> sales){
cout << id << "      " << setw(8) << sales << endl;
if (sales > high_sales){
temp = high_sales;
high_sales = sales;
}
if (sales == high_sales)
counter++;

if (temp > second_high_sales){
second_high_sales = temp;
counter2++;
}
}
cout << "The highest sales amount is " << setw(8) << high_sales << " it occurs " << counter << " times" << endl;
cout << "Second High Sales are " << setw(8) << second_high_sales << " it Occurs " << counter2 << " times" << endl;

return 0;
}

here are the contents of the 1st data file.

1000  1000
1111   500
1500  1000
2000   900
2222  2000
2500  2000
3000  1500
3333  2000
3500  2000
4000   600
4444  2500
4500  2000
5000  2500
5500  2222
5555  2000
6000  1999
6500  2222
6666  2500
7000   100
7500  2100
7777  2150


here are the contents of the second data file

1000  1000
1111   500
1500  1000
2000   900
2222  2000
2500  2000
3000  1500
3333  2000
3500  2000
4000   600
4444  2500
4500  2000
5000  2500
5500  2222
5555  2000
6000  1999
6500  2222
6666  2500
7000   100
7500  3000
7777  2150


here are the contents of the third data file

1000  1000
1111  1000
1500  1000
2000  1200
2222  1200
2500  1500
3000  1500
3333  1500
3500  1000
4000  1500
4444  1500
4500  2000
5000  4000
5500  2000
5555  4000
6000  2000
6500  2000
6666  2000
7000   100
7500  3000
7777  4000


This was a homework problem but it was due at 11:00pm central time today so I just turned in what I had above hoping for partial credit.
I would like to know how to solve this problem though for future referance.

0
Question by:vlahomt
• 6
• 3
• 3
• +2

LVL 15

Expert Comment

ID: 16998642
I think you can find the bugs if you hand-simulate the program.  Process some input data keeping track of the values on paper following the logic of your program.  Or use a debugger if you have one available.

A few hints:

When you hit a new high, you have only seen one of that value, so start a new count.

When you demote a high to second-highest, don't forget to bring along the old high's count.

Count an occurrence of the second-highest value when you read one of that value, not when you demote the high value.

It should be possible for the second-highest value to change without demoting the highest.
0

LVL 3

Expert Comment

ID: 16998805
1. First of  initialize temp also
temp = 0;

2. reset counter for high_sale

if (sales > high_sales){
temp = high_sales;
high_sales = sales;
}

Here you have updated the new highest value but didn't reset the counter....

make counter = 0 in the above if condition

if (sales > high_sales){
temp = high_sales;
high_sales = sales;
counter = 0;
}
else {
temp =0;
}

if (sales == high_sales)
counter++;

will increase it....

3. for second highest

if (temp > second_high_sales){
second_high_sales = temp;
counter2++;
}

use following

if (sales > second_high_sales)
{
if(temp != 0){
second_high_sales = temp;
counter2 = 1;
}
}
else if (sales == second_high_sales)
{
counter2++;
}

============================

Finally

while (infile >> id >> sales)
{
cout << id << "      " << setw(8) << sales << endl;
if (sales > high_sales)
{
temp = high_sales;
high_sales = sales;
counter = 0;
}
else
{
temp = 0;
}

if (sales == high_sales)
counter++;

if (sales > second_high_sales)
{
if(temp != 0)
{
second_high_sales = temp;
counter2 = 1;
}
}
else if (sales == second_high_sales)
{
counter2++;
}
}
0

LVL 39

Expert Comment

ID: 17007972

Not so much because the code posted was bad but to show you some advanced and improved techniques.

I give full (tested) code though it is a homework question. That is because the asker already posted full code himself and cause it would make no sense to propagate advanced techniques not giving the code.

Regards, Alex

#include <iostream>
#include <iomanip>
// you don't need cmath or math.h for normal arithmetics
// #include <cmath>
#include <fstream>

// you could omit plain char pointers by that
#include <string>

// allows you to read the input file line by line
// and convert numbers by using strings rather than
#include <sstream>

// vector is a dynamic array class to store the data
// for further evaluation rather than evaluating the data
#include <vector>

// sort template function
#include <algorithm>

using namespace std;

// a structure allows you to create a new data type.
struct Sales
{
int id;
int sales;   // I didn't see any floating point number

// that overload is for sorting Sales items by sales value
bool operator<(const Sales& s)
{
return sales < s.sales;
}
};

// modular programming means you should use an own function

// read the input file and return all values in vector salesArr
// return true if successful
bool readData( const string& filename, vector< Sales >& salesArr )
{
// c_str returns a const char * for the std::string
ifstream infile ( filename.c_str() );

if (!infile)
{
cout << "Can not open file >>" << filename << "<<" << endl;
return false;
}

// we read the file line by line
// that makes it easier to ignore white spaces
// or spot errors in input data

int counter = 0;
string line;
while (getline(infile, line))
{
// ignore empty lines
if (line.empty())
continue;

++counter;
// string streams make it easier to read wrong data
// by not spoiling the file stream
istringstream iss(line);

// we read the values from the string and display errors if any
Sales sales = { 0 };
if (!(iss >> sales.id))
{
cout  << ">>" << line << "<<, Error reading line " << counter << ". The id can not be read properly. " << endl;
return false;
}
if (!(iss >> sales.sales))
{
cout  << ">>" << line << "<<, Error reading line " << counter << ". The sales value can not be read properly. " << endl;
return false;
}
// put the Sales to the vector
salesArr.push_back(sales);
}
return true;
}

void displayData( const vector<Sales>& salesArr)
{
// use const whereever possible
const string header1 = "  Acme Sales Report    ";
const string header2 = "  ID         Sales      ";
const string header3 = "  __         _____      ";

// not really necessary for integer salesArr ???
cout << fixed << setprecision(2);

for (int i = 0; i < salesArr.size(); ++i)
{
const Sales& sales = salesArr[i];
cout << sales.id << "   " << sales.sales << endl;
}
cout << endl;
}

// get highest and second highest salesArr
void evaluateDisplayTopTwoSales(  const vector<Sales>& inputArr )
{
if (inputArr.empty())
return;  // ???

// make a local copy where we have write access
vector<Sales> salesArr = inputArr;
// we sort the Sales items by sales value (in ascending order)
// here operator< was used
sort( salesArr.begin(), salesArr.end() );

// now its easy to evaluate and display the highest sales values
// we do it in a loop to have one piece of code for highest and
// second highest
string prompt = "The highest sales amount is      ";
for (int i = 0; i < 2; ++i)
{
int nsiz        = salesArr.size();
int high_sales  = salesArr[nsiz-1].sales;
int counter  = 0;
while (--nsiz >= 0)
{
Sales& sales = salesArr[nsiz];
if (sales.sales != high_sales)
break;
// count occurrence
++counter;
// erase last from array
salesArr.resize(nsiz);
}

cout << prompt << setw(8) << high_sales << " it occurs " << setw(3) << counter << " times" << endl;

prompt = "The next highest sales amount is ";
if (nsiz == 0)
break;   // just for case where we have only one value
}
}

// finally we put all together
int main ()
{
// create an empty vector
vector<Sales> salesArr;

return 1;

displayData(salesArr);

evaluateDisplayTopTwoSales(salesArr);

return 0;
}

0

Author Comment

ID: 17033697
Everything that jitendra_wadhwani works except for finding the second high value. what itsmeandnobodyelse said is way beyond my level of understanding I have not learned how to work with array's yet that is next week.

I have tried to follow the logic and see why it is not finding the second high value correctly but I am not sure.
0

LVL 15

Expert Comment

ID: 17034106
jitendra_wadhwani's solution sets second_high_sales only when two conditions are true:

if (sales > second_high_sales)
{
if(temp != 0)

Tracing back, temp != 0 is true only if previously sales was > high_sales.  Thus, second_high_sales can only get a new value when high_sales gets a new value.

This misses a case where second_high_sales should be changed.  For example, consider the input sequence 2, 1.  After the program reads the 2, high_sales will be 2 and second_high_sales will be 0.  After it reads the 1, there is not a new high_sales value, and so neither value will change, while actually second_high_sales should be set to 1.

A new high is indeed one way to get a new second-high, but it is not the only way.  The other way is to read in a value that is lower than the high, but higher than the current second-high.  This was the idea of my fourth hint above.

jitendra_wadhwani's solution also retains the bug addressed by my second hint "When you demote a high to second-highest, don't forget to bring along the old high's count."  A concrete example may help.  If you have seen 67 occurrences of the high value 200 in the data, and then you read in a sales value of 210, 210 becomes the new high value and 200 becomes the second-highest value.  That should not cause you to discard the count of 67 occurrences of 200 already seen and start the count for 200 as second-highest over at 1. The count of 200s seen so far is still 67, so that should now be the count of occurrences of the second-highest values seen, which is stored in counter2.
0

LVL 3

Expert Comment

ID: 17035025
Agreed Can rectify by following

else if(second_high_sales == 0 && sales != high_sales)
{
second_high_sales = sales;
counter2 = 1;
}
with if(temp != 0)

while (infile >> id >> sales)
{
cout << id << "      " << setw(8) << sales << endl;

if (sales > high_sales)
{
temp = high_sales;
high_sales = sales;
counter = 0;
}
else
{
temp = 0;
}

if (sales == high_sales)
counter++;

if (sales > second_high_sales)
{
if(temp != 0)
{
second_high_sales = temp;
counter2 = 1;
}
else if(second_high_sales == 0 && sales != high_sales) // else if Added Now
{
second_high_sales = sales;
counter2 = 1;
}
}
else if (sales == second_high_sales)
{
counter2++;
}
}

condition
second_high_sales == 0 is for that second_high_sales is not updated yet and
sales != high_sales is for that in case inputs are 2,2,2,2

highest value will be 2
second highest will be still 0...

0

LVL 3

Expert Comment

ID: 17035027
Final code is

while (infile >> id >> sales)
{
cout << id << "      " << setw(8) << sales << endl;

if (sales > high_sales)
{
temp = high_sales;
high_sales = sales;
counter = 0;
}
else
{
temp = 0;
}

if (sales == high_sales)
counter++;

if (sales > second_high_sales)
{
if(temp != 0)
{
second_high_sales = temp;
counter2 = 1;
}
else if(second_high_sales == 0 && sales != high_sales) // else if Added Now
{
second_high_sales = sales;
counter2 = 1;
}
}
else if (sales == second_high_sales)
{
counter2++;
}
}
0

LVL 15

Expert Comment

ID: 17035140
Since the original question said

> I would like to know how to solve this problem though for future referance.

, here's another procedural suggestion:

Attack the problem in small steps.  Instead of trying to write a program that solves the whole problem the first time, sneak up on it step by step.  Test each increment and make sure it produces correct results before going on to the next step.

Suggested breakdown:

1.  Write a program that finds the highest number in the input.  Don't worry about the second-highest number or the counts.
2.  Change the program so it also finds the second-highest number.
3.  Change the program so it also finds the count for the highest number.
4.  Change the program so it also finds the count for the second-highest number.
0

Author Comment

ID: 17053050
I am still unable to figure out how to properly find the second high value and count it's occurances.
0

LVL 3

Expert Comment

ID: 17057807

while (infile >> id >> sales)
{
cout << id << "      " << setw(8) << sales << endl;

if (sales > high_sales)
{
temp = high_sales;
high_sales = sales;
counter = 0;
}
else
{
temp = 0;
}

if (sales == high_sales)
counter++;

if (sales > second_high_sales)
{
if(temp != 0)
{
second_high_sales = temp;
counter2 = 1;
}
else if(second_high_sales == 0 && sales != high_sales) // else if Added Now
{
second_high_sales = sales;
counter2 = 1;
}
}
else if (sales == second_high_sales)
{
counter2++;
}
}

In case any issue ...or not able to understand anyline please point it out ....will clear it...
0

LVL 3

Expert Comment

ID: 17070669
// Here high_sales, temp, second_high_sales and sales all are zero
// This will work for only positive values...

while (infile >> id >> sales)
{
cout << id << "      " << setw(8) << sales << endl;

// Here sales contains some value....
// For first time remaining are zero and first time this condition will be true we need to store it as highest value
// After first time if new value in sales in greater than previous high_sales
// we need to update high_sales and reset teh second highest    sales value and counter
if (sales > high_sales)
{

temp = high_sales; // Storing previous highest value to temp.
high_sales = sales; // Storing new value as high sales.
counter = 0; //Reseting counter to zero....count for this occurence will be updated below.
}
else
{
temp = 0; // Resetting temp value to zero otherwise it may contain previous highest value.
}

// if sales and counter are equal increasing the counter....
if (sales == high_sales)
counter++;

//process for finding highest value and its counter is over

// Now if sales is greater than second highest we need to doo something else if it is equal increase counter and if it is less ignore...
if (sales > second_high_sales)
{
// Here sales > second_high_sales now two cases
// if temp != 0 says that highes value is just updated and temp contains previous highest value so make it second highest

if(temp != 0)
{
second_high_sales = temp; // Storing previous highest as second highest
counter2 = 1; //Setting the counter to 1 fit current occurence
}
// Now temp is now zero means highest value is not updated but sales > second_high_sales
// Again we need to reset the second highest value and its counter
// But with a check that is is not equal to high_sales
// because if it is equal to high_sales we have increased the counter of high_sales and now it should be ignored
else if(second_high_sales == 0 && sales != high_sales) // else if Added Now
{
second_high_sales = sales; // Storing new valu as second highest
counter2 = 1;  //Setting the counter to 1 fit current occurence
}
}
// Now here sales is not greater than second_high_sales os if it is equal we have to increase counter else ignore
else if (sales == second_high_sales)
{
counter2++;
}
}

0

LVL 2

Expert Comment

ID: 17165678
here, i try to give a pseudocode instead of the code to tackle the problem

setting up values
first = 0 //highest initially is 0
firstC=0 //highest count is 0
second =0 //second highest initially is 0
secondC =0 //second highest count is 0

while more input
check input with first
if input is > first
{
//demote first to second
second = first
secondC  = firstC
//set input as first
first = input
firstC=1
}
else if input == first
{
++firstC
}
else if input > second (but it would be less than first)
{
second = input
secondC=1
}
else if input == second
{
++secondC
}
}

i din't have much time to read through the others code but i believe the did exactly what i explained here (but in code form). hope tt helps you to understand how to find the second highest
normally, when i have this sort of problem, i don't jump into the code directly. rather, work out the logic and pseudocode behind how to taclke them. ask youself, what happens if you have a certain number bigger than the first? equal to first? smaller than first? bigger than second?equal to second?smaller then second?
did you cover all cases?
0

LVL 3

Accepted Solution

ID: 17166469
After looking seet82  solution....found one more bug in my solution...

No comment from Author from last 17 days.....may be he has already got the solution.....

The rectified one is as follows

// Here high_sales, temp, second_high_sales and sales all are zero
// This will work for only positive values...

int iTempCounter = 0;

while (infile >> id >> sales)
{
cout << id << "      " << setw(8) << sales << endl;

// Here sales contains some value....
// For first time remaining are zero and first time this condition will be true we need to store it as highest value
// After first time if new value in sales in greater than previous high_sales
// we need to update high_sales and reset teh second highest    sales value and counter
if (sales > high_sales)
{

temp = high_sales; // Storing previous highest value to temp.
high_sales = sales; // Storing new value as high sales.
iTempCounter  =  counter; // Storing Previous counter
counter = 0; //Reseting counter to zero....count for this occurence will be updated below.
}
else
{
temp = 0; // Resetting temp value to zero otherwise it may contain previous highest value.
iTempCounter = 0;
}

// if sales and counter are equal increasing the counter....
if (sales == high_sales)
counter++;

//process for finding highest value and its counter is over

// Now if sales is greater than second highest we need to doo something else if it is equal increase counter and if it is less ignore...
if (sales > second_high_sales)
{
// Here sales > second_high_sales now two cases
// if temp != 0 says that highes value is just updated and temp contains previous highest value so make it second highest

if(temp != 0)
{
second_high_sales = temp; // Storing previous highest as second highest
counter2 = iTempCounter  + 1; //Setting the counter to iTempCounter  + 1 fit current occurence
}
// Now temp is now zero means highest value is not updated but sales > second_high_sales
// Again we need to reset the second highest value and its counter
// But with a check that is is not equal to high_sales
// because if it is equal to high_sales we have increased the counter of high_sales and now it should be ignored
else if(second_high_sales == 0 && sales != high_sales) // else if Added Now
{
second_high_sales = sales; // Storing new valu as second highest
counter2 = 1;  //Setting the counter to 1 fit current occurence
}
}
// Now here sales is not greater than second_high_sales os if it is equal we have to increase counter else ignore
else if (sales == second_high_sales)
{
counter2++;
}
}
0

Author Comment

ID: 17168432
This is an extra credit problem I have just been busy with required programs that I have not had a chance to revist this one yet.

thanks
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [sâ€¦
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilationâ€¦
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.