将数字转换为字母(例如:123变成一二三)

时间:2018-11-02 08:29:02

标签: c++ algorithm

问题本身并不难找到解决方案,但是当我编写良好的代码时... 这是代码:

#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--;
    }
}

当我使用123(我已经使用调试多次检查值)运行程序时,发现的问题非常令人困惑,它在前两个数字上运行平稳,但在最后一个数字上总是出现奇怪的结果 例如:

  

123给出One Two Four

     

7895给出Seven Nine Four //这是最奇怪的

我可以假设new_val()函数特别是这一行有问题:

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

当我检查调试手表时,是在此行之后n的值被弄乱了。

但是当我将其粘贴到main()函数中时,它就可以正常工作。我希望这不是我的愚蠢错误,但是如果是这样,您能告诉我这个问题吗?

6 个答案:

答案 0 :(得分:1)

pow函数仅适用于浮点数,不适用于整数,将出现舍入错误,这将导致您遇到的这类问题!

为解决您的问题,我可能会将数字转换为字符串(也许使用std :: to_string)并使用字符串的字符。

答案 1 :(得分:1)

为避免使用pow中的math.h函数,请编写自己的power_of_10函数。由于count_n不会为负,因此您可以通过以下方式实现它:

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

}

当然,您的int数组必须重新定义为:

unsigned long long m[100]={0};

答案 2 :(得分:1)

与此有关的StackOverflow中必须有许多Q / A。

我可能没有回答,但是OP使用烦人的pow()来获取小数幂。那不是好事,没有必要。大约是int s – pow()不是必需的,但可能会引起奇怪的问题,因为它正在处理double s(或float s)。

通过模和除法(如果从末尾开始),可以更便宜地实现预期的(分隔数字)效果。

示例:

#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;
}

输出:

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

Live Demo on coliru

注释:

  1. 我使用了David评论中提到的技巧-数字单词的数组-将数字int转换为字符串。

  2. 从右到左进行数字分隔:数字用number % 10分隔,数字用number /= 10删除。

  3. 这将数字从右到左拼写–结果必须最终颠倒。我使用了一种相当简单的方法:将数字词存储在std::vector中,然后将其反转。

  4. do / while循环至少授予一次迭代。因此,尽管所有数字都被消耗(即0变成number)后,迭代会立即停止,但单个0的拼写正确。

答案 3 :(得分:1)

使用以下方法可以轻松实现目标。

  1. 创建一个字符串数组,其中字符串对应于09
  2. 获取用户输入的字符串,这样就不会将用户的期望限制为INT_MAX
  3. 对于(输入)字符串的每个字符,请检查其是否为数字。(使用std::isdigit
  4. 如果是数字,则将char(数字)转换为int并在索引= 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;
}

示例输入

12345678987654321h

输出

One Two Three Four Five Six Seven Eight Nine Eight Seven Six Five Four Three Two One Unknown 

答案 4 :(得分:1)

正如P.W所说的那样,要使自己具有tens函数的功能,而不要使用注释和答案中许多人所说的pow(),因为在处理整数时结果不可靠。

例如:

//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;
}

作为另一种解决方案,其中OP代码经过重构以包含上述功能:

Demo

答案 5 :(得分:0)

您必须重新设计遍历数字的方式。 pow返回一个double,当您将其强制转换回int时,可能会导致舍入错误。应该在内部产生5的内容可能是4.999999,而当您键入内容时,它将被截断为4。在我的计算机上运行程序时,我也没有收到此错误,您绝对不希望这样的行为不稳定。

我的建议是摆脱那些计算,而以字符串形式读取数字,从而允许您遍历其内容。您的程序如下所示:

#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'];
    }
}