- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个正在扫描的文本文件。文件中的第一个数字是矩阵中的行数,第二个数字是矩阵中的列数。
“文本文件”
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 个整数(前两行中的每一行)代表 rows
和 cols
数据的数量。然后,您会将 rows
数量的 cols
读取到您的矩阵中。您的第一个决定将是“我如何处理存储?” (动态分配,或者如果我对矩阵使用可变长度数组 (VLA),数据是否足够小它不会 StackOverflow?)
使用 VLA 消除了动态分配、跟踪和释放内存的需要,但您必须知道您不需要存储超过堆栈所能容纳的更多 double
值。以下假设您的值少于 100,000
使 VLA 成为有效选项。
首先,您将如何从文件中提取(读取)row
和 col
值?虽然 fgets
是迄今为止进行面向行输入的首选方式,但实际上您可以在对 的一次调用中同时获得
的额外好处是消耗 row
和 col
fprintfcol
值之后的所有剩余空格,直到矩阵的第一个值。例如,以下将起作用:
/* 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 "
中最后一个转换说明符之后的空格
)
有了 row
和 col
值,您现在可以调整缓冲区大小以使用 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/
我正在用 C 编写一个函数,它应该从文件中输入有关学生及其成绩的信息。但是,有时在运行程序时,即使输出符合预期,测试也会在 fscanf 处显示分析器错误。 /*structure for grade
如何在 fscanf() 中跳过一个值并转到下一个值?例如,我的输入文件中有以下数据: 11112222 3.95 4 22.5 我应该怎么做才能扫描第二个值? (我想跳过11112222扫描3.95
我正在使用这个 for 循环从纬度和经度坐标文件中引入数据,然后将坐标转换为十进制度数,将度数转换为弧度,然后计算分离角度,并返回两个城市之间的距离。我需要比较文件的前两行,计算距离,打印结果,然后再
我在 while(fscanf != EOF) 循环中执行了一些代码。但是,即使 fscanf 已完成执行,我也需要继续运行该代码,直到满足某些条件。我的意思是我想我可以将代码复制/粘贴到 while
我对 C 语言的文件处理非常陌生,我想问几个问题! 我经常使用 fscanf/fget 将文件转换为不同的格式。不过我不太清楚 fscanf 和 fgets 之间的区别。 特别是,我不确定 fscan
我是 C 的新手,这里有这个简单的代码: int main(int argc, char **argv){ FILE *input = stdin; char string[20];
我已经有了一些使用 fscanf() 读取文本文件的代码,现在我需要修改它,以便以前无空格的字段需要允许空格。文本文件基本上是这样的形式: title: DATA title: DATA etc...
我目前正在开发一个简单的 C 应用程序。它采用单个文件作为命令行参数,其格式如下: 1,2,3 4,5,6 7,8,9 etc. 但是,无论出于何种原因,fscanf 都不会扫描数字!这是一个例子:
我正在尝试读取逗号分隔值格式的文件,程序读取了前两种数据类型,但无法读取最后一种。请帮我一些忙 这是我正在尝试读取的文件中的内容: Jane,50,400.60 代码如下: FILE* fpt
我试图让我的程序从文件中读取输入,但不跳过 fscanf 通常执行的空行。扫描文件的文件和循环是: inFile = fopen("text.txt", "r"); for(i = 0; fsca
我正在尝试从 C 文件中读取数据,该文件将始终以以下类型的行进行格式化: 16 Oct 2013 00:01:00.000,0.000,0.000000 这是一个字符串、一个逗号、一个浮点数、一个逗号
如何格式化 fscanf 来格式化输入{'name surname', 'username', 指向不包含撇号的字符串 fscanf(fp,"{%s %s %d}",name,username,use
我正在尝试使用 fscanf 将文件中的行读取到指向字符数组的指针中。我在打印时遇到段错误。我究竟做错了什么?我应该使用 fscanf 以外的函数吗? #include #include #inc
我有一个制表符分隔文件,我正在尝试将其转换为制表符分隔文件。我正在使用 C。我在尝试读取文件的第二行时遇到了困难。现在我只有数万行重复第一行。 #include #include #define
我正在尝试使用 c 读取一个文件,其中每个变量都由竖线字符分隔。我尝试了以下 fscanf(fp, "%s[|], %s[|], \n", str1, str2); 括号之间的字符是垂直线:竖线字符。
我真的卡在某事上了。 我有一个文本文件,其中有 1 个单词后跟 ~100 个 float 。 float 由空格、制表符或换行符分隔。这种格式在整个文本文件中重复多次。 例如,这是文本文件的样子: o
我想使用 fscanf (使用 gcc 的 C 代码)从文件中解析 ip。所以,我想做: char myip[INET_ADDRSTRLEN]; fscanf(file, "%16s", myip);
while 循环不起作用,我不明白为什么。它没有给我任何错误,但它没有读取任何输入内容。文件内容为: 4 $11$ pelle $2$ pollo $333$ palla $41$ alla 我的代码
我有一些代码,我试图从文件中读取一个集团实例。实例文件中的第一行和第二行分别表示顶点和边的数量。但是我的代码似乎没有正确阅读。这是我的代码中与问题相关的部分: int num_edges=0; int
我正在尝试使用 fscanf 解析一个文本 (CSS) 文件并提取所有匹配此模式的语句: @import "some/file/somewhere.css"; 为此,我设置了以下循环: FILE *f
我是一名优秀的程序员,十分优秀!