【问题标题】:convert values in string to float array将字符串中的值转换为浮点数组
【发布时间】:2009-12-07 18:02:34
【问题描述】:

我在 C 中有一个字符串,它是从某种算法中得到的。它具有像这样格式的数值

0.100
0.840
0.030
0.460
0.760
-0.090

等等

需要将这些数值中的每一个存储到一个浮点数组中以进行数值处理。我是 C 新手,发现 C 中的字符串处理很复杂。谁能告诉我如何实现这一点。

【问题讨论】:

    标签: c arrays string


    【解决方案1】:

    使用strtod()。与atof() 不同,它可以检测输入字符串中的错误。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void) {
      char buf[] = "0.100\n0.8foo40\n0.030\n\n\n\n0.460\n0.760bar\n-0.090trash";
      char *err, *p = buf;
      double val;
      while (*p) {
        val = strtod(p, &err);
        if (p == err) p++;
        else if ((err == NULL) || (*err == 0)) { printf("Value: %f\n", val); break; }
        else { printf("Value: %f\n", val); p = err + 1; }
      }
      return 0;
    }
    

    strtod() 返回读取的值,除非出现错误。

    如果err指向传入的字符串,则字符串中没有任何内容,所以在我上面的sn-p中,我增加p以从下一个位置继续读取。 p>

    如果err 为 NULL 或指向空字符串,则没有错误,所以,在我的 sn-p 中,我打印该值并停止循环。

    如果err 指向字符串中的某个位置(不是p 本身,之前测试过),那就是有错误的字符,在我上面的sn-p 中,我知道读取了一些内容,所以我打印它,将 p 设置为越过错误并循环。


    编辑 为了完整起见,我应该提到错误的情况。 strtod() 读取的字符序列(尽管有效)可能无法由 double 表示。在这种情况下,errno 设置为 ERANGE,并且值本身是“无意义的”。您应该在调用strtod() 之前将errno 设置为0,然后在使用返回值之前对其进行检查。对于极小的输入值(例如“1E-42000”),设置 errno 是实现定义的,但返回 0(或几乎为 0)。

    【讨论】:

      【解决方案2】:

      是单个字符串中的所有值,例如“0.100 0.840 0.030 ...”,还是您有一堆单独的字符串,例如“0.100”、“0.840”、“0.030”等?如果它们在单个字符串中,它们是由空格(制表符、空格、换行符)还是由打印字符(逗号、分号)分隔?你知道你提前有多少值(即你的浮点数组需要多大)?

      要将表示单个浮点值的字符串转换为双精度值,请使用strtod(),如下所示:

      char valueText[] = "123.45";
      char *unconverted;
      double value;
      
      value = strtod(valueText, &unconverted);
      if (!isspace(*unconverted) && *unconverted!= 0)
      {
        /**
         * Input string contains a character that's not valid
         * in a floating point constant
         */
      }
      

      请阅读strtod() 了解详情。 unconverted 将指向字符串中未被strtod() 转换的第一个字符;如果它不是空格或 0,那么您的字符串没有正确格式化为浮点值,应该被拒绝。

      如果所有值都在一个字符串中,您将不得不将字符串分成不同的标记。执行此操作的简单(如果有些不安全)方法是使用strtok():

      char input[] = "1.2 2.3 3.4 4.5 5.6 6.7 7.8";
      char *delim = " "; // input separated by spaces
      char *token = NULL;
      
      for (token = strtok(input, delim); token != NULL; token = strtok(NULL, delim))
      {
        char *unconverted;
        double value = strtod(token, &unconverted);
        if (!isspace(*unconverted) && *unconverted != 0)
        {
          /**
           * Input string contains a character that's not valid
           * in a floating point constant
           */
        }
      }
      

      请阅读strtok() 了解详情。

      如果您不知道自己有多少个值,则需要进行一些内存管理。您可以使用malloc() 或realloc() 动态分配一些初始大小的浮点数组,然后使用realloc() 定期扩展它:

      #define INITIAL_EXTENT 10
      
      double *array = NULL;
      size_t arraySize = 0;
      size_t arrayIdx = 0;
      
      char input[] = ...; // some long input string
      char *delim = ...; // whatever the delimiter set is
      char *token;
      
      /**
       * Create the float array at some initial size
       */
      array = malloc(sizeof *array * INITIAL_EXTENT));
      if (array)
      {
        arraySize = INITIAL_EXTENT;
      }
      /**
       * Loop through your input string
       */
      for (token = strtok(input, delim); token != NULL; token = strtok(NULL, delim))
      {
        double val;
        char *unconverted;
        if (arrayIdx == arraySize)
        {
          /**
           * We've reached the end of the array, so we need to extend it.  
           * A popular approach is to double the array size instead of
           * using a fixed extent; that way we minimize the number
           * of calls to realloc(), which is relatively expensive.  
           *
           * Use a temporary variable to receive the result; that way,
           * if the realloc operation fails, we don't lose our
           * original pointer.
           */
          double *tmp = realloc(array, sizeof *array * (arraySize * 2));
          if (tmp != NULL)
          {
            array = tmp;
            arraySize *= 2;
          }
          else
          {
            /**
             * Memory allocation failed; for this example, we just exit the loop
             */
            fprintf(stderr, "Memory allocation failed; exiting loop\n");
            break;
          }
        }
        /**
         * Convert the next token to a float value
         */
        val = strtod(token, &unconverted);
        if (!isspace(*unconverted) && *unconverted != 0)
        {
          /**
           * Bad input string.  Again, we just bail.
           */
          fprintf(stderr, "\"%s\" is not a valid floating-point number\n", token);
          break;
        }
        else
        {
          array[arrayIdx++] = val;
        }
      }
      

      完成后不要忘记free() 数组。

      【讨论】:

      • 我尝试实现此功能,但每次都出现分段错误错误。调查它。你知道是什么原因造成的吗?
      • 段错误发生在哪里?在阅读令牌时?转换令牌?扩展数组?赋值?我把那个代码从我的头顶上扔掉了,所以如果有错误我不会感到惊讶,但它会帮助确切地知道它死在哪里。如果您可以通过调试器运行它以找到确切的行,那将很有帮助。
      【解决方案3】:
      【解决方案4】:

      你想要的函数叫做fscanf。

      /* fscanf example */
      /* Stolen from cplusplus.com
         Modified by C Ross */
      #include <stdio.h>
      
      int main ()
      {
        char str [80];
        float f;
        FILE * pFile;
      
        pFile = fopen ("myfile.txt","r");
        /* Loop over this and add to an array, linked list, whatever */
        fscanf (pFile, "%f", &f);
        fclose (pFile);
        printf ("I have read: %f \n",f);
        return 0;
      }
      

      【讨论】:

        【解决方案5】:

        假设你的字符串是

        char *str;
        

        使用类似的东西:

        double d[<enter array size here>];
        double *pd = d;
        
        for(char *p = str; p = strchr(p, '\n'); p++, pd++)
        {
            *p = 0;
            *pd = atof(p);
            *p = '\n';
        }
        

        【讨论】:

          【解决方案6】:

          如果它是一个字符串,首先您需要将其拆分为换行符,然后您可以使用“atof”stdlib 函数从中创建浮点数。像这样:

          【讨论】:

            猜你喜欢
            • 2011-11-25
            • 1970-01-01
            • 2017-09-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多