[英]How can I read only the integer values from a txt file into an array?
我正在修改我編寫的一些現有代碼,以從.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
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
,只需聲明一個double
數組(使用float
只會引入更多的舍入誤差,並且並沒有真正節省現代處理器的速度) . (例如存儲你的值,以便在陣列中R1
在索引0
, R2
在索引1
,依此類推)。 這樣,如果您有多行相同的數據,只需將 7 個元素的臨時數組和一個memcpy
填充到它們的數組中即可。
您已經很好地使用了LINEMAX
的#define
來避免在整個代碼中散布魔術數字。 你也可以對字符串常量做同樣的事情,例如
#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
和指針數組來字符串文字,例如
/* 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.};
數組初始化為零,因此如果由於某種原因一行缺少值,則不會調用未定義的行為嘗試訪問未初始化的值)
/* compare tmp value ... */
邏輯上面的位置就是:
/* 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]);
一個簡短的示例,它采用您的輸入行並將雙R1-5, IA, IB
值按R1-5, IA, IB
的順序完全分離到一個數組中:
#include <stdio.h>
#include <string.h>
#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 */
/* 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" };
int main (int argc, char **argv) {
char buf[MAXC]; /* buffer to hold each line */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
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 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]);
nextline:; /* label for nextline */
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
return 0;
}
示例使用/輸出
使用文件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
由您決定,只需更多工作)
仔細檢查一下,如果您還有其他問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.