• Welcome to Computer Association of SIUE - Forums.
 

help on some c++ code

Started by Rick Lynch, 2007-09-24T19:03:24-05:00 (Monday)

Previous topic - Next topic

Rick Lynch

Hey everyone, I'm not in CS 140, yet, but I'm trying to get a headstart and keep up with my friends in there... anyway, I'm teaching myself via Accelerated C++, and there is an exercise in there that requires me to...

"3-2. Write a program to compute and print the quartiles (that is, the quarter of the numbers with the largest values, the next highest quarter, and so on) of a set of integers"

Yeah, I have got this:

//exercise 3.2
#include
#include
#include
#include
using namespace std;

int main()
{
cout << "Please enter any amount of positive intergers and then end-of-file: " << endl;

vector set;
double num;

//obtain values and add to vector
while (cin >> num)
set.push_back(num);

//making synonym type vctsz
typedef vector::size_type vctsz;
vctsz size = set.size();

if (size == 0)
{
cout << "Whoops! You didn't enter any values. Please try again." << endl;
return 1;
}

//sort numbers from lowest to highest
sort(set.begin(), set.end());

vctsz a = (size)/4;
vctsz b = size - 1;
vctsz c = 1;

for (vctsz count = 0; count <= b; ++count)
{
if (count == b)
{
cout << set[b - count] << "....Finished!n" << endl;
} else {
if (c < a)
{
cout << set[b - count] << ", ";
++c;
} else {
cout << set[b - count] << "." << endl;
c = 1;
}
}
}

return 0;
}

I was wondering if this is the best way, or if there is a better way to do so? Keep in mind, I don't know much, so don't go too in depth, haha. The only thing that really irratates me is when there are 7 values entered, it wont divide it up into 4 lines, it just prints 7 numbers on 7 different lines... I don't know. Any help is appreciated.
Rick Lynch - Junior
Applied Mathematics Major
(Don't let this fool you. I love CS as well!)

bandyguy

wow, I'm in 150 and I've never seen vector or algorithm librarys.

blacklee

Integer division ignores decimals, so 7/4 is 1. Try using ceiling function from math.h library.

Rick Lynch

Alright, I will give it a try, and post how it turns out! Thanks.
Rick Lynch - Junior
Applied Mathematics Major
(Don't let this fool you. I love CS as well!)

Shaun Martin

Vector is the lazy man's dynamic array.
Shaun Martin
SIUE Alumni
Associate IT Analyst, AT&T Services, Inc. St. Louis, MO.

Rick Lynch


//exercise 3.2
#include
#include
#include
#include
#include
using namespace std;

int main()
{
cout << "Please enter any amount of positive intergers and then end-of-file: " << endl;

vector set;
double num = 0;

//obtain values and add to vector
while (cin >> num)
set.push_back(num);

//making synonym type vctsz
typedef vector::size_type vctsz;
vctsz size = set.size();

if (size == 0)
{
cout << "Whoops! You didn't enter any values. Please try again." << endl;
return 1;
}

//sort numbers from lowest to highest
sort(set.begin(), set.end());

double a = ceil(double(size)/4);
vctsz b = size - 1;
double c = ceil(double(1/a));

for (vctsz count = 0; count <= b; ++count)
{
if (count == b)
{
cout << set[b - count] << "....Finished!n" << endl;
} else {
if (c < a)
{
cout << set[b - count] << ", ";
++c;
} else {
cout << set[b - count] << "." << endl;;
c = ceil(double(1/a));
}
}
}

return 0;
}



Ok, this is what I have. It still doesn't do exactly what I'd like it to do. If 6 values, or 10 values are entered, it wont give the right output. All other values, except for (multiples of 4)+1 or 2, will work. If it's 5 values that are entered for example, it'll output:
5, 4.
3, 2.
1....Finished.
I want:
5.
4.
3.
2, 1....Finished.
For 6, it'll give:
6, 5.
4, 3.
2, 1....Finished
I want:
6.
5.
4, 3.
2, 1....Finished.
I understand why it isn't working. I know it's the mathematical stuff that I put in, but I'm just not sure how to fix it. The ceiling function did put me a step closer though. Thanks again. I hope someone can provide further help to get me closer to my final solution!
Rick Lynch - Junior
Applied Mathematics Major
(Don't let this fool you. I love CS as well!)

Mark Sands

I looked up what a quartile actually is because I'd never heard of this. I found a site here: http://www.statcan.ca/english/edu/power/ch12/range.htm that explains it pretty well. I am not sure if you are correct when inputting 6 should yield:
6.
5.
4, 3.
2, 1...Finished!

Since the median is 3.5, the first quartle is half of the median which would be 1.5, and the last quartle would be 4.5 Inputting these numbers should yield:

6.
5, 4.
3.
2, 1...Finished!

So I hope I did that right.
One thing to note however, floating decimals won't calculate unless you add the decimal, for example 2 should be 2.0 And typedefing double::size_type isn't necessary, just std::size_t will work just as well. Also, I'm glad someone else is teaching themselves outside of the classroom like myself :)

my code is below, for the way I learned, if it's not right and not what you're looking for I apologize for me being stupid ^_^



//exercise 3.2
#include
#include
#include
#include

using namespace std;

int main()
{
cout << "Please enter any amount of positive intergers and then end-of-file: " << endl;

vector set;
double num = 0;

//obtain values and add to vector
while (cin >> num)
set.push_back(num);

if (set.size() == 0)
{
cout << "Whoops! You didn't enter any values. Please try again." << endl;
return 1;
}

//sort numbers from highest to lowest
sort(set.rbegin(), set.rend());


//set up our rows
vector::iterator miter = (set.begin() + (set.size()/2.0)); //median 1/2
vector::iterator otiter =(set.begin() + (set.size()/4.0)); //first quartile 1/4
vector::iterator ttiter =(set.begin() + 3*(set.size()/4.0)); //final quartile 3/4

vector::iterator diter = set.begin(); //our iterator throughout the program


while(diter < set.end())
{
if (diter == otiter-1) {
std::cout << *diter++ << "." << endl;
} else if (diter == miter-1) {
std::cout << *diter++ << "." << endl;
} else if (diter == ttiter-1) {
std::cout << *diter++ << "." << endl;
} else if (diter == set.end()-1) {
std::cout << *diter++ << "...Finished!" << endl;
} else {
std::cout << *diter++ << ", ";
}
}


return 0;
}
Mark Sands
Computer Science Major

William Grim

Actually, everyone's idea here of a quartile is slightly incorrect. It actually doesn't have anything to do with medians of raw data values or any other aggregate functions (well, technically speaking, it does, but as we will see, it is irrelevant). What it does have to do with is sets of numbers that, for the sake of making an argument, are sorted.  Within these sets, we deal with lengths of the subsets and the mid-points of each subset.

Given the list {1,2,3,3,3,3,4,5,6,7,7,7,8,8,8}, you have the set {1,2,3,4,5,6,7,8}.

The four quartiles would then contain:
{1,2}
{3,3,3,3,4}
{5,6}
{7,7,7,8,8,8}

Luckily, the math is pretty basic. The hard part is just understanding what a quartile precisely is.

P.S.: I congratulate both of your efforts on this problem, seeing as you are both freshmen. That's a lot more advanced than most freshmen prefer to handle.
William Grim
IT Associate, Morgan Stanley

Tony

I just had stats 380 over the summer.  For quartiles, for the first quartile, there are two equations, one for if there are an even number of items and one for if there is an odd number of items.  This might be why he was getting incorrect answers for even numbers.

Quartile 1 is:
Odds = (n + 3)/4
Evens = (n + 2)/4

Quartile 2 is the median.  The median is usually just the middle number, but if there is an even number of items then it is the average of the two middle numbers.  

Quartile 3 is: (n + 1) - Q1.

The problem is that these numbers need to be sorted.  So, unless they have to enter them in order, you need to sort them first.  

Secondly, just keep a count of them and mod it by 2 to see if it is even or odd and use a simple set of if statements to decide what formulas to use.  Use your count a n and then just use the number those formulas give you to get Q1 and Q2 and you can figure out what to do to find the Median if it is odd or even.  

If what you need is Quartiles 1, 2 and 3 that is how that should go.  I hope this is helpful, and I hope I am talking about the right thing because I am kind of confused by what you are doing.
I would rather be hated for doing what I believe in, than loved for doing what I don't.

William Grim

Oh, right right.  The problem I solved was slightly different.  I solved quartiles using unique sets rather than just finding each quarter of a list, because I got the definition wrong after lecturing everyone about it.  My bad.
William Grim
IT Associate, Morgan Stanley

Rick Lynch

I guess my true mistake is not correctly understand what a quartile was, hah. Thanks to everyone for all of your help. I'll see what I can do... If only there was a site where I could find solutions to this book.
Rick Lynch - Junior
Applied Mathematics Major
(Don't let this fool you. I love CS as well!)

Tony

I is great that you are trying to learn on your own, but don't tear yourself up about it.  You will have plenty of time to learn stuff like this.

Also, some of the stuff you are using isn't used for awhile in the CS degree, and some of this could be done in more simple ways, which you will learn once you get further into the degree.  

So, keep at it, but don't worry if you can't figure something out.  You are ahead of most freshman, that is for sure.
I would rather be hated for doing what I believe in, than loved for doing what I don't.

Rick Lynch

hah! Don't worry, I wont tear myself over it, but I just like solving problems and figuring them out. It really bugs me when I can't. As far as learning easier ways: It will be nice, but it never hurts to understand the basic stuff thoroughly, which is why I wish to know it the best I can before I move on...

Ok, as far as Exercise 3.2 goes, I'll get back to it later, for now, I actually have another issue. I'm so close to solving this one:

"3-5. Write a program that will keep track of grades for several students at once. The program could keep two vectors in sync: The first should hold the student's names, and the second the final grades that can be computed as input is read. For now, you should assume a fixed number of homework grades."

Here is the code I have:

#include
#include
#include
#include
#include
using namespace std;

void main()
{
//vectors to hold names
vector name;

//getting the names (works!)
cout << "Please enter the students names and then end-of-file: " << endl;
string x;
while (cin >> x)
{
name.push_back(x);
}

cout << endl << endl;

vector score;

//getting the grades
for (unsigned int count1 = 0; count1 <= (name.size() - 1)  ; ++count1)
{
cout << "Please enter " << name[count1] <<
"'s midterm and final scores: " << endl;

double midterm, final;

/*Here is where it isn't working.
The program will not let the user enter values! Why?!*/
cin >> midterm >> final;

double z = (0.2 * midterm + 0.4 * final + 0.4 * 90.0);
score.push_back(z);

}

streamsize prec = cout.precision();
setprecision(3);
cout << endl << endl;

//writing the grades
unsigned int count2 = 0;
while (count2 <= (name.size() - 1))
{
cout << name[count2] << "'s final grade: " << score[count2] << "." << endl;
++count2;
}

setprecision(prec);
}


For whatever reason, it will not let me enter values for the grades. I don't understand. I have changed the program around in multiple ways, yet it still values to get the values. It's perplexing me. It is probably a simple problem, but I still wish to figure it out. Thanks in advance for anyones help!
Rick Lynch - Junior
Applied Mathematics Major
(Don't let this fool you. I love CS as well!)

William Grim

Your issue is that you rely on EOF to be set when you are in your first loop, but you never clear EOF before entering your second loop.  So, your second loop never executes, because it still thinks it's at the end of file.

Most would think that simply calling "cin.clear();" would do the trick to clear EOF.  However, this is not the case, because we are still at an EOF character in the input stream.  Therefore, we have to rewind our stream by a character and then call "cin.clear();" to resume input.  The code below demonstrates how to do that.


#include
#include
#include
#include
#include
#include
using namespace std;

int main()
{
  //vectors to hold names
  vector name;
 
  //getting the names (works!)
  cout << "Please enter the students names and then end-of-file: " << endl;
  string x;
  while (cin >> x) {
    name.push_back(x);
  }
 
  cin.clear();    // do this first or the next call will fail!
  cin.unget();   // rewind our stream by one character
 
  cout << endl << endl;
 
  vector score;
 
  //getting the grades
  for (unsigned int count1 = 0; count1 < name.size(); ++count1)
  {
    cout << "Please enter " << name[count1] <<
    "'s midterm and final scores: " << endl;
   
    double midterm, final;
    cin >> midterm >> final;
   
    double z = (0.2 * midterm + 0.4 * final + 0.4 * 90.0);
    score.push_back(z);
   
  }
 
  streamsize prec = cout.precision();
  setprecision(3);
  cout << endl << endl;
 
  //writing the grades
  unsigned int count2 = 0;
  while (count2 <= (name.size() - 1))
  {
    cout << name[count2] << "'s final grade: " << score[count2]
  << "." << endl;
    ++count2;
  }
 
  setprecision(prec);
  return 0;
}
William Grim
IT Associate, Morgan Stanley

Rick Lynch

I did not know that EOF did that, which is kind of silly considering it is pretty self explanatory. I tried cin.clear() and cin.get(), but they did not do anything for me; still the problem pertained. So taking in what you said about EOF, I simply created a "quit" option instead of using EOF, and now it works flawlessly... here is the code:


//exercise 3.5
#include
#include
#include
#include
#include
using namespace std;

void main()
{
//vectors to hold names
vector name;

//getting the names (works!)
cout << "Please enter the students names and then enter 'quit': " << endl;
string x;
while (cin >> x)
{
if (x == "quit" || x == "q" || x == "Quit" || x == "Q")
{
break;
} else {
name.push_back(x);
}
}

cout << endl << endl;

//checks to see if names were entered
if ( name.size() == 0 )
{
cout << "You have to enter names! Please restart." << endl << endl;
return;
}

vector score;

//getting the grades
for (unsigned int count1 = 0; count1 <= (name.size() - 1)  ; ++count1)
{
cout << "Please enter " << name[count1] <<
"'s midterm and final scores: " << endl;

double midterm, final;
cin >> midterm >> final;

double z = (0.2 * midterm + 0.4 * final + 0.4 * 90.0);
score.push_back(z);
}

//checks if grades were entered correctly. Such as a user entering a string.
if (score.size() != name.size())
{
cout << "You have not entered enough grades. Please try again." << endl;
}

streamsize prec = cout.precision();
setprecision(3);

cout << endl << endl;

//writing the grades
unsigned int count2 = 0;
while (count2 <= (name.size() - 1))
{
cout << name[count2] << "'s final grade: " << score[count2] << "." << endl;
++count2;
}

cout << endl;
setprecision(prec);
}


Thanks a lot for the heads up!
Rick Lynch - Junior
Applied Mathematics Major
(Don't let this fool you. I love CS as well!)