Project 1 - Body-mass index
bmi.cpp
Go to the documentation of this file.
1 
39 #include <algorithm>
40 #include <cstdlib>
41 #include <iomanip>
42 #include <iostream>
43 #include <istream>
44 #include <limits>
45 #include <locale>
46 #include <ostream>
47 #include <string>
48 #include <vector>
49 
60 int compute_bmi(int height, int weight)
61 {
62  return static_cast<int>(weight * 10000 / (height * height) + 0.5);
63 }
64 
66 void skip_line()
67 {
68  std::cin.ignore(std::numeric_limits<int>::max(), '\n');
69 }
70 
79 bool get_record(std::vector<std::string>& names,
80  std::vector<int>& heights,
81  std::vector<int>& weights,
82  std::vector<char>& sexes)
83 {
84  std::string name{};
85  int height{0};
86  int weight{0};
87  char sex{'?'};
88 
89  std::cout << "Name " << names.size()+1 << ": ";
90  if (not std::getline(std::cin, name))
91  return false;
92 
93  // Enforce minimal sanity check on the height, which must be
94  // between 10 and 300 cm, or baby- to giant-size.
95  int const min_height{10};
96  int const max_height{300};
97  std::cout << "Height (cm): ";
98  if (not (std::cin >> height))
99  return false;
100  skip_line();
101  if (height < min_height or height > max_height)
102  {
103  std::cout << "Invalid height. Aborting.\n";
104  return false;
105  }
106 
107  // Enforce minimal sanity check on the weight, which must
108  // be between premature-baby and giant size.
109  int const min_weight{1};
110  int const max_weight{500};
111  std::cout << "Weight (kg): ";
112  if (not (std::cin >> weight))
113  return false;
114  skip_line();
115  if (weight < min_weight or weight > max_weight)
116  {
117  std::cout << "Invalid weight. Aborting.\n";
118  return false;
119  }
120 
121  std::cout << "Sex (M or F): ";
122  if (not (std::cin >> sex))
123  return false;
124  skip_line();
125  sex = std::toupper(sex, std::locale());
126  if (sex != 'M' and sex != 'F')
127  {
128  std::cout << "Invalid sex. Aborting.\n";
129  return false;
130  }
131 
132  // All information has now been collected, so
133  // append it all to the respective vectors.
134  names.push_back(name);
135  heights.push_back(height);
136  weights.push_back(weight);
137  sexes.push_back(sex);
138 
139  return true;
140 }
141 
155 void print_table(char sex,
156  std::vector<int> const& heights,
157  std::vector<int> const& weights,
158  std::vector<int> const& bmis,
159  std::vector<char> const& sexes,
160  std::vector<std::string> const& names,
161  int threshold)
162 {
163  std::cout << "Ht(cm) Wt(kg) Sex BMI Name\n";
164 
165  float bmi_sum(0);
166  long int bmi_count(0);
167  std::vector<int> tmpbmis; // store only the BMIs that are printed
168  // to compute the median
169  for (std::vector<int>::size_type i(0); i != heights.size(); ++i)
170  if (sexes.at(i) == sex)
171  {
172  bmi_sum = bmi_sum + bmis.at(i);
173  ++bmi_count;
174  tmpbmis.push_back(bmis.at(i));
175  std::cout << std::setw(6) << heights.at(i)
176  << std::setw(7) << weights.at(i)
177  << std::setw(3) << sexes.at(i)
178  << std::setw(6) << bmis.at(i);
179  if (bmis.at(i) >= threshold)
180  std::cout << '*';
181  else
182  std::cout << ' ';
183  std::cout << ' ' << names.at(i) << '\n';
184  }
185 
186  // If the vectors are not empty, print basic statistics.
187  if (bmi_count != 0)
188  {
189  std::cout << "Mean BMI = "
190  << std::setprecision(1) << std::fixed << bmi_sum / bmi_count
191  << '\n';
192 
193  // Median BMI is trickier. The easy way is to sort the
194  // array and pick out the middle item or items.
195  std::sort(tmpbmis.begin(), tmpbmis.end());
196  std::cout << "Median BMI = ";
197  // Index of median item.
198  int i(tmpbmis.size() / 2);
199  if (tmpbmis.size() % 2 == 0)
200  std::cout << (tmpbmis.at(i) + tmpbmis.at(i-1)) / 2.0 << '\n';
201  else
202  std::cout << tmpbmis.at(i) << '\n';
203  }
204 }
205 
207 int main()
208 {
209  std::locale::global(std::locale{""});
210  std::cout.imbue(std::locale{});
211  std::cin.imbue(std::locale{});
212 
213  std::vector<std::string> names{};
214  std::vector<int> heights{};
215  std::vector<int> weights{};
216  std::vector<char> sexes{};
217  std::vector<int> bmis{};
218  int threshold{};
219 
220  std::cout << "Enter threshold BMI: ";
221  if (not (std::cin >> threshold))
222  return EXIT_FAILURE;
223  skip_line();
224 
225  std::cout << "Enter name, height (in cm),"
226  " and weight (in kg) for each person:\n";
227  while (get_record(names, heights, weights, sexes))
228  {
229  int bmi{compute_bmi(heights.back(), weights.back())};
230  bmis.push_back(bmi);
231  std::cout << "BMI = " << bmi << '\n';
232  }
233 
234  // Print the data.
235  std::cout << "\n\nMale data\n";
236  print_table('M', heights, weights, bmis, sexes, names, threshold);
237  std::cout << "\nFemale data\n";
238  print_table('F', heights, weights, bmis, sexes, names, threshold);
239 }
int main()
Main program to compute BMI.
Definition: bmi.cpp:207
void skip_line()
Skip the rest of the input line.
Definition: bmi.cpp:66
void print_table(char sex, std::vector< int > const &heights, std::vector< int > const &weights, std::vector< int > const &bmis, std::vector< char > const &sexes, std::vector< std::string > const &names, int threshold)
Print a table. Print a table of height, weight, sex, BMI, and name. Print only records for which sex ...
Definition: bmi.cpp:155
int compute_bmi(int height, int weight)
Compute the body-mass index (BMI). The height is in centimeters, so the computed value is off by 10...
Definition: bmi.cpp:60
bool get_record(std::vector< std::string > &names, std::vector< int > &heights, std::vector< int > &weights, std::vector< char > &sexes)
Get a single person&#39;s record. Store the name, height, weight, and sex in the supplied vectors...
Definition: bmi.cpp:79