I'm working in a program that converts from Roman to Decimal. I have to validate 2 things: One that the characters entered are M or D or C or L or X or V or I, in other words valid for processing.
Number two, I have to make sure that bigger characters value go first and if not to print and error message and have the user to try again (this is the part where I am stuck)
For instance, If I wanted to input 9 and I input IX it should display an error message because is not in Additive form. It should be VIIII. How can I code this so it compares characters to know whether bigger letter values are first and so on?
I keep getting incorrect validation.
Is there a way to assign a value to the letters in the string? I'm thinking in comparing them as int values which I know how to and from there validate input format.
void RomanNum::setRomanNumber() //get input and calculate decimal equivalent
{
//I 1, V 5, X 10, L 50, C 100, D 500, M 1000
int value = 0;
string input;
char current, next;
enum validationData { M, D, C, L, X, V, I };
bool validationCharacters = true;
//bool validationAdditiveForm = true;
getline(cin, input, '\n');
for (int i = 0; i < input.length(); i++) //calculate each Roman letter at a time
{
current = input[i];
next = current + 1;
if (current >= validationData(next))
{
switch (input[i])
{
case 'M':
value += 1000;
break;
case 'D':
value += 500;
break;
case 'C':
value += 100;
break;
case 'L':
value += 50;
break;
case 'X':
value += 10;
break;
case 'V':
value += 5;
break;
case 'I':
value += 1;
break;
default:
validationCharacters = false;
break;
}
}
else
{
cout << "\nInvalid order. Bigger values go first\n";
}
}
}
I would recommend a std::map<char, int> to hold the mapping between letetrs and values.
With the map, you can then convert the input string (a sequence of characters) to a sequence of values (std::vector<int>). From there on, it's just a single check to see if the vector is sorted, and a single function call to add up all values. (I'll leave finding the right function as homework)
Related
in my code, i don't understand why zero doesn't print i did all possible solutions that I know but it doesn't print zero.
#include <iostream>
using namespace std;
int main(){
int digits;
int numberOne = 0;
int integer;
cout<<"Enter the number: ";
cin>>digits;
while (digits != 0) {
numberOne = (numberOne * 10) + (digits % 10);
digits /= 10;
}
for (integer = numberOne; integer > 0; integer = integer / 10){
switch (integer % 10) {
case 0:
cout<<"Zero\n";
break;
case 1:
cout<<"One\n";
break;
case 2:
cout<<"Two\n";
break;
case 3:
cout<<"Three\n";
break;
case 4:
cout<<"Four\n";
break;
case 5:
cout<<"Five\n";
break;
case 6:
cout<<"Six\n";
break;
case 7:
cout<<"Seven\n";
break;
case 8:
cout<<"Eight\n";
break;
case 9:
cout<<"Nine\n";
break;
}
}
return 0;
}
zero doesn't print how do I fix it?
Expected output is 900 (nine zero zero) but zero doesn't print in my case. help thanks.
Because in this line:
for (integer = numberOne; integer > 0; integer = integer / 10){
the loop continues only if integer>0. Therefore you never see "Zero".
Why doesn't it print zero? Look at your loop
for (integer = numberOne; integer > 0; integer = integer / 10){
If integer equals zero then the loop is never entered. You need to be a bit smarter in your loop. How about counting digits?
int num_digits = 0;
while (digits != 0) {
numberOne = (numberOne * 10) + (digits % 10);
digits /= 10;
++num_digits;
}
Now that you have the number of digits, you can use that in your second loop
for (integer = numberOne; num_digits > 0; integer = integer / 10, --num_digits) {
...
}
You still need to treat zero as a special case, because if the user enters 0 then num_digits will equal zero and you again won't print anything. I'll leave you to figure out how to fix that.
#include <iostream>
using namespace std;
int main(){
int digits;
int arrayLength = 10;
cout<<"Enter the number: ";
cin>>digits;
string reverse_number[arrayLength]; //array to store the string of numbers like "Zero"
int array_counter=0;
while (digits != 0) {
switch (digits % 10) {
case 0:
reverse_number[array_counter++] = "Zero";
break;
case 1:
reverse_number[array_counter++] = "One";
break;
case 2:
reverse_number[array_counter++] = "Two";
break;
case 3:
reverse_number[array_counter++] = "Three";
break;
case 4:
reverse_number[array_counter++] = "Four";
break;
case 5:
reverse_number[array_counter++] = "Five";
break;
case 6:
reverse_number[array_counter++] = "Six";
break;
case 7:
reverse_number[array_counter++] = "Seven";
break;
case 8:
reverse_number[array_counter++] = "Eight";
break;
case 9:
reverse_number[array_counter++] = "Nine";
break;
}
digits /=10;
}
int num_digits = array_counter;
for (int i = 0; i < num_digits; i++) {
cout << reverse_number[--array_counter] <<" ";
}
return 0;
}
The reason why your zeros are not showing while doing for 900 is because when you are reversing 900 to 009, there is no condition mentioned to handle the leading zeros in 009 which are just ignored. For this the best approach would be to store them somewhere else like in a string or an array. You can also just store the number words directly to an array while you are converting, that way you wont lose the leading zeros.
The other answers have already addressed the main problem with your code.This answer focus on the post's title: how to print multiple numbers to words?
First, I would consider using an array of strings instead of a switch.
In order to retrieve a string for a given digit, you would just index that array.(see digits[c - '0'] below)
Also, if you are allowed to convert a number to a string, the code would reduce to walking that string and converting each character to a word.You could read the number directly as a string from the standard input, or use std::to_string on an integer.
Notice also that, when reading a character c from the a string of digits, c - '0' gives you an integer betweeen 0 and 9, which you can use as the array index.
Demo
#include <array>
#include <iostream>
#include <string> // to_string
std::array<std::string, 10> digits{
"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"
};
void digits_to_words(int n) {
for (unsigned char c : std::to_string(n)) {
std::cout << digits[c - '0'] << "\n";
}
}
int main() {
for (int n : { 0, 5, 105, 900 }) {
std::cout << "Number: " << n << "\n";
digits_to_words(n);
std::cout << "\n";
}
}
Here, I've made a function, that takes a character array and a single element array as input.
The input of expression is like "56+78", and then someone suggested this approach of using ascii code and for loops to store the two "numeric" substrings as two numbers, and used the character and switch statement below. But, I don't understand the part of storing these substrings as numbers and the asciicode concept.
void calculate(char ch[], char op[]){
int i;
int num1 = 0, num2 = 0;
for(i=0; ch[i]!='\0';i++)
{
if((int)ch[i]>=48 && (int)ch[i]<=57){
num1 = num1*10+(((int)ch[i])-48);
}
else{
op[0]=ch[i];
break;
}}
i++;
for(; ch[i]!='\0';i++)
{
if((int)ch[i] >= 48 && (int)ch[i] <= 57){
num2 = num2*10+(((int)ch[i])-48);
}
}
cout<<"OUTPUT: ";
switch(op[0])
{
case '+':
cout<<num1 + num2<<endl;
break;
case '-':
cout<<num1 - num2<<endl;
break;
case '*':
cout<<num1 * num2<<endl;
break;
case '/':
cout<<num1 / num2<<endl;
break;
}
}
I'm trying to count the cats and dogs in a string. So,
for example:
if the string is "cc+dd-cd",:
I want to count 2 positive cats, 2 positive dogs, 1 negative cat, 1 negative dog (yes I know this is a weird way to count, but it's part of my assignment).
I thought about doing a for loop where I iterated over the string, then nested inside the for loop, I'd have a while loop that would run until a '-', then run until a '+' or the end. I started the code, and without even getting that far into it, it created an infinite loop.
Question: How can I fix it?
Thanks!
string animalparkString = "cc+dd-cd"
for (int k = 0; k != animalparkString.size(); k++)
{
while (k != '-'){
pdc = pdc + 1; //positive dog count
pcc = pcc + 1; //positive cat count
}
while (k != '+') {
ndc = ndc + 1;
ncc = ncc + 1;
}
}
The immediate issue is that the while loops check k's value, but don't modify it. So once you entered one of them you'll be stuck there infinitely as k doesn't change inside the loop's body.
I wouldn't bother with nested loops - I'd just go over the entire string in one loop, and evaluate each character in its turn. A neat way to accomplish this is to keep a state of whether you're adding or subtracting (according to whether you last encountered a + or a - sign:
bool positive = true;
string animalparkString = "cc+dd-cd";
for (int k = 0; k < animalparkString.size(); k++) {
char ch = animalparkString[k];
switch (ch) {
case '+':
positive = true;
break;
case '-':
positive = false;
break;
case 'c':
if (positive) {
pcc++;
} else {
ncc++
}
break;
case 'd':
if (positive) {
pdc++;
} else {
ndc++
}
break;
}
}
This post describes iterating all characters is a string.
This is a simple solution using modern C++:
int sign = 1;
int dogs_count = 0, cats_count = 0;
std::string animalparkString = "-cccccc+dddd-cd";
for (const char& ch : animalparkString)
{
switch (ch) {
case '+':
sign = 1;
continue;
case '-':
sign = -1;
continue;
case 'c':
cats_count += sign;
continue;
case 'd':
dogs_count += sign;
continue;
}
}
std::cout <<"dogs: " << dogs_count << " cats: " <<cats_count;
A couple of suggestions to help you get started:
1. Use online c++ compilers to quickly test code
2. If your code doesn't behave as expected, use step-by-step debugging in your IDE or print our variables as you go using std::cout
3. Explicitly stating namespace is considered good practice. i.e:
// preferable:
std::string myString;
// avoid:
using namespace std;
string myString
To make your code work without too many changes , you can simply replace the while() condition with an if(). Moreover, instead of checking the iterator value k, you should compare the kth string element animalparkString[k].
Then you might start wondering if the code you wrote is actually doing what you expect. Possible questions you could try to answer is "how do I distinguish between positive or negative counts" and, then, "how do I distinguish between cats and dogs "? You will probably need to check also for cs and ds, not only for the operation sign!
string animalparkString = "cc+dd-cd"
for (int k = 0; k != animalparkString.size(); k++)
{
if(animalparkStrink[k] != '-'){
// Now you know, there will be a pos count. Dog or Cat?
}
if(animalparkString[k] != '+') {
// Now you know, there will be a neg count. Dog or Cat?
}
}
Note that if you write while( k != '-'), it will always evaluate true and, therefore, you will be stuck there. If it is the first time working with for-loops, consider printing the iterator value, to understand when and where you are stuck.
string animalparkString = "cc+dd-cd"
for (int k = 0; k != animalparkString.size(); k++)
{
std::cout << "for-loop iteration number: " << k << std::endl;
if(animalparkStrink[k] != '-'){
// Now you know, there will be a pos count. Dog or Cat?
}
if(animalparkString[k] != '+') {
// Now you know, there will be a neg count. Dog or Cat?
}
}
for and while together approach is unnecessarily complicated. Here's a simpler solution:
#include <concepts>
#include <iostream>
int main() {
auto const& str{"cc+dd-cd"};
std::boolean auto isPositive = 1;
std::integral auto pdc{0}, pcc{0}, ndc{0}, ncc{0};
for (char const ch : str) {
switch (ch) {
case 'c': {
pcc += isPositive;
ncc += !isPositive;
break;
}
case 'd': {
pdc += isPositive;
ndc += !isPositive;
break;
}
case '+': {
isPositive = true;
break;
}
case '-': {
isPositive = false;
break;
}
}
}
std::cout << "pcc: " << pcc << '\n'
<< "ncc: " << ncc << '\n'
<< "pdc: " << pdc << '\n'
<< "ndc: " << ndc << '\n';
}
LIVE
I am writing a small program convert hex representation of a string , it is a kata to improve my skills.
This is what I have come up with
std::vector<int> decimal( std::string const & s )
{
auto getint = [](char const k){
switch(k){
case 'f':
return 15;
case 'e':
return 14;
case 'd':
return 13;
case 'c':
return 12;
case 'b':
return 11;
case 'a':
return 10;
case '9':
return 9;
case '8':
return 8;
case '7':
return 7;
case '6':
return 6;
case '5':
return 5;
case '4':
return 4;
case '3':
return 3;
case '2':
return 2;
case '1':
return 1;
case '0':
return 0;
};
std::vector<int> result;
for( auto const & k : s )
{
result.push_back(getint(k));
}
return result;
}
I was wondering if there in another way to do this. I have considered to use something as an std::map as well, but I am uncertain which one might be faster. If there is another way to do this please add it.
Please keep in mind that I am doing this as a code-kata to improve my skills, and learn.
Thanks and TIA!
To start with, you can probably simplify your logic like so:
auto getint = [](char const k){
if(k >= 'a' && k <= 'f') return (k - 'a');
else if(k >= 'A' && k <= 'F') return (k - 'A');
else if(k >= '0' && k <= '9') return (k - '0');
else return -1;
}
Beyond that, there may exist a Standard Library function that does exactly this, which you might prefer depending on your specific needs.
For the decimal digits it's very easy to convert a character to its digit, as the C++ specification says that all digits must be consecutive in all encodings, with '0' being the lowest and '9' the highest. That means you could convert a character to number by just subtracting '0', like e.g. k - '0'. There's no such requirement for the letters though, but the most common encoding (ASCII) the same is true, but it should not be counted on if you want to be portable.
You could also do it using e.g. std::transform and std::back_inserter, so no need for your own loop. Perhaps something like
std::transform(std::begin(s), std::end(s), std::back_inserter(result), getint);
In the getint function you could use e.g. std::isxdigit and std::isdigit to check if the character is a valid hexadecimal or decimal digit, respectively. You should probably be using e.g. std::tolower in case the hexadecimal digits are upper-case.
You can use strtol or strtoll to do most of the heavy lifting for you of converting from a base16 string to an integer value.
Then convert back to a regular string using a stringstream object.
// parse hex string with strtol
long value = ::strtol(s.c_str(), nullptr, 16); //not shown - checking for errors. Read the manual page for more info
// convert value back to base-10 string
std::stringstream st;
st << value;
std::string result = st.str();
return result;
Assume one has an vector or array of N elements (N can be very large) containing the octal representation of a non negative integer. How do I get the decimal representation of the number from this array? The code has to be really fast.
EDIT: array A of N elements contains octal representation of a non-negative integer K, i.e. each element of A belongs to the interval [0; 7] (both ends included)
Example: A[0] = 2; A[1] = 6; A[2] = 3
Now a naive calculation would be 2*8pow0 + 6*8pow1 + 3*8pow2 = 2+ 48+ 192 = 242
I tried this but it does not seem to work for large inputs > 6K
//vector<int> A is the input
using namespace std;
vector<int>::iterator it = A.begin();
unsigned int k = 0;
unsigned int x = 0;
while(it < A.end()){
x = x | (*it<<3*k);
k++;
it++;
}
I am also having problems converting a hexadecimal string to its decimal representation? Is this the correct way to do this in C++:
//Assume S to be your input string containing a hex representation
//like F23
std::stringstream ss;
ss << std::hex << S;
ss >> x;
Arbitray precision octal to decimal conversion is rather annoying because there is no way to localize the computation. In other words a change in the most significant digit of the octal number will change even the least significant digit in the decimal representation.
That said I think I would convert the octal number to a say base-1000000000 number and then I'd print that (this is instead a trivial problem, each base-1000000000 digit just maps trivially to 9 base-10 digits).
The conversion to base-1000000000 is simple because you only need to support incrementing and multiplying by two (just consider the input as binary with three bits for each octal digit).
EDIT
I tried to implement it in C++ and this is the resulting code
#include <stdio.h>
#include <vector>
int main(int argc, const char *argv[]) {
// Base 100,000,000 accumulator
// Initialized with one digit = 0
std::vector<unsigned> big(1);
const unsigned DIGIT = 100000000;
for (int c=getchar(); c >= '0' && c <= '7'; c=getchar()) {
// Multiply accumulator by 8 and add in incoming digit
int carry = c - '0';
for (int i=0,n=big.size(); i<n; i++) {
unsigned x = big[i] * 8 + carry;
carry = x / DIGIT;
big[i] = x - carry * DIGIT;
}
if (carry) big.push_back(carry);
}
// Output result in decimal
printf("%i", big.back());
for (int i=int(big.size())-2; i>=0; i--) {
printf("%08i", big[i]);
}
putchar('\n');
return 0;
}
On my PC the time to convert an 80,000 digit octal number to decimal (resulting in 72246 digits) is about 1.2 seconds. Doing the same using python eval/str the time is about 3 seconds. The number used was "01234567" * 10000.
The code above uses 100,000,000 as base so that it can process one digit (3 bits) at a time with 32-bit arithmetic not overflowing with the intermediate results. I tried also using 64 bit integers or the 53 bit integer part of a double but the code was running always slower than in this case (one reason is probably the division in the inner loop that can be converted to a multiplication in the 32 bit case).
This is still a simple O(n^2) implementation that would take ages to convert a 10,000,000-digits octal number.
This is what I came up with:
template<typename Iter>
int read_octal(Iter begin, Iter end)
{
int x = 0;
int f = 1;
for (; begin != end; ++begin)
{
x += *begin * f;
f *= 8;
}
return x;
}
int main()
{
int test[] = {2, 6, 3};
int result = read_octal(test + 0, test + 3);
std::cout << result << '\n';
}
I tried this but it does not seem to work for large inputs > 6K
What exactly do you mean by 6k? An int usually has 32 bits, and an octal digit has 3 bits. Thus, you cannot have more than 10 elements in your range, otherwise x will overflow.
I am also having problems converting a hexadecimal string to its decimal representation?
Well, you could always write a function to parse a string in hex format yourself:
int parse_hex(const char* p)
{
int x = 0;
for (; *p; ++p)
{
x = x * 16 + digit_value(*p);
}
return x;
}
With the most portable version of digit_value being:
int digit_value(char c)
{
switch (c)
{
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case 'A':
case 'a': return 10;
case 'B':
case 'b': return 11;
case 'C':
case 'c': return 12;
case 'D':
case 'd': return 13;
case 'E':
case 'e': return 14;
case 'F':
case 'f': return 15;
}
}