【发布时间】:2009-12-07 18:02:34
【问题描述】:
我在 C 中有一个字符串,它是从某种算法中得到的。它具有像这样格式的数值
0.100
0.840
0.030
0.460
0.760
-0.090
等等
需要将这些数值中的每一个存储到一个浮点数组中以进行数值处理。我是 C 新手,发现 C 中的字符串处理很复杂。谁能告诉我如何实现这一点。
【问题讨论】:
我在 C 中有一个字符串,它是从某种算法中得到的。它具有像这样格式的数值
0.100
0.840
0.030
0.460
0.760
-0.090
等等
需要将这些数值中的每一个存储到一个浮点数组中以进行数值处理。我是 C 新手,发现 C 中的字符串处理很复杂。谁能告诉我如何实现这一点。
【问题讨论】:
使用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)。
【讨论】:
是单个字符串中的所有值,例如“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() 数组。
【讨论】:
你想要的函数叫做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;
}
【讨论】:
假设你的字符串是
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';
}
【讨论】:
如果它是一个字符串,首先您需要将其拆分为换行符,然后您可以使用“atof”stdlib 函数从中创建浮点数。像这样:
【讨论】: