【问题标题】:How to Parse Dollars And Cents in C如何在 C 中解析美元和美分
【发布时间】:2014-10-07 02:53:14
【问题描述】:

假设我有一个 3.50(字符串)的输入,我该如何解析它以便将它存储为 3 美元和 50 美分。美元和美分都是整数,不允许使用atoi。

我有这个想法,但显然它在 C 中不起作用(假设令牌是 3.50):

dollars = int(token); /* dollars is 3 */
cents = atoi(token) - dollars; /* atoi is not allowed but I can't think of anything else */

谢谢!

【问题讨论】:

  • 请不要将值转换为float。人们对舍入错误感到好笑
  • 如果atoi不被允许,人们不得不怀疑any库函数是否被允许。也许重点是自己解析字符串,一次一个字符。
  • 使用sprintf 而不是atoi
  • -1 对于这些任意要求避开标准库,在 cmets 中对答案进行了说明。你应该做自己的功课。对你来说会更好。

标签: c


【解决方案1】:

您是否想将自己的string 滚动到int 解析器...

int parse_int(char **s) {
  char sign = **s;
  if (sign == '-' || sign == '+') {
    (*s)++;
  }
  int result = 0;
  unsigned char ch;
  while (isdigit(ch = **s)) {
    (*s)++;
     // By accumulating the int on the negative side, we can parse INT_MIN
    result = result * 10 + '0' - ch;
  }

  if (sign != '-') result = -result;
  return result;
}


void parse_dollars_cents(char **s, int *dollar, int *cent) {
  *dollar = parse_int(s);
  if (**s == '.') {
    (*s)++;
    *cent = parse_int(s);
  } else {
    *cent = 0;
  }
}


int main(void) {
  char buf[100];
  fgets(buf, sizeof buf, stdin);
  int dollar, cent;
  char *s = buf;
  parse_dollars_cents(&s, &dollar, &cent);
  printf("$%d.%02d\n", dollar, cent);
  return 0;
}

【讨论】:

  • 啊,是的,这个答案比我的要安全得多:P
  • @Govind Parmar 谢谢,但它有这些缺点(都很容易修改):没有溢出检测,空字符串检测,美分的负值(有“123.-45”有点傻) , 将 cents 限制为 2 位数,cents 之后的额外数据,导致空白消耗。 OP可以根据需要添加。
【解决方案2】:

你可以使用sscanf

sscanf(stringWhereDollarCentValueIsStored , "%d.%d" , &dollars , &cents);

【讨论】:

  • 不能因为我在从文件读取数据的函数中使用它。
  • @Teddy 这如何使这个答案对您的问题无效?
  • 你可以在任何时候使用它,它不会影响任何东西,除了dollarscents这两个变量
【解决方案3】:

您需要修改这些以优雅地处理无效输入,但这些函数将适用于有效输入:

int get_dollars(char *str)
{
    int i = 0;
    int accum = 0;

    // While the current character is neither the null-terminator nor a '.' character
    while(str[i]&&str[i]!='.')
    {
        // Shift any previously accumulated values up one place-value by multiplying it by 10
        accum *= 10;
        // Add the numeric value of the character representation of the digit in str[i] to accum
        // (('0'-'9')-0x30=integer value 0-9)
        accum+=str[i]-0x30;
        // Increment the loop counter
        i++;
    }
    // Return the result
    return accum;
}

int get_cents(char *str)
{
    int i = 0; 
    int accum = 0;
    int start_pos = 0;
    // Get the location of the '.' character so we know where the cent portion begins at
    while(str[i]&&str[i]!='.') {i++; start_pos++; }
    i = start_pos+1;
    // Same algorithm as get_dollars, except starting after the '.' rather than before
    while(str[i])
    {
        accum *= 10;
        accum += str[i]-0x30;
        i++;
    }
    return accum;
}

【讨论】:

  • 想添加一些 cmets 吗?
【解决方案4】:

假设您所追求的美分长度仅为小数点后 2 位且令牌为 double,则从令牌中减去美元并乘以 100。

dollars=int(token);
token-=dollars;
cents=int(token*100.);

编辑:根据评论,tokenchar *

int dollars, cents;
sscanf(token,"%d.%d",&dollars,&cents);

编辑 2:从评论开始,没有 itoa()sscanf()

按照here 的描述实现以下功能。然后使用它:

double amount=parseFloat(token);
dollars=int(amount);
cents=int((amount-dollars)*100.);

【讨论】:

  • 我明白了,那么我们需要使用不同的方法。查看修改后的答案。
  • 我的坏,atoi 和 sscanf 是不允许的。
  • 哇。你让事情变得越来越难。在这种情况下,您需要编写自己的字符串解析器。
  • 刚刚为您找到了double 的解析器。见修改。
  • 将字符串解析为浮点数而不是将这些浮点数转换为 int 似乎相当迂回......
猜你喜欢
  • 2021-03-31
  • 1970-01-01
  • 1970-01-01
  • 2017-01-18
  • 1970-01-01
  • 2021-06-15
  • 2014-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多