将文本文件数据读入结构数组(同时忽略注释行)
Reading text file data into an array of structs (while ignoring comment lines)
概览:
以下程序的目的是将数据从输入文件逐行读取到结构数组中,同时忽略输入文件中以 character '#'
开头的任何注释行。然后程序应遍历结构数组并打印内容,以确认程序是否按预期工作。
这是一个输入文件的例子,其中可以看到 3 行非注释数据。非注释行的数量在编译之前是已知的,如下面 int Nbodies = 3
.
行的尝试所示
30 07 6991
# some comment
28 02 4991
09 09 2991
注意:请注意,在决定 post 这个问题之前,已经研究了以下 SO 问题等:
Ignoring comments when reading in a file
Read a text file ignoring comments
困境:
当没有注释行时,程序可以成功地将行读入结构数组并打印内容。程序还可以成功检测行何时以 ' #' 字符,因此将其视为注释行。问题在于,即使检测到注释行,程序仍会尝试错误地将此行读入结构数组。
这是预期的输出:
30 07 6991
28 02 4991
09 09 2991
这是实际的(和不正确的)输出,它似乎忽略了最后一行未注释的数据:
30 07 6991
-842150451 -842150451 -842150451
28 02 4991
当前尝试:
fgets
已用于读取每一行,从而确定行的开头是否以 '#'
开头。此注释检查在 IF
语句中执行,该语句在 FOR
循环条件中递增 Nbodies
变量(因此迭代不是 'wasted' 在注释行中,如果那讲得通?)。此后,sscanf
用于尝试将当前 非注释行 的三个值读入结构数组。 fscanf
也是一种尝试的方法,但没有用。通过在示例中看到的 IF 语句中使用 continue;
,如果检测到注释行,sscanf
不应该是 'skipped' 吗?它似乎没有按预期进行。
到目前为止的代码:
#include "stdio.h"
#define EXIT_SUCCESS 0
#define EXIT_FAILURE !EXIT_SUCCESS
int main() {
typedef struct {
int a1, b1, c1;
}DATA;
FILE *file = fopen("delete.nbody", "r");
if (file == NULL)
{
printf(stderr, "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int Nbodies = 3;
int comment_count = 0;
DATA* data = malloc(Nbodies * sizeof * data); // Dynamic allocation for array
char line[128]; // Length won't be longer than 128
int x;
for (x = 0; x < Nbodies; x++)
{
fgets(line, sizeof(line), file);
if (line[0] == '#')
{
comment_count++;
Nbodies++;// Advance Nbodies so that iteration isn't 'wasted' on a comment line
continue;
}
// QUESTION: doesn't "continue;" within above IF mean that the
// following sscanf shouldn't scan the comment line?
sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
}
// Nbodies - comment_count, because Nbodies advanced
// every time a comment was detected in the above FOR loop
for (x = 0; x < Nbodies - comment_count; x++)
{
printf("%d %d %d\n", data[x].a1, data[x].b1, data[x].c1);
}
return (EXIT_SUCCESS);
}
问题:
谁能看出为什么这个程序不能运行?我原以为 continue
这个词会在检测到时跳过 sscanf 读取注释行。任何帮助将不胜感激。
- 只有在你实际赋值时才增加数组索引
- 检查两个条件:数组索引和输入成功
for (x = 0; x < Nbodies; ) {
int rc;
if ( !fgets(line, sizeof line, file)) break;
if (line[0] == '#')
{
comment_count++;
continue;
}
rc = sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
if (rc != 3) continue;
x++;
}
如果您收到评论,请不要增加Nbodies
。
这是错误的方法,因为 data
由于预循环 malloc
[ 被限制为 Nbodies
的 原始 值=17=]
并且,您将在 data
数组中引入一个 间隙 。
这里有一个更好的方法,让data
只包含有效的数据。注释行完全变为 "invisible"(即它们 不会 影响数据的计数):
int
main()
{
typedef struct {
int a1,
b1,
c1;
} DATA;
FILE *file = fopen("delete.nbody", "r");
if (file == NULL) {
printf(stderr, "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int Nbodies = 3;
int comment_count = 0;
// Dynamic allocation for array
DATA *data = malloc(Nbodies * sizeof *data);
char line[128]; // Length won't be longer than 128
int x;
#if 0
for (x = 0; x < Nbodies; x++) {
fgets(line, sizeof(line), file);
if (line[0] == '#') {
comment_count++;
// Advance Nbodies so that iteration isn't 'wasted' on a comment
Nbodies++;
continue;
}
// QUESTION: doesn't "continue;" within above IF mean that the
// following sscanf shouldn't scan the comment line?
sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
}
#else
int inc = 1;
for (x = 0; x < Nbodies; x += inc) {
fgets(line, sizeof(line), file);
inc = (line[0] != '#');
if (! inc) {
comment_count++;
continue;
}
// QUESTION: doesn't "continue;" within above IF mean that the
// following sscanf shouldn't scan the comment line?
sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
}
#endif
// Nbodies - comment_count, because Nbodies advanced
// every time a comment was detected in the above FOR loop
#if 0
for (x = 0; x < Nbodies - comment_count; x++) {
#else
for (x = 0; x < Nbodies; x++) {
#endif
printf("%d %d %d\n", data[x].a1, data[x].b1, data[x].c1);
}
return (EXIT_SUCCESS);
}
概览:
以下程序的目的是将数据从输入文件逐行读取到结构数组中,同时忽略输入文件中以 character '#'
开头的任何注释行。然后程序应遍历结构数组并打印内容,以确认程序是否按预期工作。
这是一个输入文件的例子,其中可以看到 3 行非注释数据。非注释行的数量在编译之前是已知的,如下面 int Nbodies = 3
.
30 07 6991
# some comment
28 02 4991
09 09 2991
注意:请注意,在决定 post 这个问题之前,已经研究了以下 SO 问题等:
Ignoring comments when reading in a file
Read a text file ignoring comments
困境:
当没有注释行时,程序可以成功地将行读入结构数组并打印内容。程序还可以成功检测行何时以 ' #' 字符,因此将其视为注释行。问题在于,即使检测到注释行,程序仍会尝试错误地将此行读入结构数组。
这是预期的输出:
30 07 6991
28 02 4991
09 09 2991
这是实际的(和不正确的)输出,它似乎忽略了最后一行未注释的数据:
30 07 6991
-842150451 -842150451 -842150451
28 02 4991
当前尝试:
fgets
已用于读取每一行,从而确定行的开头是否以 '#'
开头。此注释检查在 IF
语句中执行,该语句在 FOR
循环条件中递增 Nbodies
变量(因此迭代不是 'wasted' 在注释行中,如果那讲得通?)。此后,sscanf
用于尝试将当前 非注释行 的三个值读入结构数组。 fscanf
也是一种尝试的方法,但没有用。通过在示例中看到的 IF 语句中使用 continue;
,如果检测到注释行,sscanf
不应该是 'skipped' 吗?它似乎没有按预期进行。
到目前为止的代码:
#include "stdio.h"
#define EXIT_SUCCESS 0
#define EXIT_FAILURE !EXIT_SUCCESS
int main() {
typedef struct {
int a1, b1, c1;
}DATA;
FILE *file = fopen("delete.nbody", "r");
if (file == NULL)
{
printf(stderr, "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int Nbodies = 3;
int comment_count = 0;
DATA* data = malloc(Nbodies * sizeof * data); // Dynamic allocation for array
char line[128]; // Length won't be longer than 128
int x;
for (x = 0; x < Nbodies; x++)
{
fgets(line, sizeof(line), file);
if (line[0] == '#')
{
comment_count++;
Nbodies++;// Advance Nbodies so that iteration isn't 'wasted' on a comment line
continue;
}
// QUESTION: doesn't "continue;" within above IF mean that the
// following sscanf shouldn't scan the comment line?
sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
}
// Nbodies - comment_count, because Nbodies advanced
// every time a comment was detected in the above FOR loop
for (x = 0; x < Nbodies - comment_count; x++)
{
printf("%d %d %d\n", data[x].a1, data[x].b1, data[x].c1);
}
return (EXIT_SUCCESS);
}
问题:
谁能看出为什么这个程序不能运行?我原以为 continue
这个词会在检测到时跳过 sscanf 读取注释行。任何帮助将不胜感激。
- 只有在你实际赋值时才增加数组索引
- 检查两个条件:数组索引和输入成功
for (x = 0; x < Nbodies; ) {
int rc;
if ( !fgets(line, sizeof line, file)) break;
if (line[0] == '#')
{
comment_count++;
continue;
}
rc = sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
if (rc != 3) continue;
x++;
}
如果您收到评论,请不要增加Nbodies
。
这是错误的方法,因为 data
由于预循环 malloc
[ 被限制为 Nbodies
的 原始 值=17=]
并且,您将在 data
数组中引入一个 间隙 。
这里有一个更好的方法,让data
只包含有效的数据。注释行完全变为 "invisible"(即它们 不会 影响数据的计数):
int
main()
{
typedef struct {
int a1,
b1,
c1;
} DATA;
FILE *file = fopen("delete.nbody", "r");
if (file == NULL) {
printf(stderr, "ERROR: file not opened.\n");
return EXIT_FAILURE;
}
int Nbodies = 3;
int comment_count = 0;
// Dynamic allocation for array
DATA *data = malloc(Nbodies * sizeof *data);
char line[128]; // Length won't be longer than 128
int x;
#if 0
for (x = 0; x < Nbodies; x++) {
fgets(line, sizeof(line), file);
if (line[0] == '#') {
comment_count++;
// Advance Nbodies so that iteration isn't 'wasted' on a comment
Nbodies++;
continue;
}
// QUESTION: doesn't "continue;" within above IF mean that the
// following sscanf shouldn't scan the comment line?
sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
}
#else
int inc = 1;
for (x = 0; x < Nbodies; x += inc) {
fgets(line, sizeof(line), file);
inc = (line[0] != '#');
if (! inc) {
comment_count++;
continue;
}
// QUESTION: doesn't "continue;" within above IF mean that the
// following sscanf shouldn't scan the comment line?
sscanf(line, "%d %d %d", &data[x].a1, &data[x].b1, &data[x].c1);
}
#endif
// Nbodies - comment_count, because Nbodies advanced
// every time a comment was detected in the above FOR loop
#if 0
for (x = 0; x < Nbodies - comment_count; x++) {
#else
for (x = 0; x < Nbodies; x++) {
#endif
printf("%d %d %d\n", data[x].a1, data[x].b1, data[x].c1);
}
return (EXIT_SUCCESS);
}