我有一个文本文件,其中一行的数字用空格分隔,如下例所示:
1 -2 3.1 0xf 0xcc
使用C程序解析文件后,结果应保存在向量中,其内部结构应为:
V[0]=1
V[1]=-2
V[2]=3.1
V[3]=15
V[4]=204
基本上我需要将以0x开头的数字转换为十进制数。
我已经尝试将所有元素存储在char矢量中,然后将其转换为数字,但没有太多成功。
任何有关C代码的帮助都将不胜感激。谢谢
你可以有一个look at sscanf
。这是一个简单的计划。我相信你可以从这里接受:
#include <stdio.h>
int main(void)
{
char *hex = "0xF";
int i= 0;
sscanf(hex, "%x", &i);
printf("%d", i);
}
你需要的是整数类型的strtol函数。您可以使用endptr
迭代字符串。对于double
,您可以使用atof函数,但您必须首先检查字符串是否包含点。
编辑:正如user3386109提到strtod是double
更好的解决方案。
假设你有一个数组中的字符串:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char numbers_str[] = "1 -2 3.1 0xf 0xcc";
int ints[10];
double doubles[10];
int ints_idx = 0, doubles_idx = 0;
const char delims[] = " ";
char *it = strtok(numbers_str, delims);
while(it != NULL)
{
char *dot_it = strchr(it, '.');
// When a dot is found then a double number is found
if(dot_it)
doubles[doubles_idx++] = strtod(it, NULL);
// When a dot is not found then we've got an integer
else
ints[ints_idx++] = strtol(it, NULL, 0);
it = strtok(NULL, delims);
}
printf("Integers found: \n");
for(int i = 0; i < ints_idx; ++i)
printf("%d\n", ints[i]);
printf("Double numbers found: \n");
for(int i = 0; i < doubles_idx; ++i)
printf("%f\n", doubles[i]);
}
处理从线上读取值的最简单方法是使用strtod
。 strtod
将两个指针作为参数。第一个指向开始点,以搜索数字(或引导+/-
),以便将数字的字符串表示转换为数字值(跳过所有前导空格)。第二个指向指针(endptr
)将被设置为转换中使用的最后一个字符之后的下一个字符。您开始搜索下一个要从那里转换的数字(例如设置p = ep;
并重复该过程)。
您可以查阅手册页以获取更多详细信息,但为了验证转换成功,您检查指针是否不等于结束指针(意味着数字已转换),并检查以确保未设置errno
。如果没有转换的数字(意味着你有一个无效的字符),你只需要手动向前扫描直到找到你的下一个+/-
或0-9
(或者你点击了nul-terminating字符)。
您希望保护数组边界,并通过保持一个简单的计数器并在阵列已满时退出循环来限制您尝试存储在向量数组中的值的数量。
这是一个简短的例子(省略了NAN和INF检查):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define VECSZ 5 /* if you need a constant, define one (or more) */
int main (int argc, char **argv) {
int i, n = 0;
double v[VECSZ] = {0.0};
char buf[BUFSIZ] = "";
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
while (n < VECSZ && fgets (buf, BUFSIZ, fp)) { /* read each line */
char *p = buf, *ep; /* pointer, end-pointer for strtod */
while (n < VECSZ) { /* convert vales in buf until VECSZ */
double tmp = strtod (p, &ep);
if (p != ep) { /* digits converted */
if (!errno) /* validate no error */
v[n++] = tmp; /* add to vector */
p = ep; /* update pointer */
}
else { /* no digits converted */
fprintf (stderr, "error: no digits converted.\n");
/* scan forward to next valid '+,-,0-9' */
while (*p && *p != '-' && *p != '+' && (*p < '1' || '9' < *p))
p++;
if (*p) /* numbers remain in line */
continue;
break; /* otherwise get next line */
}
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
for (i = 0; i < n; i++)
printf ("v[%d]=% g\n", i, v[i]);
return 0;
}
示例输入文件
$ cat dat/strtod_vect.txt
1 -2 3.1 0xf 0xcc
示例使用/输出
$ ./bin/strtod_vect dat/strtod_vect.txt
v[0]= 1
v[1]=-2
v[2]= 3.1
v[3]= 15
v[4]= 204
仔细看看,如果您有其他问题,请告诉我。您可以查看strtod(3) - Linux man page以获取更多详细信息和可以执行的错误检查。