1

I've been bashing my head against these drills for days and I can't grasp them. I have to add a unit to my numbers (i.e m,ft,in,cm.) and reject invalid units, then convert the numbers and units into metres.
I have my code that shows how to choose and keep the highest and lowest numbers etc, but i'm at a complete loss as to how to add the unit part, i've tried if statements and they seem to look like they'll work, but then they don't and i get frustrated and it honestly bugs me that i've missed some fundamental point. here is my code so far

int main(){
double val1=0;
string unit;
double large=0;
double small=0;

cout<<"please Enter 1 number and a unit (cm, M, Ft, In):\n";
while (cin>>val1>>unit){

    if(val1<small) {small=val1; cout<<"smallest so far\n";}//find smallest number
    else if(val1>large) {large=val1; cout<<"largest so far\n";}//Find largest    number



else cout<<"Neither largest nor smallest\n";
}
cout<<"The smaller value so far is (in metres): "<<small<<"\n";
cout<<"The larger value so far is (in metres): "<<large<<"\n";

keep_window_open("~");
return 0;

}

It's not homework and I'm only doing this for my own interest. any help would be appreciated.

Bob Mc Bob
  • 17
  • 1
  • 2
  • Bjarne walks through some code involving user defined literals for units in a recent presentation http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Keynote-Bjarne-Stroustrup-Cpp11-Style starting at about minute 23. That might help you :-) – Kate Gregory Feb 14 '12 at 14:37
  • 2
    `then convert the numbers and units into metres`, Where? I don't see you converting. – atoMerz Feb 14 '12 at 14:38
  • You don't seem to be retaining the smallest distance. You should read in the first distance, make it the largest *and* smallest, then proceed with the loop. – Beta Feb 14 '12 at 14:43
  • Yup - once you have `val1` and `unit`, you ignore `unit` and just assume `val1` is in metres. – Useless Feb 14 '12 at 14:47
  • This line from Bjarne really bugs me: "You may consider 12 m (with a space between the number and the unit) equivalent to 12m (without a space)". Reading units separated from numbers with a space was easy with std::cin, but I just can't get it to "eat" stuff like "12ft" – Maksim Gayduk Mar 14 '17 at 15:14
  • @MaksimGayduk yes that threw me off too at first: now I just read it as saying "Don't even try to deal with stuff like `12ft`, just read in space-delimited value/unit pairs such as `12 ft`". – eric Apr 08 '18 at 03:11

7 Answers7

2

1 .By chapter 4 you already know about constants and "magic constants or numbers"
(What is a magic number, and why is it bad?).

2 . cout << "please Enter 1 number and a unit (cm, M, Ft, In):" << endl; this is wrong becouse you use upper case and you test lower case letters.



3 .if (small == 0 && val1 > large)

if i enter 0 m it says its "its neither largest nor smallest" like those are already set, better use

  if(small=0 && large==0)



4 .Personaly i dont like that conversion into meters i would rather use

    if(unit=="m")
    {
        if( (val1*=m_in_cm) <= small)
        {
            std::cout<<"\nThe smallest value so far "<<val1<<" "<<unit<<" \n";
            small=val1;
        }
        if( (val1*=m_in_cm) >= large)
        {
            std::cout<<"\nThe largest value so far "<<val1<<" "<<unit<<" \n";
            large=val1;
        }
    }
    else if(unit=="in"){....}

where "m_in_cm" is

const double m_in_cm=100;

It keeps original value and unit used.

Community
  • 1
  • 1
Josip7171
  • 93
  • 1
  • 10
  • At first I did not understand your answer for #2 because that does not match the code in the original post. However after I found the answer from the same person who wrote the question it makes sense. – drescherjm Mar 21 '14 at 12:59
  • This is a very good analysis of the OP's code. I would just suggest use `constexpr` instead of `const` because you know that `m_in_cm` is going to be set at compile time. – eric Apr 08 '18 at 03:24
2

Here is my solution. I would prefer to just check the vector for the highest and lowest values, but that isn't what the drill asks for? Seems like a pretty janky program Bjarne wanted us to make with this drill.

#include "../../std_lib_facilities.h"
void inMeters(double n) { //just seeing if i can call a function here, not needed.
    cout << "that is " << n << " in meters!\n";
}

int main() {
    double small_val; //declaring variables.
    double large_val;
    double val1;
    double val1_meter = 0;
    char unit = 'z';
    vector <double> all_vals;
    double total_meters = 0;

    constexpr double meter_per_cm = 0.01;
    constexpr double meter_per_inch = 0.03;
    constexpr double meter_per_ft = 0.3;



    cout << "Choose a starting number\n"; //make user choose starting number because while loops wont accept null variables >.>
    cin >> val1;
    small_val = val1;
    large_val = val1;

    cout << "Now pick a number! and a unit (c, m, i, f)\n";     //user inputs number and it is assigned to highest lowest or no variable.
    while (cin >> val1 >> unit) {
       if (val1 >= small_val && val1 <= large_val)
           cout << val1 << " is not a record.\n";
       if (val1 < small_val) {
           small_val = val1;
           cout << val1 << " Smallest number yet.\n";
       }
       if (val1 > large_val) {
           large_val = val1;
           cout << val1 << "Largest number yet.\n";
       }

       switch (unit) {
          case 'c' :
           val1_meter = val1 * meter_per_cm;
           inMeters(val1_meter);
           all_vals.push_back(val1_meter);
           break;
          case 'm' :
           val1_meter = val1;
           inMeters(val1_meter);
           all_vals.push_back(val1_meter);
           break;
          case 'i' :
           val1_meter = val1 * meter_per_inch;
           inMeters(val1_meter);
           all_vals.push_back(val1_meter);
           break;
          case 'f' :
           val1_meter = val1 * meter_per_ft;
           inMeters(val1_meter);
           all_vals.push_back(val1_meter);
           break;
          default :
           cout << "Invalid unit!\n";
           break;
       }



   }
   for (int i = 0; i < all_vals.size(); i++) {
    total_meters += all_vals[i];
   }
   cout << "here's your stats!\n" <<
    "Smallest number: " << small_val << '\n' <<
    "Largest number: " << large_val << '\n' <<
    "Total numbers accepted: " << all_vals.size() << '\n' <<
    "Total length in meters: " << total_meters << '\n';
   cout << "All valid entries this play:\n";
   sort(all_vals);
   for (int i = 0; i < all_vals.size(); i++)
       cout << all_vals[i] << '\n'; 
}
John
  • 21
  • 2
0

this how i solved it

 #include "../../std_lib_facilities.h"
double unitconv(double x, string y) // a function to convert units. 
{
    if (y == "in")
    {
        x = x / 39.37;
        y = "m";
    }
    else if (y == "ft")
    {
        x = x / 3.28;
        y = "m";
    }
    else if (y == "cm")
    {
        x = x / 100;
        y = "m";
    }
    else if (y == "m")
    {
        x = x;
        y = y;
    }
    else
        cout << "unrecognised unit";
    return x;

}

int main()
{
    double value = 0;
    string unit = " ";
    double sum = 0;
    int iter = 0;
    vector<double>values;
    cin >> value >> unit;
    value = unitconv(value, unit); 
    values.push_back(value);
    sum = sum + value;
    ++iter;
    double largest = value;
    double smallest = value;
    while (cin >> value >> unit)
    {
        value = unitconv(value, unit); 
        if (value > largest)
        {
            largest = value;
        }
        if (value < smallest)
        {
            smallest = value;
        }
        values.push_back(value);
        sum = sum + value;
        ++iter;
        cout << "\nLargest Value = " << largest <<  "\nSmallest Value = " << smallest << "\nSum of Values = " << sum << "\nNumber of Values = " << iter << "\n";
    }
    sort(values.begin(),values.end());
    for (int i = 0; i < values.size(); ++i)
        cout << values[i] << '\n';
    keep_window_open();
}
  • I like the attempt to use a function, but if the unit is invalid, this just continues on as if nothing happened. My answer adds the validation layer needed to make sure this doesn't happen, without kicking out of the `while` loop with `break`. – eric Apr 08 '18 at 04:01
0
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

int main()
{
    double a = 0.0;
    vector<double> double_vec;

    int iterator = 0;
    double temp_smallest = 0;
    double temp_largest = 0;
    int count = 0;

    while (cin >> a)
    {
        // add i to the vector;
        double_vec.push_back(a);

        for (int i = 0; i < count; i++)
        {
            if (double_vec[i] > temp_largest)
            {
                temp_largest = double_vec[i];
            }

            else if (double_vec[i] < temp_smallest)
            {
                temp_smallest = double_vec[i];
            }
        }

        if (temp_smallest > a)
            cout << "smallest so far" << endl;
        else if (temp_largest < a)
            cout << "largest so far";
        count++;
    }

    system("PAUSE");

    return 0;
}

Chapter 4 does discuss vectors, there are a few modifications that can be added to perform tests on all values. This program works for most, but not all values.

Pang
  • 9,564
  • 146
  • 81
  • 122
  • This doesn't handle units, which is what makes this problem a challenge to deal with in the first place. – eric Apr 08 '18 at 04:02
0

Here is my solution. What I find concerning about all the other solutions is how they are handling the invalid inputs (i.e., those with invalid units). Most of them just add the value to the vector anyway. Some just break out of the while loop without giving the user the chance to keep adding values.

I am also using conventions suggested by Stroustrup such as constexpr constants, and a ranged for loop.

The additional complexity in my version is a valid_entry flag that is set on each loop. If the input is not valid, the program does not stop, it simply loops around again.

#include "std_lib_facilities.h"

int main()
{
  constexpr double METERS_PER_CM = 1/100.0;
  constexpr double METERS_PER_IN = 1/39.37; //avoid magic #s!
  constexpr double METERS_PER_FT = 1/3.28;

  double smallest_so_far = 0;
  double largest_so_far = 0;
  double current_val = 0;
  double current_val_meters = 0;
  vector<double> all_distances;
  double values_sum = 0;
  string units;
  bool valid_entry = true; //if they enter some bs, set to false

  cout << fixed << showpoint << setprecision(3);
  cout << "Please enter length and unit. Enter single char if done.\n"
      << "Assume 0 was first. Units are cm, m, in, ft.\n\n";
  while ( cin >> current_val >> units)
  {
    cout << "You entered " << current_val << units << ".\n";
    //process units: convert to meters
    if (units == "m")
      current_val_meters = current_val;
    else if (units == "cm")
      current_val_meters = current_val * METERS_PER_CM;
    else if (units == "in")
      current_val_meters = current_val * METERS_PER_IN;
    else if (units == "ft")
      current_val_meters = current_val * METERS_PER_FT;
    else
    {
      cout << "You done messed up A-aron!\n";
      valid_entry = false;
    }

    if (valid_entry)
    {
      if (units != "m")
        cout << "\nThat is " << current_val_meters << " meter(s)!\n";

      //add to vector
      all_distances.push_back(current_val_meters);
      //deal with relative sizes
      if (current_val_meters < smallest_so_far)
      {
        cout << "Smallest so far!\n";
        smallest_so_far = current_val;
      }
      if (current_val_meters > largest_so_far)
      {
        cout << "Largest so far!\n";
        largest_so_far = current_val_meters;
      }
  } // valid_entry
    valid_entry = true;
    cout << "\nAnother...?\n";
  }  // while cin

  //When done, present summary statistics
  cout << "You entered " << all_distances.size() << " values.\n";
  //Get sum
  sort(all_distances);
  cout << "All the values you entered: \n";
  for (double x: all_distances)
  {
    values_sum += x;
    cout << x << "\n";
  }
  cout << "Sum of all meters: " << values_sum << "\n";

  //show min and max
  cout << "The max was " << largest_so_far << ", and the min was "
       << smallest_so_far << ".\n";

  cout << "\nHave a good day!\n";
  return 0;
};
eric
  • 7,142
  • 12
  • 72
  • 138
0

Here is my solution with using just the topics discussed till Chapter 4. Try to organize and list down first all the steps you want to execute before putting them up in code. Then check if you have missed any case. Also, think first of solutions which only involve the topics that have been discussed so far.

int main() {
    double val {0};
    double smallest {0};
    double largest {0};
    string unit {""};
    vector<string> valid_units {"cm", "m", "in", "ft"};

    // first instance
    cin >> val >> unit;
    smallest = largest = val;
    string s_unit {unit};
    string l_unit {unit};
    print_values(val, unit, smallest, s_unit, largest, l_unit);

    // vector of entered values
    vector<double> entered_values_in_meters {convert_to_meters(val, unit)};

    // loop
    while (cin >> val >> unit) {
        // check for valid units
        bool is_valid = false;
        for (string valid_unit: valid_units) {
            if (unit == valid_unit)
                is_valid = true;
        }
        if (!is_valid) {
            cout << "Invalid unit. Exiting." << endl;
            break;
        }

        // convert units into meters
        double val_m = convert_to_meters(val, unit);
        double smallest_m = convert_to_meters(smallest, s_unit);
        double largest_m = convert_to_meters(largest, l_unit);

        // store the input into the vector
        entered_values_in_meters.push_back(val_m);

        // check for smallest and largest
        if (val_m <= smallest_m) {
            smallest = val;
            s_unit = unit;
        }

        if (val_m >= largest_m) {
            largest = val;
            l_unit = unit;
        }

        // print out values
        print_values(val, unit, smallest, s_unit, largest, l_unit);
    }

    // sort and write out the entered values
    sort(entered_values_in_meters);
    cout << "Entered values in meters: " << endl;
    for (double val: entered_values_in_meters)
        cout << val << "     ";
}


void print_values(double val, string v_unit, double smallest, string s_unit, double largest, string l_unit) {
    cout << "value entered: " << val << v_unit << endl <<
            "smallest so far: " << smallest << s_unit << endl <<
            "largest so far: " << largest << l_unit << endl;
}


double convert_to_meters(double val, string unit) {
    // get integer equivalent of the unit
    int unit_value = int{unit[0]};
    if (unit.size() > 1) {
        unit_value += int{unit[1]};
    }

    // switch case
    switch (unit_value) {
        case (int{'c'} + int{'m'}):
            val *= 0.01;
            break;
        case (int{'i'} + int{'n'}):
            val *= 0.0254;
            break;
        case (int{'f'} + int{'t'}):
            val *= 0.3048;
            break;
        default: // for 'm'
            val *= 1;
            break;
    }

    return val;
}
thox
  • 129
  • 4
  • 13
-1

Ok I think i got it. Keep in mind that I only know these basics from the first 4 chapters, so considering the tools i have so far, is this a proper way of doing this?

int main(){

double val1 = 0;
string unit;
double large = 0;
double small = 0;

cout << "please Enter 1 number and a unit (cm, M, Ft, In):" << endl;

while (cin >> val1 >> unit) {
    if (unit == "cm") val1 = val1/100;
    else if (unit == "m") val1 = val1;
    else if (unit == "in") val1 = val1 * 0.0254;
    else if (unit == "ft") val1 = val1 * 0.3048;
    else {
        cout << endl << "dont understand " << unit;
        break;
    }

    if (small == 0 && val1 > large){
        small = val1;
        large = val1;
        cout << val1 << "metres is both the largest and smallest" << endl;
    } else if (val1 < small) { 
        small = val1;
        cout << small << " metres is the smallest so far" << end;
    } else if (val1 > large){
        large = val1;
        cout << large <<" metres is the largest so far" << endl;
    } else {
        cout << val1 << " metres is neither largest nor smallest" << endl;
    }
}

cout << endl << small << " metres" << "\t" << "is the smallest number" << endl << large << " metres" << "\t" << "is the largest number" << endl;

keep_window_open("~");
return 0;
}
Vic
  • 21,473
  • 11
  • 76
  • 97
Bob Mc Bob
  • 17
  • 1
  • 2
  • Maybe it's just me but i think you should indent your code better (e.g. everything in the scope of the main function should be indented and everything in the scope of the while loop should be indented). You should also use std::endl instead of placing the newline manually (e.g. 'cout << "bla" << endl;'). –  Feb 14 '12 at 23:41
  • yes, my indenting needs attention for sure, I didn't know about the endl thing, thanks – Bob Mc Bob Feb 14 '12 at 23:53
  • For everything wrong with your code, see @user3446166's answer. Also, I initinally tried using `break` with this problem, but don't l ike it because it breaks free of the `while` loop altogether, rather than just moving on to the next number. – eric Apr 08 '18 at 03:25