#include #include #include #include using namespace std; int DatesFromString(string, int &, int &, int&); int DayOfYear(int, int, int); int DaysInMonth(int, int); int DaysBetweenDates(string, string); float InterpolateWeight(int, char); string PupWeightStatus(string, string, int, char); //////////////////////////////// // global constants for things that won't change // like puppy average weights. int male_week_4 = 2000; int male_week_5 = 2750; int male_week_6 = 3750; int male_week_7 = 5100; int male_week_8 = 6500; int male_week_9 = 7700; int female_week_4 = 1800; int female_week_5 = 2500; int female_week_6 = 3450; int female_week_7 = 4550; int female_week_8 = 5750; int female_week_9 = 7200; int main(){ // Variables for the input and output files ifstream inputfile; ofstream outputfile; string inputfile_name, outputfile_name; // Variables for holding data read from files string puppy_name, puppy_bday, puppy_sex, puppy_color, puppy_dad, puppy_mom, date1, date2, date3, date4; int weight1, weight2, weight3, weight4; char pup_sex; // Tell what the program does cout << "This program parses puppy data files and labels the" << endl << "puppies' weight as underweight, average, or overweight" << endl << endl; // Open the files and make sure they worked ok cout << "Please enter the input file name: "; getline (cin, inputfile_name); inputfile.open(inputfile_name.c_str()); if (!inputfile){ cerr << "Could not open " << inputfile_name << endl; exit (1); } cout << "Please enter the output file name: "; getline (cin, outputfile_name); outputfile.open(outputfile_name.c_str()); if (!outputfile){ cerr << "Could not open " << outputfile_name << endl; exit (1); } // Since the files are short, and a fixed format, // just read the input file all at once getline (inputfile, puppy_name); getline (inputfile, puppy_bday); getline (inputfile, puppy_sex); getline (inputfile, puppy_color); getline (inputfile, puppy_dad); getline (inputfile, puppy_mom); inputfile >> date1 >> weight1; inputfile >> date2 >> weight2; inputfile >> date3 >> weight3; inputfile >> date4 >> weight4; // Mark the sex of the pup by grabbing the first letter of the sex // from the string pup_sex = puppy_sex.at(0); // now output what we can right off, // which is everything, since fuctions are so nice! outputfile << puppy_name << endl; outputfile << puppy_bday << endl; outputfile << puppy_sex << endl; outputfile << puppy_color << endl; outputfile << puppy_dad << endl; outputfile << puppy_mom << endl; outputfile << date1 << " " << weight1 << " " << PupWeightStatus(puppy_bday,date1, weight1, pup_sex) << endl; outputfile << date2 << " " << weight2 << " " << PupWeightStatus(puppy_bday,date2, weight2, pup_sex) << endl; outputfile << date3 << " " << weight3 << " " << PupWeightStatus(puppy_bday,date3, weight3, pup_sex) << endl; outputfile << date4 << " " << weight4 << " " << PupWeightStatus(puppy_bday,date4, weight4, pup_sex) << endl; return 0; } ///// DatesFromString(string date_string, int & day, int & month, int & year) // This function takes a string in the format: mm/dd/yyyy and extracts the // month, day, and year as integers. These are set in the reference parameters. // returns 0 if it thinks it worked OK, or -1 otherwise. int DatesFromString(string date_string, int & day, int & month, int & year){ int first_slash = 0, second_slash = 0; string day_string, month_string, year_string; //traverse the string to find the slashes for (int i =0; i < date_string.length(); i++){ // is this a slash? if (date_string.at(i) == '/'){ // is it the first? if (first_slash == 0) { first_slash = i; } else // is it the second slash? if (second_slash == 0) { second_slash = i; } } } // end for loop ////////////// // check to make sure we found two slashes // if we didn't, then return an error code if ( ! (first_slash && second_slash && (first_slash != second_slash))){ // one or both of the slashes was in the same spot, or they were equal return (-1); } /////////////////////////////////////////// // Now we should know where the slashes are. // We can cut the string into three substrings, // each with a piece of the date in it. month_string = date_string.substr(0, first_slash); day_string = date_string.substr(first_slash + 1, second_slash - first_slash - 1); year_string = date_string.substr(second_slash + 1, date_string.length() - second_slash); day = atoi(day_string.c_str()); month = atoi(month_string.c_str()); year = atoi(year_string.c_str()); return 0; } //// End DatesFromString ///// DayOfYear(int day, int month, int year) // This function finds the ordinal day of the year, from 1 to 366. // int DayOfYear(int day, int month, int year){ int total_days = 0; // add up all the days from the months before the one entered for (int i = 1; i < month; i++){ total_days += DaysInMonth(i,year); } // Now add the days in this month total_days += day; return total_days; } //// End DayOfYear ///// int DaysInMonth(int month, int year) // This function returns the number of days in a particular month // int DaysInMonth(int month, int year){ switch (month){ case 1: //January return 31; case 2: // February if (year % 4 == 0) return 29; else return 28; case 3: // March return 31; case 4: // April return 30; case 5: // May return 31; case 6: // June return 30; case 7: // July return 31; case 8: // August return 31; case 9: // September return 30; case 10: // October return 31; case 11: // November return 30; case 12: // December return 31; } } //// end DaysInMonth // int DaysBetweenDates (string first, string second) // This function computes the number of days between two dates, given // dates of the format MM/DD/YYYY. // Assumes that the first date is lower than the second date int DaysBetweenDates (string first, string second){ int first_month, first_day, first_year, second_month, second_day, second_year, first_ordinal_day, second_ordinal_day, days_to_end; // convert the strings to numerical dates DatesFromString(first, first_day, first_month, first_year); DatesFromString(second, second_day, second_month, second_year); // find the ordinal day for each date first_ordinal_day = DayOfYear(first_day, first_month, first_year); second_ordinal_day = DayOfYear(second_day, second_month, second_year); // Now compute the days between // If the year is the same, just subtract the ordinal days if (first_year == second_year) return (second_ordinal_day - first_ordinal_day); else { // Different years, so things get a little more complicated // We know that they will always be adjacent years, // so just find out how long to the end of year1 and add that to // the days of year 2. if (first_year % 4 == 0){ // leap year days_to_end = 366 - first_ordinal_day; return (days_to_end + second_ordinal_day); } else { days_to_end = 365 - first_ordinal_day; return (days_to_end + second_ordinal_day); } } } /// end days between dates float InterpolateWeight(int AgeInDays, char Sex){ int AgeInWeeks, extra_days; float weight_per_day; // Figure out which week the puppy is in // Notice this is int division, so it rounds down, so we always // get the bottom of the range AgeInWeeks = AgeInDays/7; cerr << "Pup is: " << AgeInWeeks << " weeks and "; // For each case: // Figure out how many days older than the earlier week the puppy is // Estimate how much weight the puppy shoud gain each day // Compute how much the puppy should weigh by adding // (gain/day * days) to the base weight for the week. switch(Sex){ case 'M': // Male puppies case 'm': switch (AgeInWeeks){ case 4: extra_days = (AgeInDays - (4*7)); cerr << extra_days << " days old" << endl; weight_per_day = (male_week_5 - male_week_4)/7; return (male_week_4 + (extra_days * weight_per_day)); break; case 5: extra_days = (AgeInDays - (5*7)); cerr << extra_days << " days old" << endl; weight_per_day = (male_week_6 - male_week_5)/7; return (male_week_5 + (extra_days * weight_per_day)); break; case 6: extra_days = (AgeInDays - (6*7)); cerr << extra_days << " days old" << endl; weight_per_day = (male_week_7 - male_week_6)/7; return (male_week_6 + (extra_days * weight_per_day)); break; case 7: extra_days = (AgeInDays - (7*7)); cerr << extra_days << " days old" << endl; weight_per_day = (male_week_8 - male_week_7)/7; return (male_week_7 + (extra_days * weight_per_day)); break; case 8: extra_days = (AgeInDays - (8*7)); cerr << extra_days << " days old" << endl; weight_per_day = (male_week_9 - male_week_8)/7; return (male_week_8 + (extra_days * weight_per_day)); break; default: cerr << "Age out of range: " << AgeInDays << " days" < (1.2 * interpolated_weight)) return "Overweight"; else if (weight < (.8 * interpolated_weight)) return "Underweight"; else return "Average"; }// end PupWeightStatus /* This is the main I used for testing. It isn't neat, but you can get an idea of what I did. int main(){ int day,month,year; string input1, input2; cin >> input1 >> input2; DatesFromString(input1,day,month,year); cerr << "Day: " << DayOfYear(day,month,year) << endl; DatesFromString(input2,day,month,year); cerr << "Day: " << DayOfYear(day,month,year) << endl; cerr << DaysBetweenDates(input1,input2) << endl; for (int i = 29; i < 63; i++){ cerr << i << " day male weight: " << InterpolateWeight(i,'M') << endl; } for (int i = 29; i < 63; i++){ cerr << i << " day female weight: " << InterpolateWeight(i,'F') << endl; } return 0; } */