【问题标题】:Count the length of a float given string计算给定字符串的浮点长度
【发布时间】:2015-10-07 01:01:52
【问题描述】:

假设您有一个变量char s[30],并且s 以正浮点数开头,例如 s = "15.016This is not a part of the float !";

浮点数后面的字符可以不是数字。

目标是确定代表浮点数的字符数,例如|15.016| = 6。

我正在尝试编写一个简单的代码来做到这一点,最好没有任何外部库。

我有:

int count_len(char *s)
{
   char tmp_buf[30];
   int integral_digits = sprintf(tmp_buf, "%d", atoi(s) );
   return integral_digits + sprintf(tmp_buf, "%d", atoi(s + integral_digits +1) );
}

这适用于任何分数不包含前导零的数字(适用于 15.16,但不适用于 15.016)。

你会如何修复这个函数?

【问题讨论】:

  • IRGS!您的 s 字符串长度超过 30!
  • 你找到函数“atof()”了吗?
  • 嗨@PeterMiehle - 是的,我试过了,atof,但是当你使用atof("1.6") 时,结果是1.60000001,这会破坏计数。
  • @PeterMiehle 在这种情况下,我会推荐strtod()/strtof() 而不是atof()。 :-)
  • 多条路通罗马

标签: c string floating-point char converter


【解决方案1】:

为什么不简单地将 sscanf 与 adhoc 格式说明符一起使用?

考虑

sscanf("15.01336This is not a part of the float !", "%*f%n", &len);

%*f%n 表示

  • %*f 读取浮点数但不要将其存储在任何地方,直接使用即可。
  • %n 存储到目前为止使用的字符数

一个工作示例

#include <stdio.h>

int main()
{
    int len;

    sscanf("15.01336This is not a part of the float !", "%*f%n", &len);

    printf("%d\n", len);

    return 0;
}

【讨论】:

  • 最好初始化int len = 0,以防没有发生FP转换。
【解决方案2】:

C 用于黑客攻击,所以为什么不即时编写函数,例如:

size_t floatlenghth(char *s)
{
  size_t len = 0;
  short found_dot = FALSE;
  while ((*s >= '0' && *s <= '9') || (*s == '.' && !found_dot)) {
    len += 1;
    if (*s == '.') found_dot = TRUE;
    s++;
  }
  return len;
}

让事情变得复杂,

  • 您必须查看语言环境(如小数分隔符的“,”)。

    .... char dottype = getdottypeforlocale();

    .... if (*s == dottype)

  • 您想如何计算点后的前导零和尾随零(例如,“001.200blubber”是长度 7 还是长度 3?)

    ... s = skipleadingzeros(s);

    ... /inside while/ if (found_dot && *s == '0') counttrailingzeros++;否则 counttrailingzeros = 0;

    ... /while 之后/ len -= counttrailingzeros;

  • 科学记数法:1.22E01

    ... while() 之后看一下 if *s = 'E' 并且接下来的两个字符是数字,然后添加 3

  • 千位标记,例如 1'234.56(这在任何地方都有效吗?)或 1,234.56(英语)或 1.234,56(德语)或 1,234,567.89

【讨论】:

  • isdigit 可能有用
  • @LubomírSedlář 在我想展示的这个例子中,你可以在没有任何库函数的情况下做到这一点。如果您想使用库功能(我确实推荐!),其他回答者已经展示了如何做到这一点。
  • 许多开发人员实际上无法编写代码,只能将库调用放在一起:)
  • @MartinJames 这是真的!但也有许多开发人员无法编写通用代码。当您第一次学习模拟库函数的编程让您感到自豪时,当您拥有多年广泛的编程经验时,您开始思考:如果用户语言环境使用, 而不是. 会怎样?如果浮子使用科学计数法怎么办?如果字符串编码是 UTF8 或某些 est asia 编码怎么办?因此,您会为编写和使用精确的接口(如库函数)而感到自豪。但是,我同意你的看法,你绝对需要通过自己编写代码的阶段才能称自己为开发人员:)
【解决方案3】:
int count_len(char *s){
    int len = 0;
    sscanf(s, "%*lf%n", &len);
    return len;
}

【讨论】:

    【解决方案4】:

    如果你有模式的输入字符串,

      "15.016This is not a part of the float !";
    

    正如您在问题中提到的,我建议您使用string.h 中提供的函数strspn()strcspn() 来找出前导@987654327 的长度 @ 类型。

    如果您使用strspn(),您可以将accept设置为所有数字和点.

    您不需要外部 库来使用它们。它们是标准 Cglibc 的一部分。

    【讨论】:

    • 感谢您的回答!不过,这只是一个小问题——如果在浮动之后还有另一个点会发生什么?我写了strspn(s, "0123456789."),但这不适用于s=15.016.3snjk。如果s[strspn(s, "0123456789")] == '.',我可以再次调用strspn,但想知道是否有更好的方法。再次感谢!
    • @RB 遗憾的是没有 直接 方法来获得它,您需要滚动自己的函数,可能会混合几个库函数。
    • 嗯...亲爱的投票者,愿意在这里发表评论吗?
    • @Sourav Ghosh NMDV,但 OP 确实说“最好没有任何外部库”,这表明不使用 strspn() strcspn() 的偏好。
    【解决方案5】:

    strtod 非常适合:

    char *endOfFloat;
    double val = strtod( str, &endOfFloat );
    size_t len = (size_t) endOfFloat - str;
    

    这假设字符串的浮点部分格式正确并且可以表示为double

    如果不是这样,您将需要一种不同的方法。

    【讨论】:

      【解决方案6】:

      我在 3 分钟内写下了这篇文章。但是,它有几个错误,例如,它在数字右侧计算零。你可以自己解决这个问题:)

      int count_len(const char *s)
      {
          const int sz = strlen(s);
          int sz_of_float = 0;
          bool dot = false; // to avoid double dots like ".."
          for(int i = 0; i < sz; i++)
          {
              if(s[i] >= '0' && s[i] <= '9')
                  sz_of_float++;
              else if(s[i] == '.' && dot == false)
              {
                  dot = true;
                  sz_of_float++;
              }
              else
                  return sz_of_float;
          }
          return -1;
      }
      

      【讨论】:

        【解决方案7】:

        以下是您对编写此类函数的算法的看法。

        1. 将计数设置为零。
        2. 如果第一个字符是非零数字,则将计数设置为 1。否则,退出并返回零。
        3. 从下一个字符开始,在碰到非数字字符或字符串末尾之前读入最大位数,每次递增计数。
        4. 如果到达字符串的末尾,退出并返回计数。否则,如果字符是句点,则计数加 1。
        5. 从句点后的下一个字符开始,在碰到非数字字符或字符串末尾之前读入最大位数,每次递增计数。
        6. 返回计数。

        示例代码:

        int countDigits(char const * str)
        {
            int count = 0;
            int i;
        
            if (str == NULL) return 0;
            for (i = 0; str[i] != '\0'; i++) {
                if (isdigit(str[i]))
                    count++;
                else
                    break;
            }
        }
        
        int countFloatChars(char const * str)
        {
            int count = 0;
        
            if (str == NULL) return 0;
            if (str[0] == '\0') return 0;
        
            if ((str[0] < '1') || (str[0] > '9')) return 0;
        
            count = 1;
            count += countDigits(str + count);
        
            if ((str[count] == '\0') || (str[count] != '.')) return count;
        
            count++;
            count += countDigits(str + count);
        
            return count;
        }
        

        【讨论】:

          【解决方案8】:

          不使用 C 库,在找到至少 1 个数字的位置查找 (digits).(digits)

          size_t float_length(const char *s) {
            const char *p = s;
            int digit_count = 0;
          
            // could add tests for white-space, +, - here        
          
            while (*p >= '0' && *p <= '9') {
              s++;
              digit_found = 1;
            }
            if (*p == '.') {
              p++;
              while (*p >= '0' && *p <= '9') {
                p++;
                digit_found = 1;
              }
            }
            if (digit_found) return (size_t) (p - s);
            return 0;
          }
          

          没什么花哨的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-18
            相关资源
            最近更新 更多