The purpose of this program is to take an input of an arabic number and return the equivelant roman numeral. it needs to reject input less than 0 and greater than 3999, but also end on an input of ANY NEGATIVE NUMBER. Also needs an input fail catch for entering a letter instead of an integer. (completely clueless on this part?!)
My question is what order should these conditional statement be in so that the program doesnt just return invalid input for a negative number, it ends the program.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
string convert(int digit, string low, string mid, string high);
int main()
{
const int MAX_INPUT = 3999, MIN_INPUT = 0, // These constants hold high and low integer numbers,
ARRAY_SIZE = 4; // and the array size declarator.
string answers[ARRAY_SIZE] = { "", "", "", "" }; //An array of string to hold the output from the convert function.
int accumulator = 0; // Variable to hold number of arabic numbers converted.
int userNum = 0;
do {
cout << "Enter a negative number to end the program.\n";
cout << "Enter an arabic number between 1 and 3999: ";
cin >> userNum;;
if (userNum < 0)
{
cout << "Exiting program:";
break;
while (userNum <= MIN_INPUT || userNum >= MAX_INPUT)
{
cout << "\nInvalid Value. Number must be between 1 and 3999: ";
cin >> userNum;
}
}
int thous = userNum / 1000;
cout << thous;
int hund = userNum % 1000 / 100;
cout << "hundreds:" << hund;
int tens = userNum % 100 / 10;
cout << "tens:" << tens;
int ones = userNum % 10 / 1;
cout << "Ones: " << ones << endl;
answers[0] = convert(thous, "M", "M", "M");
answers[1] = convert(hund, "C", "D", "M");
answers[2] = convert(tens, "X", "L", "C");
answers[3] = convert(ones, "I", "V", "X");
cout << answers[0] << endl << answers[1] << endl << answers[2];
cout << endl << answers[3] << endl;
} while (userNum > 0);
system("PAUSE");
return 0;
}
string convert(int digit, string low, string mid, string high)
{
cout << digit << endl;
if (digit == 1)
{
return low;
}
if (digit == 2)
{
return low + low;
}
if (digit == 3)
{
return low + low + low;
}
if (digit == 4)
{
return low + mid;
}
if (digit == 5)
{
return mid;
}
if (digit == 6)
{
return mid + low;
}
if (digit == 7)
{
return mid + low + low;
}
if (digit == 8)
{
return mid + low + low + low;
}
if (digit == 9)
{
return low + high;
}
if (digit == 0)
{
return "";
}
}
A possible solution with minimal refactoring of your current code:
int main()
{
const int MAX_INPUT = 3999, MIN_INPUT = 0, // These constants hold high and low integer numbers,
ARRAY_SIZE = 4; // and the array size declarator.
string answers[ARRAY_SIZE] = { "", "", "", "" }; //An array of string to hold the output from the convert function.
int accumulator = 0; // Variable to hold number of arabic numbers converted.
int userNum = 0;
do {
cout << "Enter a negative number to end the program.\n";
cout << "Enter an arabic number between 1 and 3999: ";
//cin >> userNum;;
while(!(cin >> userNum) || (userNum < 1 || userNum > 3999)){
if (userNum < 0)
{
cout << "Exiting program:";
return 0;
} else {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "\nInvalid Value. Number must be between 1 and 3999. Try again ";
}
}
int thous = userNum / 1000;
cout << thous;
int hund = userNum % 1000 / 100;
cout << "hundreds:" << hund;
int tens = userNum % 100 / 10;
cout << "tens:" << tens;
int ones = userNum % 10 / 1;
cout << "Ones: " << ones << endl;
answers[0] = convert(thous, "M", "M", "M");
answers[1] = convert(hund, "C", "D", "M");
answers[2] = convert(tens, "X", "L", "C");
answers[3] = convert(ones, "I", "V", "X");
cout << answers[0] << endl << answers[1] << endl << answers[2];
cout << endl << answers[3] << endl;
} while (userNum > 0);
system("PAUSE");
return 0;
}
In sudo code:
while (inputVar >= 0) {
try {
inputVar = stoi(inputVar)
} catch {
print("Input error")
}
if in range(min to max) {
roman = romanEquiv(inputVar)
print(roman)
} else {
print("Invalid entry.")
}
}
Try-catch blocks (for catching exceptions you know your program should handle)
std::stoi a function in the cpp library to try and convert a string to an integer
Hope this helps, let me know how it goes.
I revised the beginning of the main method and the beginning of the while loop.
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
#define MAX_INPUT 3999 // These constants hold high and low integer numbers,
#define MIN_INPUT 1
#define ARRAY_SIZE 4 // and the array size declarator.
string convert(int digit, string low, string mid, string high);
int main()
{
string answers[ARRAY_SIZE] = { "", "", "", "" }; //An array of string to hold the output from the convert function.
int accumulator = 0; // Variable to hold number of arabic numbers converted.
int userNum = 0;
string strUserNum;
do {
cout << "Enter a negative number to end the program.\n";
cout << "Enter an arabic number between 1 and 3999: ";
cin >> strUserNum;
userNum = std::stoi(strUserNum);
if (userNum == 0 || userNum > MAX_INPUT)
{
cout << "\nInvalid Value. Number must be between 1 and 3999: " << endl;
continue;
}
else if (userNum < MIN_INPUT)
{
cout << "Exiting program:";
break;
}
int thous = userNum / 1000;
cout << "thousands: " << thous;
int hund = userNum % 1000 / 100;
cout << " hundreds: " << hund;
int tens = userNum % 100 / 10;
cout << " tens: " << tens;
int ones = userNum % 10 / 1;
cout << " ones: " << ones << endl;
answers[0] = convert(thous, "M", "M", "M");
answers[1] = convert(hund, "C", "D", "M");
answers[2] = convert(tens, "X", "L", "C");
answers[3] = convert(ones, "I", "V", "X");
cout << answers[0] << endl << answers[1] << endl << answers[2];
cout << endl << answers[3] << endl;
} while (userNum >= 0);
system("PAUSE");
return 0;
}
string convert(int digit, string low, string mid, string high)
{
cout << digit << endl;
if (digit == 1)
{
return low;
}
if (digit == 2)
{
return low + low;
}
if (digit == 3)
{
return low + low + low;
}
if (digit == 4)
{
return low + mid;
}
if (digit == 5)
{
return mid;
}
if (digit == 6)
{
return mid + low;
}
if (digit == 7)
{
return mid + low + low;
}
if (digit == 8)
{
return mid + low + low + low;
}
if (digit == 9)
{
return low + high;
}
if (digit == 0)
{
return "";
}
}
But I would like to also provide an alternative implementation of the string conversion ( from http://rosettacode.org/wiki/Roman_numerals/Encode#C.2B.2B ):
std::string to_roman(unsigned int value)
{
struct romandata_t { unsigned int value; char const* numeral; };
const struct romandata_t romandata[] =
{
{1000, "M"}, {900, "CM"},
{500, "D"}, {400, "CD"},
{100, "C"}, { 90, "XC"},
{ 50, "L"}, { 40, "XL"},
{ 10, "X"}, { 9, "IX"},
{ 5, "V"}, { 4, "IV"},
{ 1, "I"},
{ 0, NULL} // end marker
};
std::string result;
for (const romandata_t* current = romandata; current->value > 0; ++current)
{
while (value >= current->value)
{
result += current->numeral;
value -= current->value;
}
}
return result;
}
I would suggest you this C++14 code:
#include <utility>
#include <string>
auto toRoman(unsigned arabic)
{
constexpr auto table = {
std::make_pair(1000u, "M"),
std::make_pair(900u, "CM"),
std::make_pair(500u, "D"),
std::make_pair(400u, "CD"),
std::make_pair(100u, "C"),
std::make_pair(90u, "XC"),
std::make_pair(50u, "L"),
std::make_pair(40u, "XL"),
std::make_pair(10u, "X"),
std::make_pair(9u, "IX"),
std::make_pair(5u, "V"),
std::make_pair(4u, "IV"),
std::make_pair(1u, "I")
};
std::string roman;
for (auto& pair: table)
{
while (pair.first <= arabic)
{
arabic -= pair.first;
roman += pair.second;
}
}
return roman;
}
Related
I have something which outputs all the factors for an integer using a fixed loop.
in this case, int_end_int_ = 4
and middle_x_coefficient = 4
for (int i = 1; i <= int_end_int_; i++)
{
if (int_end_int_ % i == 0) // This gets the factors
{
//here
}
}
i have that inside the if loop that if i * 2 == 4, print a string. So i thought that when i = 2, it will output the string.
//inside if loop
int newi = i * 2;
//i = 2
if (newi == middle_x_coefficient) {
preroot1 = i; //ignore
cout << "prerooted";
preroot2 = i; //ignore
}
It does not output "prerooted", and i have no clue why.
Full Code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Quadratic Equation Solver ( to roots )" << endl;
cout << "Enter quadratic equation, e.x (x^2 + 4x + 4) must be in this form" << endl;
string equation;
cout << ">> ";
getline(cin, equation);
if (equation.length() < 12)
{
cout << "Please enter valid string." << endl;
while (equation.length() < 12)
{
cout << ">> ";
getline(cin, equation);
}
}
char middle_x_coefficient = equation[6]; // getting x^2 + 4(this<-)x + 4
char end_int_ = equation[11]; // getting x^2 + 4x + 4 <-- this
int preroot1 = 0;
int preroot2 = 0;
int int_end_int_ = static_cast<int>(end_int_); //convert char to int using static cast for like no reason
//nvm <- https://stackoverflow.com/questions/103512/why-use-static-castintx-instead-of-intx this says it is better bc compiler bad or smthn
int_end_int_ -= 48; //This converts the ascii value (52 for 4) to 4 (-48)
int pasti = 0;
for (int i = 1; i <= int_end_int_; i++)
{
if (int_end_int_ % i == 0)
{
cout << i << "this<- i" << endl;
cout << middle_x_coefficient << "this<- x" << endl;
int newi = i * 2;
//i = 2
if (newi == middle_x_coefficient) {
preroot1 = i;
cout << "prerooted";
preroot2 = i;
}
else if (i + pasti == middle_x_coefficient) {
preroot1 = i;
preroot2 = pasti;
}
pasti = i;
}
}
cout << preroot1 << " " << preroot2 << endl;
return 0;
}
You converted the character end_int_ to the integer int_end_int_, but you didn't convert the character middle_x_coefficient to an integer. Convert and use converted integer just as you did for end_int_.
Instead of using magic number 48, using character literal '0' is better.
I have a large number whereby i want to find the number of occurances of a specified digit. I wonder is using a counter will work. My code as follows:
#include <iostream>
using namespace std;
int main( )
{
int number;
int n1;
int n2;
int n3;
int n4;
int n5;
int n6;
int n7;
int n8;
int n9;
int n10;
int digit;
int digitCounter = 0;
cout << "Please enter a number between 100 to 2000000000." << endl;
cin >> number;
cout << "Please enter a digit that you want to find the number of occurances." << endl;
cin >> digit;
if (number > 0)
{
n1 = number % 10;
n2 = (number/10) % 10;
n3 = (number/100) % 10;
n4 = (number/1000) % 10;
n5 = (number/10000) % 10;
n6 = (number/100000) % 10;
n7 = (number/1000000) % 10;
n8 = (number/10000000) % 10;
n9 = (number/100000000) % 10;
n10 = (number/100000000) % 10;
if (n1 == digit)
{ digitCounter++;}
else if (n2 == digit)
{ digitCounter++;}
else if (n3 == digit)
{ digitCounter++;}
else if (n4 == digit)
{ digitCounter++;}
else if (n5 == digit)
{ digitCounter++;}
else if (n6 == digit)
{ digitCounter++;}
else if (n7 == digit)
{ digitCounter++;}
else if (n8 == digit)
{ digitCounter++;}
else if (n9 == digit)
{ digitCounter++;}
else if (n10 == digit)
{ digitCounter++;}
cout<< "The total number of occurances of " << digit << " in " << number <<" is "<<digitCounter<< endl;
}
else
cout<< "You have entered an invalid number."<<endl;
system("pause");
return 0;
}
However the counter is not working. Can someone advise what wet wrong?
Any help is really appreciated, thanks.
You can cast your number into a string after that you search the digit in the string it's simpler.
Or you can read a character string (number) and a character (digit) and then you do like that :
char number[20], digit;
int count = 0, i;
printf("\nEnter a string : ");
scanf("%s", &number);
printf("\nEnter the character to be searched : ");
scanf("%c", &digit);
for (i = 0; number[i] != '\0'; i++) {
if (number[i] == digit)
count++;
}
if (count == 0)
printf("\nCharacter '%c'is not present", digit);
else
printf("\nOccurence of character '%c' : %d", digit, count);`
Your Else If's need to be If's. As it stands now you only go through one decision statement. As soon as it finds a match you're out.
#include <iostream>
using namespace std;
int main()
{
int number;
int n1;
int n2;
int n3;
int n4;
int n5;
int n6;
int n7;
int n8;
int n9;
int n10;
int digit;
int digitCounter = 0;
cout << "Please enter a number between 100 to 2000000000." << endl;
cin >> number;
cout << "Please enter a digit that you want to find the number of occurances." << endl;
cin >> digit;
if (number > 0)
{
n1 = number % 10;
n2 = (number / 10) % 10;
n3 = (number / 100) % 10;
n4 = (number / 1000) % 10;
n5 = (number / 10000) % 10;
n6 = (number / 100000) % 10;
n7 = (number / 1000000) % 10;
n8 = (number / 10000000) % 10;
n9 = (number / 100000000) % 10;
n10 = (number / 100000000) % 10;
if (n1 == digit)
{
digitCounter++;
}
if (n2 == digit)
{
digitCounter++;
}
if (n3 == digit)
{
digitCounter++;
}
if (n4 == digit)
{
digitCounter++;
}
if (n5 == digit)
{
digitCounter++;
}
if (n6 == digit)
{
digitCounter++;
}
if (n7 == digit)
{
digitCounter++;
}
if (n8 == digit)
{
digitCounter++;
}
if (n9 == digit)
{
digitCounter++;
}
if (n10 == digit)
{
digitCounter++;
}
cout << "The total number of occurances of " << digit << " in " << number << " is " << digitCounter << endl;
}
else
cout << "You have entered an invalid number." << endl;
system("pause");
return 0;
}
try this
#include <iostream>
int main(int argc, char **argv) {
unsigned long long large(0);
int digitToFind(0);
std::cout << "enter a large number [100 to 2000000000]" << std::endl;
std::cin >> large;
if (large < 100 || large > 2000000000) {
std::cout << "invalid input." << std::endl;
return -1;
}
std::cout << "enter the digit to find" << std::endl;
std::cin >> digitToFind;
if (digitToFind < 0 || digitToFind > 9) {
std::cout << "invalid input." << std::endl;
return -1;
}
std::size_t counts[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
while (large > 0) {
int rem = large % 10;
counts[rem]++;
large /= 10;
}
std::cout << "number of occurrances of " << digitToFind << " is "
<< counts[digitToFind] << std::endl;
std::cout << "press enter to continue" << std::endl;
std::cin.get();
return 0;
}
Some of the sample codes contain another flaw: if the number is small then we get more zeroes than necessary...we cannot assume that the number is necessarily big.
This works for each number, in Python only because I'm more used to Python at the moment, it is straightforward to convert it to C:
N = 1230533007
digitToFind = 3
digitCount = 0
while N > 0:
d = N % 10
if d == digitToFind:
digitCount += 1
N //= 10
print digitCount
I have been working on a project for several hours now, and this is the last error that I cannot manage to figure out how to fix. The class is:
class WholeNumber
{
private:
int number;
public:
WholeNumber();
WholeNumber(int n);
void display(); //Display the English description
WholeNumber operator+(const WholeNumber &n1);
WholeNumber operator-(const WholeNumber &n1);
WholeNumber operator++();
WholeNumber operator--();
friend ostream& operator<<(ostream& output, const WholeNumber& N);
int getNum();
};
and I am trying to get the operator << to show a number in its digit form and English form, like for an example number 452 it should show:
452, four hundred fifty two
What I managed to compile was:
ostream& operator<<(ostream& output, const WholeNumber& N)
{
return output << N.number;
}
Which would return the number in digit form ie 452. I tried using
ostream& operator<<(ostream& output, const WholeNumber& N)
{
return output << N.number << display(); //doesn't work
return output << N.number << N.display(); //also doesn't work
}
The display() function is pretty long but it begins:
void WholeNumber::display()
I can copy the whole code for display() but I don't know if that would help or not. Any help would be appreciated.
Full Code:
#include<iostream>
#include<string>
#include<sstream>
#include<cstring>
using namespace std;
class WholeNumber
{
private:
int number;
public:
WholeNumber();
WholeNumber(int n);
void display(); //Display the English description
WholeNumber operator+(const WholeNumber &n1);
WholeNumber operator-(const WholeNumber &n1);
WholeNumber operator++();
WholeNumber operator--();
int getNum();
friend ostream& operator<<(ostream& output, const WholeNumber& N);
const static string lessThan20[];
const static string tens[];
const static string hundreds[];
};
WholeNumber::WholeNumber()
{
number = 0;
}
WholeNumber::WholeNumber(int n)
{
if (n > 1000)
number = 1000;
else if (n < -1000)
number = -1000;
else
number = n;
}
const string WholeNumber::lessThan20[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
const string WholeNumber::tens[] = { "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
const string WholeNumber::hundreds[] = { "one hundred", "two hundred", "three hundred", "four hundred", "five hundred", "six hundred", "seven hundred", "eight hundred", "nine hundred" };
int WholeNumber::getNum()
{
return number;
}
WholeNumber WholeNumber::operator+(const WholeNumber &n1)
{
WholeNumber N = number + n1.number;
if(N.number > 1000)
N = 1000;
return N;
}
WholeNumber WholeNumber::operator-(const WholeNumber &n1)
{
WholeNumber N = number - n1.number;
if(N.number < -1000)
N = -1000;
return N;
}
WholeNumber WholeNumber::operator++()
{
++number;
return *this;
}
WholeNumber WholeNumber::operator--()
{
--number;
return *this;
}
void WholeNumber::display()
{
int num = number;
int digit1;
int digit2;
int digit3;
if (num == -1000)
cout << "negative one thousand" << endl;
else if (num >= -999 && num <= -100)
{
num = num * -1;
digit1 = num / 100;
if ((num % 100) > 19)
digit2 = num % 100 / 10;
else
digit2 = num % 100;
digit3 = (num % 100) % 10;
if ((num % 100) < 20 && digit3 != 0)
cout << "negative " << hundreds[digit1 - 1] << " " << lessThan20[digit2] << endl;
else if (digit2 == 0 && digit3 == 0)
cout << "negative " << hundreds[digit1 - 1] << endl;
else
cout << "negative " << hundreds[digit1 - 1] << " " << tens[digit2 - 2] << " " << lessThan20[digit3] << endl;
}
else if (num >= -99 && num < -19)
{
num = num * -1;
digit1 = num / 10;
digit2 = num % 10;
if ((num % 10) > -20 && digit2 != 0)
cout << "negative " << tens[digit1 - 2] << " " << lessThan20[digit2] << endl;
else if (digit2 == 0)
cout << "negative " << tens[digit1 - 2] << endl;
else
cout << "negative " << tens[digit1 - 2] << " " << lessThan20[digit2] << endl;
}
else if (num >= -19 && num <= -1)
{
num = num * -1;
cout << "negative " << lessThan20[num] << endl;
}
else if (num == 0)
cout << "zero" << endl;
else if (num >= 1 && num <= 19)
cout << lessThan20[num] << endl;
else if (num > 19 && num <= 99)
{
digit1 = num / 10;
digit2 = num % 10;
if ((num % 10) < 20 && digit2 != 0)
cout << tens[digit1 - 2] << " " << lessThan20[digit2] << endl;
else if (digit2 == 0)
cout << tens[digit1 - 2] << endl;
else
cout << tens[digit1 - 2] << " " << lessThan20[digit2] << endl;
}
else if (num >= 100 && num <= 999)
{
digit1 = num / 100;
if ((num % 100) > 19)
digit2 = num % 100 / 10;
else
digit2 = num % 100;
digit3 = (num % 100) % 10;
if ((num % 100) < 20 && digit3 != 0)
cout << hundreds[digit1 - 1] << " " << lessThan20[digit2] << endl;
else if (digit2 == 0 && digit3 == 0)
cout << hundreds[digit1 - 1] << endl;
else
cout << hundreds[digit1 - 1] << " " << tens[digit2 - 2] << " " << lessThan20[digit3] << endl;
}
else
cout << "one thousand" << endl;
}
ostream& operator<<(ostream& output, const WholeNumber& N)
{
output << N.number << N.display();
return output;
}
int main()
{
WholeNumber n1(777);
WholeNumber n2(345);
n1.display();
++n1;
--n2;
cout << n1 - n2 << endl;
return 0;
}
Program is supposed to write to user input and the roman numeral equivalent to the file "output.txt" in this form 1984: MCMLXXXIV which is the original user input and the results of the convert function. In my text file I an getting only "0:" on the txt document that is successfully created by the file. code is below.
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;
string convert(int digit, string low, string mid, string high);
void saveToFile(int &, string[], const int &);
int main()
{
const int MAX_INPUT = 3999, MIN_INPUT = 1, // These constants hold high and low integer numbers,
ARRAY_SIZE = 4; // and the array size declarator.
string answers[ARRAY_SIZE] = { "", "", "", "" }; //An array of string to hold the output from the convert function.
int accumulator = 0; // Variable to hold number of arabic numbers converted.
int userNum = 0; // Variable to hold user input.
saveToFile(userNum, answers, ARRAY_SIZE);
do { //Main loop - ensures repeated execution until negative entered.
cout << "Enter a negative number to end the program.\n";
cout << "Enter an arabic number between 1 and 3999: ";
accumulator++;
while (!(cin >> userNum) || (userNum < MIN_INPUT || userNum > MAX_INPUT)){ //input validation - only proceed with
if (userNum < 0) //valid, in-range input.
{
cout << "Program Ending due to user request.";
cout << endl << "Arabic numbers converted: " << accumulator - 1 << endl; //Counter
cout << "Thank you for using the program. Have a nice day!" << endl;
system("PAUSE");
exit(EXIT_SUCCESS); //Termintaion with message and exit function
}
else {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n'); //handling of non-integer input.
cout << "Invalid Value. Number must be between 1 and 3999: ";
}
}
// Digit Extraction - turns userNum into four seperate values
int thous = userNum / 1000; //thousands place value
int hund = userNum % 1000 / 100; //hundreds place value
int tens = userNum % 100 / 10; //tens place value
int ones = userNum % 10 / 1; //ones place value
// filling answers ARRAY OF STRINGS with results from convert function.
answers[0] = convert(thous, "M", "M", "M");
answers[1] = convert(hund, "C", "D", "M");
answers[2] = convert(tens, "X", "L", "C");
answers[3] = convert(ones, "I", "V", "X");
// Printing out equivelent roman numeral on one line.
cout << "\nRoman numeral for " << userNum << " is: ";
cout << answers[0] << answers[1] << answers[2];
cout << answers[3] << endl;
} while (userNum > 0); //Loop to allow multiple numbers per run.
system("PAUSE");
return 0;
}
// Convert function - returns a string for roman numerals broken up by digits, Accepts as arguments
// the extracted digits and three string values known as low, med, and high.
string convert(int digit, string low, string mid, string high)
{
if (digit == 1)
{
return low;
}
if (digit == 2)
{
return low + low;
}
if (digit == 3)
{
return low + low + low;
}
if (digit == 4)
{
return low + mid;
}
if (digit == 5)
{
return mid;
}
if (digit == 6)
{
return mid + low;
}
if (digit == 7)
{
return mid + low + low;
}
if (digit == 8)
{
return mid + low + low + low;
}
if (digit == 9)
{
return low + high;
}
if (digit == 0)
{
return "";
}
}
void saveToFile(int &userNum, string answers[], const int &ARRAY_SIZE)
{
char writeToFile;
cout << "Do you want to write output to a file? Y/N ";
cin >> writeToFile;
if (writeToFile == 89 || writeToFile == 121)
{
ofstream outputFile;
outputFile.open("output.txt");
if (outputFile)
{
outputFile << userNum << ":" << answers[0] + answers[1] + answers[2] + answers[3];
outputFile.close();
}
else
{
cout << "Error opening the file.\n";
exit(EXIT_FAILURE);
}
}
else
return;
}
You call saveToFile BEFORE the loop.
You should call it at the end of your loop:
// Printing out equivalent roman numeral on one line.
cout << "\nRoman numeral for " << userNum << " is: ";
cout << answers[0] << answers[1] << answers[2];
cout << answers[3] << endl;
saveToFile(userNum, answers, ARRAY_SIZE);
} while (userNum > 0);
We're only interested in the #'s in the range [0,100]. There may be number outside the range [0, 100], but they aren't part of our calculation (i.e numbers below 0 and above 100 can be inputted but will be ignored in the calculations and counters).
Assume we assign ABCDF as
[85,100]: A
[75,85): B
[65,75): C
[55,65): D
[0,55): F
For each of the five letter grades, output the number of scores with that grade, and also, if the number of scores wasn't 0, output the average score with that grade. Also, if the number of valid scores (in [0, 100]) wasn't 0, output the average of all the scores
I am having trouble with this looping question. When I input multiple scores, it loops them incorrectly and outputs two sets of grades for each input rather than the example answer shown above. Also I am not sure if my break is placed correctly to exit the program when a word is inputted. Any help will be greatly appreciated!
Here is my code:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <string>
using namespace std;
int main(){
double scores;
unsigned countA = 0;
unsigned countB = 0;
unsigned countC = 0;
unsigned countD = 0;
unsigned countF = 0;
char grade;
double sumA = 0, sumB = 0, sumC = 0, sumD = 0, sumF = 0;
cout << "Enter scores: ";
for (scores; cin >> scores;){
if (scores > 85 && scores <= 100){
grade = 'A';
countA++;
sumA += scores;
}
else if (scores > 75){
grade = 'B';
countB++;
sumB += scores;
}
else if (scores > 65){
grade = 'C';
countC++;
sumC += scores;
}
else if (scores > 55){
grade = 'D';
countD++;
sumD += scores;
}
else{
grade = 'F';
countF++;
sumF += scores;
}
if (!cin){
break;
}
if (countA == 0){
cout << "# A's: 0 " << endl;
}
else {
cout << "# A's: " << countA << " Average = " << sumA/countA << endl;
} if (countB == 0){
cout << "# B's : 0 " << endl;
}
else{
cout << "# B's: " << countB << " Average = " << sumB /countB << endl;
} if (countC == 0){
cout << "# C's: 0 " << endl;
}
else{
cout << "# C's: " << countC << " Average = " << sumC /countC << endl;
} if (countD == 0){
cout << "# D's: 0 " << endl;
}
else {
cout << "# D's: " << countD << " Average = " << sumD /countD << endl;
} if (countF == 0){
cout << "# F's: 0 " << endl;
}
else {
cout << "# F's: " << countF << " Average = " << sumF /countF << endl;
}
}
TL;DR version: Closing brace on the for loop was missing. Loop never ended and caused OP's output code to also loop.
Long version:
Here is working code. The stuff I changed is marked with comments.
#include <iostream> //removed a bunch of unused includes.
using std::cin; // including all of namespace::std is overkill and often
using std::cout; // leads to hard-to-solve bugs. Only use what you need
using std::endl;
int main()
{
double scores;
unsigned countA = 0;
unsigned countB = 0;
unsigned countC = 0;
unsigned countD = 0;
unsigned countF = 0;
char grade;
double sumA = 0, sumB = 0, sumC = 0, sumD = 0, sumF = 0;
cout << "Enter scores: ";
// for (scores; cin >> scores;){
while (cin >> scores) // cleaner
{
if (scores > 85 && scores <= 100)
{
grade = 'A';
countA++;
sumA += scores;
}
else if (scores > 75)
{
grade = 'B';
countB++;
sumB += scores;
}
else if (scores > 65)
{
grade = 'C';
countC++;
sumC += scores;
}
else if (scores > 55)
{
grade = 'D';
countD++;
sumD += scores;
}
else
{
grade = 'F';
countF++;
sumF += scores;
}
// this test is made redundant by the loop condition
// if (!cin)
// {
// break;
// }
} // this was missing. The loop kept going and included all of
// the following code in the loop.
if (countA == 0)
{
cout << "# A's: 0 " << endl;
}
else
{
cout << "# A's: " << countA << " Average = " << sumA / countA << endl;
}
if (countB == 0)
{
cout << "# B's : 0 " << endl;
}
else
{
cout << "# B's: " << countB << " Average = " << sumB / countB << endl;
}
if (countC == 0)
{
cout << "# C's: 0 " << endl;
}
else
{
cout << "# C's: " << countC << " Average = " << sumC / countC << endl;
}
if (countD == 0)
{
cout << "# D's: 0 " << endl;
}
else
{
cout << "# D's: " << countD << " Average = " << sumD / countD << endl;
}
if (countF == 0)
{
cout << "# F's: 0 " << endl;
}
else
{
cout << "# F's: " << countF << " Average = " << sumF / countF << endl;
}
}
Your question is a bit confusing, I assume your main issue is the output part. Currently your code produces this.
As you see we get intermediate output, after every score entered. To change that the loop needs to be split into two loops: One for input, and one for output that runs after the first:
while (/* we get scores */) {
// update the counters and sums
}
for (/* every score */) {
// print count and average
}
To generate the output in a loop you need to store your data in some "loopable" way. Currently you have multiple local variables. Changing that to an array (indexed by the respective grade) allows us to loop over the data:
unsigned counter[5];
double sum [5];
// A -> 0, B -> 1, ..., F -> 4
for (std::size_t it = 0; it < 5; ++it) {
// use sum[it] and counter[it]
}
But raw arrays (as raw pointers) are evil - only use them when absolutely necessary - we use std::array from the standard library. And to ease iteration and improve logical encapsulation it's good to keep sum and count of each grade together:
struct grade_info {
unsigned count = 0;
double sum = 0;
};
// ... later in the main function
std::array<grade_info, 5> grades;
// input
for (auto const & grade : grades) { // C++11 shorthand to iterate over a collection
// use grade.count and grade.sum
}
Concerning your input:
for (scores; cin >> scores;){
This does the right thing, but is a bit strange. Since scores will only be used inside that loop instead of declaring it as local variable of main we only declare it inside the loop:
for (double score; // only a single score is in that variable at any time
cin >> score; // ends the loop on eof or failure to convert to double (when text got entered)
// no step instructions, the above check does that already
) {
Now there's also no need to test cin inside the loop. The operator>> returns (a reference to) its first argument, which is cin, so the test in the for loop already tests cin, no need for if (! cin) { break; }.
Then you have code like this
grade = 'A';
when you never use the value stored in grade. Just remove that.
Last but not least your input validation isn't working (the 101 in my test case is treated as grade B):
if (scores > 85 && scores <= 100) {
// scores between (85, 100]
}
// scores is either <= 85 OR > 100
else if (scores > 75){
// scores is in (75, 85] OR > 100
}
Ideally you should keep input validation and business logic separated:
if (not input_is_valid(score)) {
continue; // the loop
}
// business logic, assuming valid input
So, the final code could be
#include <iostream>
#include <array>
struct grade_info {
unsigned count = 0;
double sum = 0;
char const name;
grade_info(char n) : name(n) {
}
};
bool input_is_valid(double score) {
return (score >= 0) and (score <= 100);
}
std::size_t score_to_grade_index(double score) {
if (score >= 85) {
return 0;
} else if (score >= 75) {
return 1;
} else if (score >= 65) {
return 2;
} else if (score >= 55) {
return 3;
} else {
return 4;
}
}
int main(int, char**) {
std::array<grade_info, 5> grades {'A', 'B', 'C', 'D', 'F'};
for (double score; std::cin >> score;) {
if (not input_is_valid(score)) {
continue;
}
auto index = score_to_grade_index(score);
++(grades[index].count);
grades[index].sum += score;
}
for (auto const & grade : grades) {
std::cout << "# " << grade.name << ": "
<< grade.count;
if (grade.count > 0) {
std::cout << " avg: " << (grade.sum / grade.count);
}
std::cout << std::endl;
}
return 0;
}
Live here