gpt4 book ai didi

c - 在 C 中使用 fscanf() 扫描数组的问题

转载 作者:太空宇宙 更新时间:2023-11-04 08:01:07 25 4
gpt4 key购买 nike

我有一个正在扫描的文本文件。文件中的第一个数字是矩阵中的行数,第二个数字是矩阵中的列数。

“文本文件”

4    
10
3.000000,1.000000,1180.000000,1955.000000,221900.000000
3.000000,2.250000,2570.000000,1951.000000,538000.000000
2.000000,1.000000,770.000000,1933.000000,180000.000000
.
.
.

n(4,10)矩阵

我正在使用 fscanf 来存储读取的数组,并使用两个循环来读取二维数组中接收到的值。

double hold;
fscanf(fpointer,"%d",&value);//gets me 4
fscanf(fpointer,"%d",&lastvalue);/*gets me 10*/
for (i=0; i<value; i++)
{
for (j=0; j<lastvalue; j++) //Supposed to input the other values
{
fscanf(fpointer,"%lf",&hold); array[i][j]=hold;

我通过两个 for 循环打印数组内容。

for(i=0;i<value;i++){
for(j=0;j<lastvalue;j++){

printf("%lf\t", array[i][j]);
}
printf("\n");

然而我收到循环的第一个索引作为输出重复。

3.000000    3.000000    3.000000    3.000000    3.000000    3.000000    3.000000    3.000000    3.000000    3.000000    
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000

我在这上面花了很多时间,我不确定我的逻辑是否不正确或者我对 fscanf 不了解。我最初以为 fscanf 在逗号方面有问题。正如我在另一篇文章 (fscanf(...,"%lf[^ ,]"...) 中看到的那样,我尝试使用逗号作为分隔符。我收到了相同的输出。请让我知道出了什么问题以及如何解决。

最佳答案

您可以采用多种方法。这里的关键是您知道您将有 2 个整数(前两行中的每一行)代表 rowscols 数据的数量。然后,您会将 rows 数量的 cols 读取到您的矩阵中。您的第一个决定将是“我如何处理存储?” (动态分配,或者如果我对矩阵使用可变长度数组 (VLA),数据是否足够小它不会 StackOverflow?)

使用 VLA 消除了动态分配、跟踪和释放内存的需要,但您必须知道您不需要存储超过堆栈所能容纳的更多 double 值。以下假设您的值少于 100,000 使 VLA 成为有效选项。

首先,您将如何从文件中提取(读取)rowcol 值?虽然 fgets 是迄今为止进行面向行输入的首选方式,但实际上您可以在对 的一次调用中同时获得 rowcol fprintf 的额外好处是消耗 col 值之后的所有剩余空格,直到矩阵的第一个值。例如,以下将起作用:

/* read row & col and consume all whitespace to first value */
if (fscanf (fp, "%d %d ", &row, &col) != 2) {
fprintf (stderr, "error: failed to read row and col.\n");
return 1;
}

(注意 "%d %d " 中最后一个转换说明符之后的空格)

有了 rowcol 值,您现在可以调整缓冲区大小以使用 fgets 读取文件中剩余的每一行。在将每一行读入缓冲区后,将使用 strtod 从缓冲区解析每一列值,并根据 col 值验证解析的值的数量以确保完整的行你的矩阵被填满了。行缓冲区是一个 VLA 以及大小 32-chars 每个要读取的 col 值(应该超过 50%) .可以按如下方式使用 VLA 调整缓冲区和矩阵的大小:

    bufsz = col * 32;       /* set read buffer size based on col */
char buf [bufsz]; /* VLA for read buffer */
double mtrx[row][col]; /* VLA for matrix */
memset (mtrx, 0, row * col * sizeof **mtrx); /* zero matrix */

接下来就是简单地用fgets读取每一行,然后用一个指针来测试当前字符是否是[+-0-9]之一。如果是,则执行并验证到 double 的转换,并将指针前进到转换中结束字符之后的下一个字符(由 strtod 本身提供) .

如果当前字符不是您感兴趣的字符,则不对其进行任何操作并获取下一个字符(这是跳过 ',' 的简单方法)

转换完一行中的所有值后,将成功转换的次数与 col 进行比较,以确保矩阵中的整行已被填充,如果没有则处理错误。然后只需读取下一行并重复,直到读取并转换了 row 行数。您可以完成类似于以下内容的操作:

    /* read each remaining line up to row lines */
while (ridx < row && fgets (buf, bufsz, fp)) {
int cidx = 0; /* column index */
char *p = buf, *ep = NULL; /* pointer & end pointer for strtod */
while (cidx < col && *p && *p != '\n') { /* for each character */
/* if '+-' or '0-9' convert number with strtod */
if (*p == '+' || *p == '-' || ('0' <= *p && *p <= '9')) {
errno = 0; /* set errno for strtod */
double tmp = strtod (p, &ep); /* convert string to value */
if (errno) { /* if errno set, conversion failed */
fprintf (stderr, "error: failed conversion mtrx[%d][%d].\n",
row, col);
return 1;
}
mtrx[ridx][cidx++] = tmp; /* set matrix value, inc. cidx */
p = ++ep; /* set new p to one past ep */
}
else /* if not '+-' or '0-9', just get next char */
p++;
}
if (cidx != col) { /* validate that col values contained in line */
fprintf (stderr, "error: row '%d' has only '%d' values.\n",
ridx, cidx);
return 1;
}
ridx++; /* row done and values validated, read next row */
}

在您读取了 row 行的 col 值之后,您可以根据需要使用您的矩阵。下面只是将以上内容放在一个简短的示例中,以读取和输出您提供的示例数据:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main (int argc, char **argv) {

int bufsz, col, row, ridx = 0; /* buffer size, col, row, row index */
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;
}

/* read row & col and consume all whitespace to first value */
if (fscanf (fp, "%d %d ", &row, &col) != 2) {
fprintf (stderr, "error: failed to read row and col.\n");
return 1;
}

bufsz = col * 32; /* set read buffer size based on col */
char buf [bufsz]; /* VLA for read buffer */
double mtrx[row][col]; /* VLA for matrix */
memset (mtrx, 0, row * col * sizeof **mtrx); /* zero matrix */

/* read each remaining line up to row lines */
while (ridx < row && fgets (buf, bufsz, fp)) {
int cidx = 0; /* column index */
char *p = buf, *ep = NULL; /* pointer & end pointer for strtod */
while (cidx < col && *p && *p != '\n') { /* for each character */
/* if '+-' or '0-9' convert number with strtod */
if (*p == '+' || *p == '-' || ('0' <= *p && *p <= '9')) {
errno = 0; /* set errno for strtod */
double tmp = strtod (p, &ep); /* convert string to value */
if (errno) { /* if errno set, conversion failed */
fprintf (stderr, "error: failed conversion mtrx[%d][%d].\n",
row, col);
return 1;
}
mtrx[ridx][cidx++] = tmp; /* set matrix value, inc. cidx */
p = ++ep; /* set new p to one past ep */
}
else /* if not '+-' or '0-9', just get next char */
p++;
}
if (cidx != col) { /* validate that col values contained in line */
fprintf (stderr, "error: row '%d' has only '%d' values.\n",
ridx, cidx);
return 1;
}
ridx++; /* row done and values validated, read next row */
}

if (fp != stdin) fclose (fp); /* close file if not stdin */

if (ridx != row) { /* validate that row rows read from file */
fprintf (stderr, "error: file has only row '%d' rows.\n", ridx);
return 1;
}

for (int i = 0; i < row; i++) { /* output the matrix */
for (int j = 0; j < col; j++)
printf (" %9.2f", mtrx[i][j]);
putchar ('\n');
}

return 0;
}

示例使用/输出

$ ./bin/readmtrx dat/matrix.txt
3.00 1.00 1180.00 1955.00 221900.00
3.00 2.25 2570.00 1951.00 538000.00
2.00 1.00 770.00 1933.00 180000.00

仔细检查一下,如果您还有其他问题,请告诉我。如果您没有编译器提供的 VLA 扩展,动态内存分配是您的另一个选择,如其他答案中所述。

关于c - 在 C 中使用 fscanf() 扫描数组的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46761990/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com