将string中的值转换为float数组

时间:2009-12-07 18:02:34

标签: c arrays string

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

0.100
0.840
0.030
0.460
0.760
-0.090

等等

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

6 个答案:

答案 0 :(得分:2)

使用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指向传入的字符串,则不能在字符串中使用任何内容,所以在上面的代码片段中,我将p递增以继续从下一个位置读取。

如果err为NULL或指向空字符串,则没有错误,因此,在我的代码段中,我打印该值并停止循环。

如果err指向字符串中的某个位置(不是p本身,之前已经过测试过),那就是错误的字符,在我上面的代码段中,我知道有些东西被读了,所以我打印它,将p设置为错误并循环。


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

答案 1 :(得分:1)

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

要将表示单个浮点值的字符串转换为double,请使用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()动态分配一些初始大小的float数组,然后使用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()数组。

答案 2 :(得分:0)

答案 3 :(得分:0)

您想要的功能称为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;
}

答案 4 :(得分:0)

假设你的字符串是

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

答案 5 :(得分:0)

如果它是一个字符串,首先需要将它拆分为新行字符(s?)然后你可以使用“atof”stdlib函数从它们创建浮点数。像这样的东西: