1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
#include <algorithm>
#include <cctype>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <limits>
#include <string>
#include <exception>
#include <utility>
class MyExcp : public std::exception {
public:
MyExcp(std::string message_arg);
const char* what() const throw() override;
void setMessage(const std::string& value);
protected:
std::string message;
};
MyExcp::MyExcp(std::string message_arg)
: message {message_arg}
{}
const char* MyExcp::what() const throw()
{ return message.c_str(); }
void MyExcp::setMessage(const std::string& value)
{ message = value; }
void openFile(std::ifstream& myfile, const std::string& name);
void openFile(std::ofstream& myfile, const std::string& name);
bool checkIfDigits(const std::string& check);
void addNumbers(double temp_num, double& sum, double& mycount);
std::string get_string_component(char component, tm* AStruct);
void waitForEnter();
int main(int argc, char* argv[])
{
if(argc < 3) {
std::cout << "\nUsage: app_name data_file_name output_file_name\n";
exit(EXIT_FAILURE); // this is not a program error: I'd use "return".
}
// No further controls needed: additional parameters will be ignored
std::ifstream infile;
bool fileopened {false};
std::string name {argv[1]};
do {
try {
openFile(infile, name);
fileopened = true;
} catch (MyExcp& error) {
std::cout << error.what();
std::getline(std::cin, name);
fileopened = false; // redundant
}
} while(!fileopened);
//read each line of input file
std::string temp_str;
double sum = 0;
double mycount = 0; // count --> there're functions count() in std namespace
while (!getline(infile, temp_str)) {
std::string num_str = temp_str.substr(40,10);
num_str.erase(num_str.find_last_not_of(" \n\r\t")+1);
if (checkIfDigits(num_str)) {
double tmpdouble = std::stod(num_str);
addNumbers(tmpdouble, sum, mycount);
} else {
std::cout << "Number contains non digits: " << num_str
<< "\n Current Line will be Skipped!\n\n";
}
}
infile.close();
std::time_t now = std::time(0);
std::tm* astruct = std::localtime(&now);
std::mktime(astruct);
double average = sum/mycount;
//Write data to output file
std::ofstream outfile;
fileopened = false;
name = argv[2];
do {
try {
openFile(outfile, name);
fileopened = true;
} catch (MyExcp& error) {
error.what();
std::getline(std::cin, name);
fileopened = false; // redundant
}
} while(!fileopened);
outfile << "Date: " << get_string_component('c', astruct)
<< "\nTotal Payment: $" << sum
<< "\nAverage payment: $" << std::fixed << std::setprecision(2)
<< average << std::endl;
//Display output file data
outfile.close();
infile.open(name); // name should be still equal to argv[2]
std::string out_str;
while (!std::getline(infile, out_str)) {
std::cout << out_str << "\n";
}
void waitForEnter();
return 0;
}
void openFile(std::ifstream& myfile, const std::string& name)
{
myfile.open(name);
if (!myfile.is_open()) {
MyExcp myexcp("Cannot open data file " + name +
". Please input the correct data file name: ");
throw myexcp;
}
}
void openFile(std::ofstream& myfile, const std::string& name)
{
myfile.open(name);
if (!myfile.is_open()) {
MyExcp myexcp("Cannot open data file " + name +
". Please input the correct data file name: ");
throw myexcp;
}
}
/* ==========================================================================
* Question: should this function manage negative numbers too?
* In that case, the first character should also be checked for minus sign.
* ========================================================================== */
// Check if any non-digit characters in std::string
bool checkIfDigits(const std::string& check)
{
for(unsigned int k = 0; k < check.length(); ++k) {
if(not isdigit(check[k])) {
return false;
}
}
return true;
}
// Calculate total of payments
void addNumbers(double temp_num, double& sum, double& mycount)
{
sum += temp_num;
++mycount;
}
std::string get_string_component(char component, tm* astruct)
{
char format[3];
format[0] = '%';
format[1] = component;
format[2] = '\0';
char ans [80];
strftime(ans, 80, format, astruct);
std::string strans(ans);
return strans;
}
void waitForEnter()
{
std::cout << "\nPress ENTER to continue...\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
|