-2

The problem itself isn't that hard to find a solution but when i get to code it well... Here is the code:

#include<iostream>
#include<math.h>
int n;
using namespace std;
int input();
int num_count();
void new_val();

int main()
{
    n = input();
    new_val();
}

int input()
{
    int x;
    cout<<"Insert:";
    cin>>x;
    return x;
}

int num_count()
{
    int sub_n = n;
    int amount = 0;
    while(sub_n>0)
    {
        sub_n = sub_n/10;
        amount++;
    }
    return amount;
}

void new_val()
{
    int m[100] = {};
    int i;
    int count_n = num_count()-1;
    for(i=0; n>0; i++)
    {
         m[i]=n/(int)(pow(10,count_n));
         switch(m[i])
         {
             case 0:cout<<"Zero";break;
             case 1:cout<<"One"; break;
             case 2:cout<<"Two"; break;
             case 3:cout<<"Three";break;
             case 4:cout<<"Four";break;
             case 5:cout<<"Five";break;
             case 6:cout<<"Six";break;
             case 7:cout<<"Seven";break;
             case 8:cout<<"Eight";break;
             case 9:cout<<"Nine";break;
         }
         n = n%(int)pow(10,count_n);
         count_n--;
    }
}

The problem I found is very confusing when I ran the program with 123(I have used debugging to check the value multiple time)it runs smoothly with the first two number but on the last numbers it always gets a weird result Ex:

123 gives One Two Four

7895 gives Seven Nine Four // this is the weirdest

I can assume that there is some thing wrong with the new_val() function specifically this line:

n=n%(int)pow(10,count_n);

When I checked the debugging watches it was after this line that n's value gets messed up.

But when I paste it into the main() function it worked just fine.I hope this is not a stupid mistake of mine but if it is, can you please tell me the problem?

JeJo
  • 30,635
  • 6
  • 49
  • 88
Unknown
  • 19
  • 6
  • 2
    this is `c++`, not `c`. – Jean-Marc Zimmer Nov 02 '18 at 08:31
  • 2
    My recommendation is that you [get a few good books to read](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) and learn C++ properly. – Some programmer dude Nov 02 '18 at 08:34
  • 2
    I can't reproduce the problem. When I run this program in Visual Studio, I get the correct output for `123` and `7895`. I assume that the problem lies with rounding errors caused by those sketchy `(int)pow(10,count_n)` divisions. – Blaze Nov 02 '18 at 08:36
  • Please [format your code properly](https://stackoverflow.com/editing-help) and use the preview pane to verify, that your code is well indented. If you expect help from us, we expect some effort from you. – hellow Nov 02 '18 at 08:38
  • 1
    You can also create a const array of pointers to char initialized to your strings (e.g. `const char *numnames[] = { "Zero", "One", "Two", ...}` and then replace the `switch` with a simple `cout << numnames[m[i]];` – David C. Rankin Nov 02 '18 at 08:40

6 Answers6

1

The pow functions are for floating point numbers and not suitable for work on integers, There will be rounding errors which will cause the kind of problems you are seeing!

To solve your problem, I would probably convert the number to a string (maybe with std::to_string) and work with the characters of the string.

1

To avoid using the pow functions from math.h, write your own power_of_10 function. Since count_n will not be negative, you can implement it this way:

unsigned long long power_of_ten(int count)
{
    int pOf10 = 1;
    for(int i = 0; i < count; i++)
        pOf10 = pOf10 * 10;
    return pOf10;

}

And of course, your int array has to be redefined as:

unsigned long long m[100]={0};
P.W
  • 26,289
  • 6
  • 39
  • 76
1

There must be numerous Q/As in StackOverflow concerning this.

I probably hadn't answered but OP used the annoying pow() to get decimal powers. That's not good and unnecessary. It's about ints – pow() is not necessary but it may cause strange issues because it's dealing with doubles (or floats).

The intended effect (of separating digits) can be achieved much cheaper by applying modulo and divide in a loop – if starting from end.

Sample:

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

std::string numberToString(int number)
{
  // separate digits backwards:
  const char *digitWords[] = {
    "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"
  };
  std::vector<const char*> words;
  do {
    int digit = number % 10;
    words.push_back(digitWords[digit]);
    // do decimal right shift
    number /= 10;
  } while (number > 0);
  // add digit words in reverse order to string
  std::reverse(words.begin(), words.end());
  std::string ret;
  for (const char *const word : words) {
    ret += ' '; ret += word;
  }
  // done
  return ret;
}

int main()
{
  // some tests
  int numbers[] = { 123, 7859, 0 };
  for (int number : numbers) {
    std::cout << number << " spelled: " << numberToString(number) << '\n';
  }
  return 0;
}

Output:

123 spelled:  One Two Three
7859 spelled:  Seven Eight Five Nine
0 spelled:  Zero

Live Demo on coliru

Notes:

  1. I used the trick mentioned in David's comment – an array for the digit words – to translate digit ints to strings.

  2. The separation of digits is done from right to left: the digit is separated by number % 10, the digit is removed by number /= 10.

  3. This spells the number from right to left – the outcome has to be reversed finally. I used a rather simple method: storing the digit words in a std::vector which is reversed afterwards.

  4. The do/while loop grants at least one iteration. Hence, a single 0 is spelled correctly although the iteration stops as soon as all digits have been consumed (i.e. number became 0).

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
1

You can achieve your goal much easier using the following way.

  1. create an array of strings where strings are corresponding to 0 to 9
  2. get the user input as a string so that you do not limit the user's wish to INT_MAX
  3. for each char of the (input) string, check whether it is a digit.(using std::isdigit)
  4. If a digit, convert the char(which is a digit) to int and print the string in the array, at index = digit.

SEE LIVE


#include <iostream>
#include <array>    // std::array
#include <string>
#include <cctype>   // std::isdigit

int main()
{
    const std::array<std::string, 10> arr = { "Zero","One","Two","Three","Four","Five","Six","Seven","Eight", "Nine" };
    std::string IntString;  
    std::cout << "Insert:"; std::cin >> IntString;
    for (const char Char : IntString)
        (std::isdigit(Char)) ?
            std::cout << arr[Char - '0'] << " ": 
            std::cout << "Unknown ";   
    return 0;
}

Sample input:

12345678987654321h

output:

One Two Three Four Five Six Seven Eight Nine Eight Seven Six Five Four Three Two One Unknown 
JeJo
  • 30,635
  • 6
  • 49
  • 88
1

As P.W said make your own power of tens function and not use pow() as stated by many in the comments and answers due to unreliable results when working with integers.

For example:

//function for powers of 10
int power_of_ten(int x) 
{
    int power_of_tens = 10; // sets variable to 10
    for(int j = 1; j < x; ++j) //loops until j is greater than x(count_n)
    {
            power_of_tens *= 10;
    }
    return power_of_tens;
}

As an alternative solution with OP code refactored to include said function:

Demo

Default
  • 34
  • 5
0

You have to rework the way you loop through your numbers. pow returns a double, and that can cause rounding errors when you cast it back to an int like that. Something that is supposed to result in 5 might internally be 4.999999 instead, and when you typecast it, that would get truncated to 4. I also didn't get this error when running the program on my machine, you definitely don't want erratic behavior like that.

My suggestion is to get rid of those calculations and instead read the number in as string, allowing you to iterate through its content. Here's how your program could look like:

#include <iostream>
#include <string>
const char * nums[] = { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" };
int main()
{
    std::string n;
    std::cout << "Insert:";
    std::getline(std::cin, n);
    for (char i : n) {
        std::cout << nums[i - '0'];
    }
}
Blaze
  • 16,736
  • 2
  • 25
  • 44