C 如何将txt文件中的整数值读取到数组中?
我正在修改我编写的一些现有代码,以便从.txt文件中获取电阻和电流值,并计算电压解。让我困惑的是,一旦我读入一行并使用strtok将整数与其他文本分开,我就不知道如何正确地将这些值保存到一些变量中,然后插入数组 以下是从文本文件读入的示例行: R3:56.0,R1:33.0,R2:47.0,R4:68.0,R5:75.0,IA:10.0,IB:110.0 我下面的代码采用该行并输出:C 如何将txt文件中的整数值读取到数组中?,c,C,我正在修改我编写的一些现有代码,以便从.txt文件中获取电阻和电流值,并计算电压解。让我困惑的是,一旦我读入一行并使用strtok将整数与其他文本分开,我就不知道如何正确地将这些值保存到一些变量中,然后插入数组 以下是从文本文件读入的示例行: R3:56.0,R1:33.0,R2:47.0,R4:68.0,R5:75.0,IA:10.0,IB:110.0 我下面的代码采用该行并输出: R3 56.0 R1 33.0 R2 47.0 R4 68.0 R5 75.0 IA 10.0 IB
R3
56.0
R1
33.0
R2
47.0
R4
68.0
R5
75.0
IA
10.0
IB
110.0
我的下一个目标是以某种方式识别R3=56.0和R1=33.0,以此类推,将这些值存储到名为R1、R2、R3、R4、R5、I1、I2的变量中,以便稍后在代码中使用它们
#include <stdio.h>
#include <string.h>
#define LINEMAX 100
int main()
{
FILE *dataPtr;
char line[LINEMAX];
char* token;
float R1 ,R2, R3, R4, R5, I1, I2;
double A[4][5];
int i = 0;
if((dataPtr = fopen("input.txt" , "r")) == NULL)
{
fprintf(stderr , "FILE NOT FOUND!");
}
while (fgets(line, LINEMAX, dataPtr) != NULL)
{
token = strtok (line, ",:");
while (token != NULL)
{
printf("%s\n" , token);
token = strtok (NULL, ",:");
}
}
fclose(dataPtr);
下面是一些建议,可以帮助您将每一行解析为所需的值。与7个单独的变量R1、R2、R3、R4、R5、I1、I2不同的是,只需声明一个使用float的double数组就可以引入更多的舍入误差,并不能在现代处理器上真正节省大量的速度。在数组中按顺序存储值,例如,R1位于索引0,R2位于索引1,等等。这样,如果有多行相同的数据,只需填充一个由7个元素组成的临时数组,并向其中的一个数组填充一个memcpy即可 您已经很好地使用了defineforlinemax,以避免在代码中散布幻数。您也可以对字符串常量执行相同的操作,例如
#define MAXC 1024 /* if you need a constant, #define one (or more) */
#define TOKLEN 32 /* size for temporary token storage */
#define NELEM 7 /* number of elements to separate (R1-5, IA, IB) */
#define DELIM ",\n" /* delimiter for strtok */
在解析数据行时,需要将R1之类的字符串映射到索引,并且需要一种将索引映射到字符串的方法,以便可以执行相反的操作。当映射的数量很少时,一个方便的方法就是使用一个枚举和一个指向字符串文本的指针数组,例如
/* enum for mapping names to index */
enum { R1, R2, R3, R4, R5, IA, IB };
/* array for mapping index to names */
const char *id[] = { "R1", "R2", "R3", "R4", "R5", "IA", "IB" };
这只是另一种避免在代码中散布字符串文字的方法,同时提供了一种让您避免的映射,例如
if (strcmp (tmp, "R1") == 0)
a[R1] = d;
else if (strcmp (tmp, "R2") == 0)
a[R2] = d;
...
并且,使用下面的方法,将id的单个定义保留在顶部,作为将来更改字符串映射时必须更改的唯一位置,例如
if (strcmp (tmp, id[R1]) == 0)
a[R1] = d;
else if (strcmp (tmp, id[R2]) == 0)
a[R2] = d;
...
要将值解析到相应的数组索引中,只需将每一行读入缓冲区,用strtok标记该行以获得逗号分隔的值,然后在标记上使用sscanf解析每个标记的名称和值,例如
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line */
...
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
char tmp[TOKLEN]; /* temporary storage for R3, etc.. */
double d, a[NELEM] = {0.}; /* temporary double and array */
/* tokenize line */
for (char *p = strtok(buf, DELIM); p; p = strtok(NULL, DELIM)) {
/* separate token into tmp string and double value in array */
if (sscanf (p, " %31[^:]:%lf", tmp, &d) != 2) {
fputs ("error: bad token format\n", stderr);
goto nextline; /* goto steps over code to process full arr */
}
... /* compare tmp value here and store in-order in array */
}
... /* handle whatever additional processing on array needed here */
nextline:; /* label for nextline */
}
注:a[NELEM]={0.};数组初始化为全零,所以如果由于某种原因某行缺少值,您不会调用未定义的行为来尝试访问未初始化的值
其中,/*比较tmp值…*/逻辑应该是:
/* compare value in tmp store in-order in array */
if (strcmp (tmp, id[R1]) == 0)
a[R1] = d;
else if (strcmp (tmp, id[R2]) == 0)
a[R2] = d;
else if (strcmp (tmp, id[R3]) == 0)
a[R3] = d;
else if (strcmp (tmp, id[R4]) == 0)
a[R4] = d;
else if (strcmp (tmp, id[R5]) == 0)
a[R5] = d;
else if (strcmp (tmp, id[IA]) == 0)
a[IA] = d;
else if (strcmp (tmp, id[IB]) == 0)
a[IB] = d;
else {
fputs ("error: unrecognized format.\n", stderr);
goto nextline;
}
对于进一步的处理,例如,我们只是按顺序输出值,例如
for (int i = 0; i < NELEM; i++) /* output line results */
printf ("got %s = %.2f\n", id[i], a[i]);
示例使用/输出
使用文件dat/rnumval.txt中的输入行,您将收到:
$ ./bin/readrnumval dat/rnumval.txt
got R1 = 33.00
got R2 = 47.00
got R3 = 56.00
got R4 = 68.00
got R5 = 75.00
got IA = 10.00
got IB = 110.00
这只是一种方便地将单独的值映射到数组中可识别索引的方法,允许您映射名称和索引。这就是为什么我建议让您的姓名和文字与输入中的数据相匹配,例如IA、IB而不是I1、I2-由您决定,只是需要更多的工作
仔细检查一下,如果您还有其他问题,请告诉我。每次strtok使用strtof将字符串标记转换为浮点。或者使用带分隔符的strtok,然后使用sscanf%[^:]:%lf,tmp和dblval,如果sctrmp tmp,R1==0{…}如果strcmp tmp,R2==0{…}如果…@DavidRankin,这似乎是一个很有希望的建议,我正在重新编写代码以尝试这种方法。谢谢您的回答。@nontype-如果您遇到问题,请在问题的末尾添加一个编辑,不要替换原始内容,我们可以提供进一步的帮助。注意:对于您的数据,应该是sscanf%[^::]:%lf、tmp和dblval。理解为什么格式字符串中需要额外的空间吗?哇,好的。这是一个很大的解包,所以我可能要到明天才能得到它的所有内容,但感谢您对这些概念的透彻解释。特别是关于创建简明代码的建议,这是一个我非常感兴趣的话题,有很多地方需要改进。如果你有什么问题,明天就发表评论吧。对于char*p=strtok。。。只是重写char*p=strtok的另一种方法。。。当p{…p=strtok NULL,}循环时。没什么神奇的。我在你的帖子中根据需要修改它来保存变量,然后在程序中使用它们来计算电压。非常感谢您的帮助,在您的帮助下,我学到了很多很棒的实现。很高兴它起到了作用。这就是这个网站如此特别的原因。这是一个将学习成果传给下一代程序员和工程师的绝佳工具。祝您编码顺利:
$ ./bin/readrnumval dat/rnumval.txt
got R1 = 33.00
got R2 = 47.00
got R3 = 56.00
got R4 = 68.00
got R5 = 75.00
got IA = 10.00
got IB = 110.00