GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 04-Sep-2004, 17:55
crystalattice's Avatar
crystalattice crystalattice is offline
Aspiring author
 
Join Date: Apr 2004
Location: Japan (again)
Posts: 1,627
crystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nice
Question

Floating point exception error (Note-long post)


When I input the input file name, the program quits w/ this error:
Code:
Program has been terminated receiving signal 8 (Floating point exception)
I don't understand this because I'm not using any float values in the program.

I'm not sure if it's a problem w/ the file input or w/ how I'm getting the info from the file.

Here's what I've written so far. I do have cout << statements in it for troubleshooting, but it doesn't even get far enough to use them. I'm sure there's other errors present, but I need to get the file read before I can attack them.
CPP / C++ / C Code:
/**************************************************************************
*Purpose:  Read a file that contains the income level and product rankings from 
*	respondents in income brackets A, B, & C.  Use this information to calculate:
*	1) the average rating for product 1 in each income bracket
*	2) the number of people in income bracket B who rated both products >=5
*	3) the average rating for product 2 by people who rated product 1 <3.
***************************************************************************/
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include "Query.h"
using namespace std;

void avgRatingProd1 (char income, int rating1, int &incomeA_avg,
		     int &incomeB_avg, int &incomeC_avg);
int middleIncomeBothProd (char income, int rating1, int rating2);
int avgRatingProd2 (int rating1, int rating2);

int
main ()
{
	cout << "This program will determine product rating information based on\n" << "respondent income level.\n\n";

	//---------------Input Section-----------------------------
	cout << "Enter the input file name: ";
	ifstream inputStream;	//open input stream to file
	interactiveOpen (inputStream);

	char income_level, the_new_line;	//finds the new line character
	int prod1_rate = 0, prod2_rate = 0,	//product ratings
	  incomeA_avg, incomeB_avg, incomeC_avg,	//average product ratings
	  line_counter = 0,	//counts number of respondents
	  num_incomeB, avg_prod2;
	string respond_line;

	for (;;)
	{
		//get respondent information
		inputStream >> income_level >> prod1_rate >> prod2_rate;
	cout << "Income level and product ratings are " << income_level << prod1_rate << prod2_rate;
		//the unread newline is left at the read position
		//get() will retrieve it for the next line
		inputStream.get (the_new_line);
	cout << "Got new line";
		if (inputStream.eof ())
			break;

		++line_counter;
	cout << "Line number " << line_counter;
		avgRatingProd1 (income_level, prod1_rate, incomeA_avg,
				incomeB_avg, incomeC_avg);
		num_incomeB =
			middleIncomeBothProd (income_level, prod1_rate,
					      prod2_rate);
		avg_prod2 = avgRatingProd2 (prod1_rate, prod2_rate);
	}
	inputStream.close ();

	//--------------------Output------------------------------------
	cout << "There were " << line_counter << " respondents.\n"
		<< "Below is the average rating for product 1, by income bracket: \n"
		<< "Income level A: " << incomeA_avg 
		<< "\nIncome level B: " << incomeB_avg 
		<< "\nIncome level C: " << incomeC_avg 
		<< "\n\nThere were " << num_incomeB <<
		" people who rated product 2 5 or better.\n\n" 
		<< "The average rating for product 2 by people who rated product 1 less than 3 is " << avg_prod2 << endl;
	return 0;
}

/*avgRatingProd1() determines the average rating for product 1 for each income *bracket
*
*Receives: income, a character
*		rating1, an integer
*Send back: incomeA_avg, incomeB_avg, & incomeC_avg, three integers
****************************************************************************/
void
avgRatingProd1 (char income, int rating1, int &incomeA_avg,
		int &incomeB_avg, int &incomeC_avg)
{
	int prod_rate_A = 0, prod_rate_B = 0, prod_rate_C = 0, a = 0, b = 0, c = 0;	//counters

	switch (income)
	{
	case 'A':
	{
		prod_rate_A += rating1;
		++a;
	}
		break;
	case 'B':
	{
		prod_rate_B += rating1;
		++b;
	}
		break;
	case 'C':
	{
		prod_rate_C += rating1;
		++c;
	}
		break;
	default:
		cout << "--Error: avgRatingProd1() invalid income level or rating";
		break;
	}
	incomeA_avg = prod_rate_A / a;
	incomeB_avg = prod_rate_B / b;
	incomeC_avg = prod_rate_C / c;
}

/*middleIncomeBothProd() counts the number of persons in income bracket B who *rated both products 5 or greater
*
*Receives: income, a character
*		prod1_rate & prod2_rate, two integers
*Returns: incomeB, an integer
*************************************************************************/
int
middleIncomeBothProd (char income, int prod1_rate, int prod2_rate)
{
	int incomeB = 0;

	if ((income = 'B') && (prod1_rate >= 5) && (prod2_rate >= 5))
		++incomeB;
	return incomeB;
}

/*avgRatingProd2() determines the average rating for product 2 by persons who *rated product 1 less than 3.
*
*Receives: prod1_rate & prod2_rate, two integers
*
*Returns: avg, an integer
****************************************************************************/
int
avgRatingProd2 (int prod1, int prod2)
{
	int rate2, avg, i;

	if (prod1 < 3)
	{
		rate2 += prod2;
		++i;
	}
	avg = rate2 / i;
	return avg;
}
Here's the file query code; this came from the textbook publishers web site:
CPP / C++ / C Code:
/* Query.cpp
 *
 */
 
#include "Query.h"

#include <iostream>                    // cin, cout, >>, <<
#include <fstream>                     // ifstream, ofstream
#include <string>                      // string, getline()
using namespace std;

// --- Open an ifstream interactively ---------------------

void interactiveOpen(ifstream & theIFStream)
{
   char response;
   do
   {
      cout << "Enter the name of the input file: ";
      string inputFileName;
      getline(cin, inputFileName);

      theIFStream.open(inputFileName.data());

      if (theIFStream.is_open()) break;

      cerr << "\n***InteractiveOpen(): unable to open "
           << inputFileName << "\nTry again (Y or N)? ";
      cin >> response;
   }
   while (response != 'N' && response != 'n');
}

// --- Open an ofstream interactively ---------------------

void interactiveOpen(ofstream & theOFStream)
{
   char response;
   do
   {
      cout << "Enter the name of the output file: ";
      string outputFileName;
      getline(cin, outputFileName);

	  cin.get();

      theOFStream.open(outputFileName.data());

      if (theOFStream.is_open()) break;

      cerr << "\n***InteractiveOpen(): unable to open "
           << outputFileName << "\nTry again (Y or N)? ";
      cin >> response;
   }
   while (response != 'N' && response != 'n');
}
__________________
Start Programming with Python-A beginner's guide to programming and the Python language.
-------------
Common Sense v2.0-Striving to make the world a little bit smarter.
  #2  
Old 04-Sep-2004, 18:47
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,200
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
I don't know where the "float" error is coming from either.

A quick glance uncovers a couple of obvious errors. (But don't let that make you feel bad, they are all obvious, once someone points them out.)

in middleIncomeBothProd() this can't be right:

CPP / C++ / C Code:
int
middleIncomeBothProd (char income, int prod1_rate, int prod2_rate)
{
  int incomeB = 0;

  if ((income = 'B') && (prod1_rate >= 5) && (prod2_rate >= 5))
    ++incomeB;
  return incomeB;
}

should obviously be

CPP / C++ / C Code:
  if ((income == 'B') && (prod1_rate >= 5) && (prod2_rate >= 5))

(Note that I haven't attempted to make any meaning of your logic, just noted the obvious.)

How about avgRatingProd2():
CPP / C++ / C Code:
 int
avgRatingProd2 (int prod1, int prod2)
{
  int rate2, avg, i;

  if (prod1 < 3)
  {
    rate2 += prod2;
    ++i;
  }
  avg = rate2 / i;
  return avg;
}

See the problem: You may or may not increase the value of rate2 by the value of prod2, but rate2 is never initialized. You may or may not increment i then divide by the result. You never initialize i


How the heck do you hope to get a meaningful average using int arithmetic anyhow? Or were they originally floats or doubles and you changed them to int in order to try to get rid of the float error message?


I won't bother with avgRatingProd1(), but you should make sure that all of the arithmetic makes sense. Does your logic ever result in dividing by zero, for example?


Regards,

Dave
  #3  
Old 04-Sep-2004, 22:09
crystalattice's Avatar
crystalattice crystalattice is offline
Aspiring author
 
Join Date: Apr 2004
Location: Japan (again)
Posts: 1,627
crystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nice
Perhaps I go about coding in the wrong fashion. What I normally do (and I'm sure it's obvious by now) is write essentially an outline of the program. Then I rework the code as I find errors at runtime. I'll modify it based on what happens and what I see needs changing, e.g. ensuring all values are >0, checking that averages are correct, etc.

My goal is to get a quick and dirty program up and running to test my logic theory and see what's flawed. Would it be better to get the program as complete as I can before running it?

Perhaps part of my problem is that I have to finish this course in the next 2 months or I risk having to pay back my tuition assistance from the Navy. I only have 2 tests left and a few labs but I can feel the pressure.
__________________
Start Programming with Python-A beginner's guide to programming and the Python language.
-------------
Common Sense v2.0-Striving to make the world a little bit smarter.
  #4  
Old 05-Sep-2004, 09:23
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,200
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by crystalattice
Perhaps I go about coding in the wrong fashion. What I normally do (and I'm sure it's obvious by now) is write essentially an outline of the program. Then I rework the code as I find errors at runtime. I'll modify it based on what happens and what I see needs changing, e.g. ensuring all values are >0, checking that averages are correct, etc.

My goal is to get a quick and dirty program up and running to test my logic theory and see what's flawed. Would it be better to get the program as complete as I can before running it?

Perhaps part of my problem is that I have to finish this course in the next 2 months or I risk having to pay back my tuition assistance from the Navy. I only have 2 tests left and a few labs but I can feel the pressure.

In my opinion you should never, (never) or should I say NEVER put code in your program that you know may be defective. As your are testing your program, it is possible that your test cases don't actually result in values that reveal the bug, and if you forget to go back and make the correction, the bugs may persist into your "finished" program.

Putting in suspect code and debugging it during testing is the worst idea I have heard yet. You can't prove a program is good by testing. You should always test what you consider to be worst case conditions (sometimes known as boundary conditions: Under what conditions would it go through a loop zero times; under what conditions will it go through a loop the maximum number of times; what would happen if a function was invoked with a null pointer; etc.) But, and I hate to repeat myself: You can't prove a program is good by testing. Write the best code you can; test it as thoroughly as you can.

(For the same reason, I recommend that you don't put frivolous, obscene, or otherwise unprofessional-sounding comments or error messages in your code. You may forget to remove them, and someone may see them at a later date, to your embarrassment.)

Creating dummy functions and procedures that do nothing except return some required values is probably a good plan just to get everything to compile. But if you have a formula, say, that includes division, make sure that it can never divide by zero. If you have a function or procedure that reads from writes into an array, you should make sure that it never reads or writes using a null pointer.

As far as debugging when you get an error message that seems to indicate faulty arithmetic ("floating point exception" probably indicates division by zero), put a cout<< or printf() just before expressions that involve division.

Instead of going through your entire program putting printf() just before every arithmetic expression, you can put cout<< or printf() at the beginning and end of each function of procedure so that you can at least have some hint as to how far your program got before it bombed out. Then you can scrutinize that bad-boy routine, and put printf() wherever it could possibly go wrong.

For example

CPP / C++ / C Code:
int foo(char *out_string, char *in_string)
{
  int retval;/* this is in the actual code for this procedure */
  printf("DEBUG: Into foo()\n");
  printf("DEBUG: in_string: <%s>", in_string);

  // do some stuff here, including setting the value of retval


  printf("DEBUG: returning from foo()\n");
  printf("DEBUG: ret value is %d\n", retval);
  return retval;
}

Now this is my opinion, in general. Your Mileage May Vary. You must find the way that makes sense to you.

Is it faster to put in good code and put printf() in appropriate places, or to spend time trying to figure out what "floating point exception" means, then posting an appeal for help and waiting for a helpful response?

Two most important debugging tools:
1. Your brain
2. printf() (or cout<<)

If I had to make a list, there would be an entry for "get help from a programming forum on the internet", but it wouldn't make the top ten.

Best of luck from an ex-Navy enlisted man (I was doing my four years probably about the time that your parents were born.)

Regards,

Dave, AQB-2

p.s. printf() is your friend. I am also your friend, but I'm not always available; printf() is.
  #5  
Old 05-Sep-2004, 11:57
crystalattice's Avatar
crystalattice crystalattice is offline
Aspiring author
 
Join Date: Apr 2004
Location: Japan (again)
Posts: 1,627
crystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nice
Oy, guess I'll hash it out some more and see what happens. I did address some of your previous observations but still getting the same error. Maybe if I rewrite it :-)
__________________
Start Programming with Python-A beginner's guide to programming and the Python language.
-------------
Common Sense v2.0-Striving to make the world a little bit smarter.
  #6  
Old 05-Sep-2004, 12:39
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,200
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by crystalattice
Oy, guess I'll hash it out some more and see what happens. I did address some of your previous observations but still getting the same error. Maybe if I rewrite it :-)

I didn't mean that you shouldn't ask questions on the web or anyplace else. There are usually lots of people who would like to help. I merely meant that the more you can do on your own, the more you will see how it can be easier and faster.

If you want to post the whole thing again, I will try to take a look at it, but remember the old proverb:


Quote:
Give a man an espresso and he will have a buzz for an hour. Give a man an espresso machine and he will be buzzed for a lifetime.


Regards,

Dave
  #7  
Old 06-Sep-2004, 01:09
crystalattice's Avatar
crystalattice crystalattice is offline
Aspiring author
 
Join Date: Apr 2004
Location: Japan (again)
Posts: 1,627
crystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nice
Lightbulb

Found a few new things


I ran the code on my Windows partition to see if CodeWarrior would help out. It did come up w/ a few things:
1) It found the "divide by zero" that happens on avgRatingProd() when the file isn't input. Not a lot I can do about that unless the file is input.
2) Since I got a DBZ, I changed the counter intializ. to "1" to continue checking. This causes the default output value
CPP / C++ / C Code:
 "--Error: avgRatingProd1() invalid income level or rating";
to go into an infinite loop.
3) I found a problem w/
CPP / C++ / C Code:
cout << "Enter the input file name: ";
It is output twice for some reason. Running through the debugger didn't show why.
4) The Query.cpp file is cocked up in that if, after it asks to try again when It can't find the input file, you enter "Y", you never get a chance to reenter the filename. It just keeps dumping back to "Do you want to try again?".

Unfortuantly, I got no additional information on the floating point error.

Because of the problem w/ 4) above, I think that my issue isn't w/ my code but w/ the Query.cpp file that I got from the publisher's website. So, my solution right now is to go back to my previous file from a few days ago (that I finally got fixed do to your help) and use the file input code from that. I figure that way I can eliminate the publisher's file as the culprit.

Below is my latest revision, prior to removing the call to the Query.cpp file.
CPP / C++ / C Code:
/**************************************************************************
*Cody Jackson (60-0067CE)
*CS265
*Test 5 #16
*
*Purpose:  Read a file that contains the income level and product rankings from 
*	respondents in income brackets A, B, & C.  Use this information to calculate:
*	1) the average rating for product 1 in each income bracket
*	2) the number of people in income bracket B who rated both products >=5
*	3) the average rating for product 2 by people who rated product 1 <3.
***************************************************************************/
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include "Query.h"
using namespace std;

void avgRatingProd1 (char income, int rating1, double &incomeA_avg,
		     double &incomeB_avg, double &incomeC_avg);
int middleIncomeBothProd (char income, int rating1, int rating2);
double avgRatingProd2 (double rating1, double rating2);

int
main ()
{
	cout << "This program will determine product rating information based on\n" 
		<< "respondent income level.\n\n";

	//---------------Input Section-----------------------------
	cout << "Enter the input file name: ";
	ifstream inputStream;	//open input stream to file
	interactiveOpen (inputStream);

	char income_level, the_new_line;	//finds the new line character
	int prod1_rate = 0, prod2_rate = 0,	//product ratings
	  line_counter = 0,	//counts number of respondents
	  num_incomeB, avg_prod2;
	double incomeA_avg, incomeB_avg, incomeC_avg;	//average product ratings
	string respond_line;

	for (;;)
	{
		//get respondent information
		inputStream >> income_level >> prod1_rate >> prod2_rate;
	
	//***Testing code - Remove***************
	cout << "Income level and product ratings are " 
		<< income_level 
		<< prod1_rate 		
		<< prod2_rate;
	
		//the unread newline is left at the read position
		//get() will retrieve it for the next line
		inputStream.get (the_new_line);
	
	//***Testing code - Remove***************
	cout << "Got new line";
	
		if (inputStream.eof ())
			break;

		++line_counter;
		
	//***Testing code - Remove***************	
	cout << "Line number " << line_counter;
		
		avgRatingProd1 (income_level, prod1_rate, incomeA_avg,
				incomeB_avg, incomeC_avg);
		num_incomeB = middleIncomeBothProd (income_level, prod1_rate,
					      prod2_rate);
		avg_prod2 = avgRatingProd2 (prod1_rate, prod2_rate);
	}
	inputStream.close ();

	//--------------------Output------------------------------------
	cout << "There were " << line_counter << " respondents.\n"
		<< "Below is the average rating for product 1, by income bracket: \n"
		<< "Income level A: " << incomeA_avg 
		<< "\nIncome level B: " << incomeB_avg 
		<< "\nIncome level C: " << incomeC_avg 
		<< "\n\nThere were " << num_incomeB <<
		" people who rated product 2 5 or better.\n\n" 
		<< "The average rating for product 2 by people who rated product 1 less than 3 is " << avg_prod2 << endl;
	return 0;
}

/*avgRatingProd1() determines the average rating for product 1 for each income *bracket
*
*Receives: income, a character
*		rating1, an integer
*Send back: incomeA_avg, incomeB_avg, & incomeC_avg, three integers
****************************************************************************/
void
avgRatingProd1 (char income, int rating1, double &incomeA_avg,
		double &incomeB_avg, double &incomeC_avg)
{
	int prod_rate_A = 0, prod_rate_B = 0, prod_rate_C = 0, 
		a = 0, b = 0, c = 0;	//counters

	switch (income)
	{
		case 'A':
		{
			prod_rate_A += rating1;
			++a;
		}
			break;
		case 'B':
		{
			prod_rate_B += rating1;
			++b;
		}
			break;
		case 'C':
		{
			prod_rate_C += rating1;
			++c;
		}
			break;
		default:
			cout << "--Error: avgRatingProd1() invalid income level or rating";
			break;
	}
	incomeA_avg = prod_rate_A / a;
	incomeB_avg = prod_rate_B / b;
	incomeC_avg = prod_rate_C / c;
}

/*middleIncomeBothProd() counts the number of persons in income bracket B who *rated both products 5 or greater
*
*Receives: income, a character
*		prod1_rate & prod2_rate, two integers
*Returns: incomeB, an integer
*************************************************************************/
int
middleIncomeBothProd (char income, int prod1_rate, int prod2_rate)
{
	int incomeB = 0;

	if ((income == 'B') && (prod1_rate >= 5) && (prod2_rate >= 5))
		++incomeB;
	return incomeB;
}

/*avgRatingProd2() determines the average rating for product 2 by persons who *rated product 1 less than 3.
*
*Receives: prod1_rate & prod2_rate, two integers
*
*Returns: avg, an integer
****************************************************************************/
double
avgRatingProd2 (double (prod1), double (prod2))
{
	int  i=0;
	double rate2=0, avg;

	if (prod1 < 3)
	{
		rate2 += prod2;
		++i;
	}
	avg = rate2 / i;
	return avg;
}
__________________
Start Programming with Python-A beginner's guide to programming and the Python language.
-------------
Common Sense v2.0-Striving to make the world a little bit smarter.
  #8  
Old 06-Sep-2004, 10:17
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,200
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by crystalattice
I ran the code on my Windows partition to see if CodeWarrior would help out. It did come up w/ a few things:
1) It found the "divide by zero" that happens on avgRatingProd() when the file isn't input. Not a lot I can do about that unless the file is input.
[/c]

Sure there is, and you must take care of this case if you want any program that you write to be useful. I'm sure CodeWarrier is a good tool if you learn to use it, but, and I hate to repeat myself: cout<< is your friend. You are already writing a C++ program; add some debugging code to help you see what's happening. Call your friends first.

Do something like this in your main()

CPP / C++ / C Code:
  //cout << "Enter the input file name: ";
  ifstream inputStream;  //open input stream to file
  interactiveOpen (inputStream);
  if (inputStream.fail()) {
    cout << endl << endl;
    cout << "Since no input file was opened, program is now terminated.";
    cout << endl << endl;
    return 1;
  }

You shouldn't have your program attempt to do anything else if you don't have an input file to work with. We simply can't have programs bombing out like yours does when there are elegant, predictable ways to keep it from happening.

Note that I commented out your "Enter the input file name: " statement since interactiveOpen() has its own prompt

CPP / C++ / C Code:
      cout << "Enter the name of the input file: ";

Now there is really nothing wrong with interactiveOpen(), but I would have made in an int function rather than void. Then I would have it return a value of 0 if the file was not opened and a value of 1 if it was opened.

then the calling sequence in main() would look like

CPP / C++ / C Code:
  ifstream inputStream;  //open input stream to file
 if (!interactiveOpen(inputStream)){
    cout << endl << endl;
    cout << "Since no input file was opened, program is now terminated.";
    cout << endl << endl;
    return 1;
  }


This is a matter of style rather than substance, and I merely mention it here for your amusement.

Now, as to substance: Suppose someone has a file with the first line like this:
Quote:
B 2 3

Your cout statement that shows these values could be a little more useful, to me at least, if you had something like

CPP / C++ / C Code:
  cout << "Income level and product ratings are: "  << endl
    << "income level = " << income_level 
    << ", prod1_rate = " << prod1_rate     
    << ", prod2_rate = " << prod2_rate
    << endl << endl;

If you have a fear of typing, maybe programming is not your bag (just kidding, but my point is: if you are going to look at something, make it easy to see what you are looking at).

Now, this is still a matter of style instead of substance.

From my previous post, I would put something like this at the beginning of avgRatingProd1:

CPP / C++ / C Code:
  cout << endl;
  cout << "In avgRatingProd1: " 
       << "income = " << income
       << ", rating1 = " << rating1
       << endl << endl;

Then you wouldn't need CodeWarrier to tell you where your program is bombing out.

Now, finally, we get to the substance.

Follow the code (by inspecting the source code)

You start by declaring local variables a, b, and c and initializing them to 0. You also declare local variables prod_rate_A, prod_rate_B, and prod_rate_C and initialize them to 0.

Then, with the given input file, I see that it's going to case B. Here we see that prod_rate_A has its value increased by the input value of rating1 and we see that a is incremented. Now, a is an int that was given a value of 0 at the beginning of the function, so we increment it so that in now has a value of 1.
So far, so good. Break out of the switch statement, and we see the following:
(I added the debug message)

CPP / C++ / C Code:
  incomeA_avg = prod_rate_A / a;
  incomeB_avg = prod_rate_B / b;
  incomeC_avg = prod_rate_C / c;
  cout << "Returning from avgRatingProd1()"<< endl;


You never see the "Returning..." because it bombs out here.

See the problem: First of all you are dividing by b, and b has a value of 0.
From the point of view of what you have to do to calculate the averages, you wouldn't do it this way anyhow. More about that in a minute.

Secondly, suppose you somehow tested to see that it wouldn't divide by zero (by some kind of conditional expression), what would this routine be doing for the prod_rate_A, _B, and _C?

The variables prod_rate_A, _B, and _C are temporary variables that are reinitialized to zero every time this function is invoked (i.e. for every line in your input file). Then one of them might be given a non-zero value in the switch statement, then the variable and its value are gone forever when the program leaves this function.

What you really want to do is something like:

In main(), declare three doubles, say total_A, total_B and total_C. Initialize them to zero. (Actually, in this program they could be ints.)

Then change avgRatingProd1() so that it looks something like
CPP / C++ / C Code:
avgRatingProd1 (char income, int rating1, double &total_A,
    double &total_B, double &total_C)

Inside avgRatingProd1, change the switch statement to something like
CPP / C++ / C Code:
  switch(income)
  {
    case 'A': total_A += rating1;
                 break;

    case 'B': total_B += rating1;
                 break;

    case 'C': total_C += rating1;
                 break;
  }

This function does not compute averages; you must wait until all lines are counted, then divide the total_ values by the number of lines.

(There must be some kind of error checking somewhere that takes care of input lines that don't have one of these values or that don't have valid income levels. I'll let you work on what to do about bad input lines.)

Anyhow, back to main()

After you have read in all of the lines (i.e. after it leaves your for( ; ; ) loop), now you calculate the averages for each product:

CPP / C++ / C Code:
  incomeA_avg = total_A/NumberOfValidLines;

etc.

What is NumberOfValidLines? It's a variable that you initialized to zero, and you incremented it for every line that had valid input values. (Note that if total_A is a double, and NumberOfValidLines is an int, the answer will be what you expect. If total_A and NumberOfValidLines are both int, then you need something like the following to force floating point evaluation of the expression:

CPP / C++ / C Code:
  incomeA_avg = (double)Total_A/NumberOfValidLines;

Please, please, please remember: it is your responsibility to make sure the program can handle bad input lines. You could choose to terminate the program and inform the user what line was bad. You could inform the user that a particular line was bad, and continue with calculations for the rest of the file (using the NumberOfValidLines counter that I suggested above). You could do something else. Whatever you do, don't let the program bomb out so that the user is left staring at some operating system message about floating point exceptions or (for you Windows users)
Quote:
z.exe has encountered a problem and needs to close. We are sorry for the inconvenience.

Best regards,

Dave
Last edited by davekw7x : 06-Sep-2004 at 11:43.
  #9  
Old 06-Sep-2004, 21:17
crystalattice's Avatar
crystalattice crystalattice is offline
Aspiring author
 
Join Date: Apr 2004
Location: Japan (again)
Posts: 1,627
crystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nicecrystalattice is just really nice

Made a little more progress.


I found that the Query.cpp file was bad. I added the line
CPP / C++ / C Code:
ifstream theIFStream;
to it and now I don't get the floating point error, and I can get the rest of the program to run. However, the output is incorrect so I know it's not reading the input file.

I've also found that if it can't read the input file, the input loop doesn't respond correctly. You never get an option to retype the input file; it just auto fails. And, for some reason, it doesn't error out so my program executes anyways, as shown below.
CPP / C++ / C Code:
EXECUTING:
/home/cody/Projects/Project5_15/src/project5_15
----------------------------------------------
This program will determine product rating information based on
respondent income level.

Enter the name of the input file: wrong_file

***InteractiveOpen(): unable to open wrong_file
Try again (Y or N)? y
Enter the name of the input file:
***InteractiveOpen(): unable to open
Try again (Y or N)? y
Enter the name of the input file:
***InteractiveOpen(): unable to open
Try again (Y or N)? n

Income level= @
Product 1 rating= 0
Product 2 rating= 0

Got new line

There were 0 respondents.
Below is the average rating for product 1, by income bracket:
Income level A: -inf
Income level B: -inf
Income level C: inf

There were 0 people who rated product #2 with a 5 or better.

The average rating for product 2 by people who rated product #1
less than 3 is 0

----------------------------------------------
Program exited successfully with errcode (0)
Press the Enter key to close this terminal ...

Now, if I give it the correct test input file, I get the same output w/o the "unable to open" comments. This tells me that it sees the input but for some reason doesn't read it, because it doesn't loop at all. Nor do I see any of my cout testing from the functions.

I'm attaching the new Query.cpp file and my new program source as text files to cut down on the size of this thread.
Attached Files
File Type: txt Query.txt (1.3 KB, 17 views)
File Type: txt Test5_16.txt (5.6 KB, 17 views)
__________________
Start Programming with Python-A beginner's guide to programming and the Python language.
-------------
Common Sense v2.0-Striving to make the world a little bit smarter.
  #10  
Old 06-Sep-2004, 21:42
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,200
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
I didn't notice the bug in query.cpp. The problem is that when you enter the 'y', the input buffer still has a newline character, so the next time through the loop, the program thinks you just typed a newline.

One way to get around this is to put the following at the end of the do-while loop in interactiveOpen():

CPP / C++ / C Code:
      cin >> response;
      while (cin.get ( ) != '\n' ) {
        ;
      }

This uses the get() function to eat up everything up to and including the newline. (For example if you typet "Yes" instead of "y").

I'll look over your other program and get back to you.

Dave
 
 

Recent GIDBlogProgramming ebook direct download available by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Encryption implementation issue bigbangman C Programming Language 6 02-Sep-2004 12:21
Floating point operand? warny_maelstrom C Programming Language 11 04-Mar-2004 14:31

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 23:35.


vBulletin, Copyright © 2000 - 2009, Jelsoft Enterprises Ltd.