#include #include #include #include #include #include #include std::tuple read_from_file(std::string filename); std::tuple normalize(std::tuple values); std::tuple read_from_file_term(std::string filename); std::tuple normalize_term(std::tuple values); std::tuple normalize_pre(std::tuple values); int read_from_file_errcode(std::string filename, std::tuple &values); int normalize_errcode(std::tuple values, std::tuple &res); int read_error{0}; int norm_error{0}; std::tuple read_from_file_glob(std::string filename); std::tuple normalize_glob(std::tuple values); std::tuple read_from_file_mult(std::string filename); std::tuple normalize_mult(std::tuple values); std::optional> read_from_file_opt(std::string filename); std::optional> normalize_opt(std::tuple values); struct CannotOpenError { std::string filename; }; struct CannotReadError { std::string filename; }; struct DivisionByZeroError { }; std::tuple read_from_file_expt(std::string filename); std::tuple normalize_expt(std::tuple values); int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << "Forneca o nome do arquivo de dados.\n"; return 1; } // Variação 1: Avestruz auto values1 = read_from_file(argv[1]); auto [na1, nb1, nc1] = normalize(values1); std::cout << "Valores normalizados: " << na1 << ", " << nb1 << ", " << nc1 << std::endl; // Versão 2: Terminação abrupta auto values2 = read_from_file_term(argv[1]); auto [na2, nb2, nc2] = normalize_term(values2); std::cout << "Valores normalizados: " << na2 << ", " << nb2 << ", " << nc2 << std::endl; // Versão 2: Terminação abrupta auto values3 = read_from_file_term(argv[1]); auto [ia, ib, ic] = values3; if (ia == 0 || ib == 0 || ic == 0) { std::cerr << "Os valores no arquivo sao invalidos\n."; return 4; } auto [na3, nb3, nc3] = normalize_pre(values2); std::cout << "Valores normalizados: " << na3 << ", " << nb3 << ", " << nc3 << std::endl; // Versão 4: Código de erro std::tuple values4; int err_read = read_from_file_errcode(argv[1], values4); if (err_read != 0) { std::cerr << "Erro ao ler arquivo.\n"; return err_read; } std::tuple norm; auto err_norm = normalize_errcode(values4, norm); if (err_norm != 0) { std::cerr << "Dados invalidos no arquivo.\n"; return err_norm; } std::cout << "Valores normalizados: " << std::get<0>(norm) << ", " << std::get<1>(norm) << ", " << std::get<2>(norm) << std::endl; // Versão 5: Código de erro em variável global. auto values5 = read_from_file_glob(argv[1]); if (read_error != 0) { std::cerr << "Erro ao ler arquivo.\n"; return read_error; } auto [na5, nb5, nc5] = normalize_glob(values5); if (norm_error != 0) { std::cerr << "Valores invalidos no arquivo.\n"; return norm_error; } std::cout << "Valores normalizados: " << na5 << ", " << nb5 << ", " << nc5 << std::endl; // Versão 6: Código de erro numa tupla auto [ia6, ib6, ic6, err_read6] = read_from_file_mult(argv[1]); if (err_read6 != 0) { std::cerr << "Erro ao ler arquivo.\n"; return err_read6; } auto [na6, nb6, nc6, err_norm6] = normalize_mult(std::make_tuple(ia6, ib6, ic6)); if (err_norm6 != 0) { std::cerr << "Valores invalidos no arquivo.\n"; return err_norm6; } std::cout << "Valores normalizados: " << na6 << ", " << nb6 << ", " << nc6 << std::endl; // Versão 7: Retorno com std::optional auto opt_values = read_from_file_opt(argv[1]); if (!opt_values) { std::cerr << "Erro ao ler arquivo.\n"; return 3; } auto opt_norm = normalize_opt(*opt_values); if (!opt_norm) { std::cerr << "Valores invalidos no arquivo.\n"; return 4; } auto [na7, nb7, nc7] = *opt_norm; std::cout << "Valores normalizados: " << na7 << ", " << nb7 << ", " << nc7 << std::endl; // Variação 8: Exceções não tratadas. auto values8 = read_from_file_expt(argv[1]); auto [na8, nb8, nc8] = normalize_expt(values8); std::cout << "Valores normalizados: " << na8 << ", " << nb8 << ", " << nc8 << std::endl; // Variação 9: Exceções tratadas. try { auto values9 = read_from_file_expt(argv[1]); auto [na9, nb9, nc9] = normalize_expt(values9); std::cout << "Valores normalizados: " << na9 << ", " << nb9 << ", " << nc9 << std::endl; } catch (CannotOpenError e) { std::cerr << "Nao consegue abrir arquivo " << e.filename << std::endl; return 1; } catch (CannotReadError e) { std::cerr << "Nao consegue ler do arquivo " << e.filename << std::endl; return 2; } catch (DivisionByZeroError e) { std::cerr << "Valores invalidos no arquivo.\n"; return 3; } return 0; } std::tuple read_from_file(std::string filename) { std::ifstream file(filename); int a, b, c; file >> a >> b >> c; return {a, b, c}; } std::tuple normalize(std::tuple values) { auto [a, b, c] = values; double m = a; if (b < a && c < a) { m = std::max(b, c); } else if (a < c && a < b) { m = std::min(b, c); } return {a/m, b/m, c/m}; } std::tuple read_from_file_term(std::string filename) { std::ifstream file(filename); if (!file.good()) { std::cerr << "Impossivel acessar arquivo.\n"; std::exit(2); } int a, b, c; file >> a >> b >> c; if (file.fail()) { std::cerr << "Erro lendo os dados do arquivo.\n"; std::exit(3); } return {a, b, c}; } std::tuple normalize_term(std::tuple values) { auto [a, b, c] = values; double m = a; if (b < a && c < a) { m = std::max(b, c); } else if (a < c && a < b) { m = std::min(b, c); } if (m == 0) { std::cerr << "Erro: Divisao por zero.\n"; std::exit(4); } return {a/m, b/m, c/m}; } // Pré-condição: values todos diferentes de zero. std::tuple normalize_pre(std::tuple values) { auto [a, b, c] = values; double m = a; if (b < a && c < a) { m = std::max(b, c); } else if (a < c && a < b) { m = std::min(b, c); } return {a/m, b/m, c/m}; } int read_from_file_errcode(std::string filename, std::tuple &values) { std::ifstream file(filename); if (!file.good()) { return 2; } int a, b, c; file >> a >> b >> c; if (file.fail()) { return 3; } values = std::make_tuple(a, b, c); return 0; } int normalize_errcode(std::tuple values, std::tuple &res) { auto [a, b, c] = values; double m = a; if (b < a && c < a) { m = std::max(b, c); } else if (a < c && a < b) { m = std::min(b, c); } if (m == 0) { return 4; } res = std::make_tuple(a/m, b/m, c/m); return 0; } std::tuple read_from_file_glob(std::string filename) { std::ifstream file(filename); if (!file.good()) { read_error = 2; return {0,0,0}; } int a, b, c; file >> a >> b >> c; if (file.fail()) { read_error = 3; return {0,0,0}; } read_error = 0; return {a, b, c}; } std::tuple normalize_glob(std::tuple values) { auto [a, b, c] = values; double m = a; if (b < a && c < a) { m = std::max(b, c); } else if (a < c && a < b) { m = std::min(b, c); } if (m == 0) { norm_error = 4; return {0., 0., 0.}; } norm_error = 0; return {a/m, b/m, c/m}; } std::tuple read_from_file_mult(std::string filename) { std::ifstream file(filename); if (!file.good()) { return {0, 0, 0, 2}; } int a, b, c; file >> a >> b >> c; if (file.fail()) { return {0, 0, 0, 3}; } return {a, b, c, 0}; } std::tuple normalize_mult(std::tuple values) { auto [a, b, c] = values; double m = a; if (b < a && c < a) { m = std::max(b, c); } else if (a < c && a < b) { m = std::min(b, c); } if (m == 0) { return {0., 0., 0., 4}; } return {a/m, b/m, c/m, 0}; } std::optional> read_from_file_opt(std::string filename) { std::ifstream file(filename); if (!file.good()) { return std::nullopt; } int a, b, c; file >> a >> b >> c; if (file.fail()) { return std::nullopt; } return std::make_tuple(a, b, c); } std::optional> normalize_opt(std::tuple values) { auto [a, b, c] = values; double m = a; if (b < a && c < a) { m = std::max(b, c); } else if (a < c && a < b) { m = std::min(b, c); } if (m == 0) { return std::nullopt; } return std::make_tuple(a/m, b/m, c/m); } std::tuple read_from_file_expt(std::string filename) { std::ifstream file(filename); if (!file.good()) { throw CannotOpenError{filename}; } int a, b, c; file >> a >> b >> c; if (file.fail()) { throw CannotReadError{filename}; } return {a, b, c}; } std::tuple normalize_expt(std::tuple values) { auto [a, b, c] = values; double m = a; if (b < a && c < a) { m = std::max(b, c); } else if (a < c && a < b) { m = std::min(b, c); } if (m == 0) { throw DivisionByZeroError(); } return std::make_tuple(a/m, b/m, c/m); }