好的,从评论继续,正如评论中所述,对于任何数据处理问题,您需要做的第一件事是将所有数据读入一个允许您根据需要使用它的表单.在这里,您有不同类型的数据,它们都构成一个单元(在这种情况下是汽车)。每当您必须将不同类型的数据作为一个单元处理时,您都应该考虑 struct.这里的结构 car 是有意义的:
typedef struct { /* struct for cars */
int id;
char color[MAXN];
char manf[MAXN];
int year;
} car;
您现在可以将数据文件中的每一行读入一个数组或struct car,并为您的其余代码提供所有数据。
当您有 行 数据时,您应该考虑 面向行 输入,例如fgets 或 getline。虽然您可以在此处使用scanf 系列,但最好一次读取一行并从读取的每一行中解析您的数据。此外,通常最好将数据解析为临时变量,然后如果您确认您已经全部考虑,那么,并且只有这样,将您的临时变量复制到您的结构并增加您的索引。例如,您可以执行以下操作:
/* constants for max name, chars & structs */
enum { MAXN = 16, MAXC = 64, MAXS = 128 };
...
car cars[MAXS] = {{ .id = 0 }}; /* array of struct car */
char buf[MAXC] = "";
size_t i, j, idx = 0, nc = 0, nm = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
...
while (idx < MAXS && fgets (buf, MAXC, fp)) { /* read each line */
int tid, tyr; /* temp variables */
char tcol[MAXC] = "", tman[MAXC] = "";
/* separate into temp variables, validate, copy to struct */
if (sscanf (buf, " %d %s %s %d%*c", &tid, tcol, tman, &tyr) == 4) {
cars[idx].id = tid;
snprintf (cars[idx].color, MAXN, "%s", tcol);
snprintf (cars[idx].manf, MAXN, "%s", tman);
cars[idx++].year = tyr;
}
}
现在您的结构数组中已经有了所有数据,剩下的唯一事情就是确定数据中的唯一颜色和制造商。您不需要将数据重新复制到另一个数组,您可以简单地使用指针数组指向结构数组中的唯一值。你可以这样做:
char *colors[MAXN] = {NULL}, *manfs[MAXN] = {NULL}; /* pointer arrays */
...
for (i = 0; i < idx; i++) { /* find unique colors */
if (!nc) { colors[nc++] = cars[i].color; continue; }
for (j = 0; j < nc; j++)
if (!strcmp( colors[j], cars[i].color)) goto cdup;
colors[nc++] = cars[i].color;
cdup:;
}
(其中nc 是唯一颜色数量的计数器)
您可以为您的制造商做同样的事情。
将所有部分放在一起,(并注意所有您的制造商都有独特首字母开头)您可以执行以下操作:
#include <stdio.h>
#include <string.h>
/* constants for max name, chars & structs */
enum { MAXN = 16, MAXC = 64, MAXS = 128 };
typedef struct { /* struct for cars */
int id;
char color[MAXN];
char manf[MAXN];
int year;
} car;
int main (int argc, char **argv) {
car cars[MAXS] = {{ .id = 0 }}; /* array of struct car */
char *colors[MAXN] = {NULL}, *manfs[MAXN] = {NULL}; /* pointer arrays */
char buf[MAXC] = "";
size_t i, j, idx = 0, nc = 0, nm = 0;
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;
}
while (idx < MAXS && fgets (buf, MAXC, fp)) { /* read each line */
int tid, tyr; /* temp variables */
char tcol[MAXC] = "", tman[MAXC] = "";
/* separate into temp variables, validate, copy to struct */
if (sscanf (buf, " %d %s %s %d%*c", &tid, tcol, tman, &tyr) == 4) {
cars[idx].id = tid;
snprintf (cars[idx].color, MAXN, "%s", tcol);
snprintf (cars[idx].manf, MAXN, "%s", tman);
cars[idx++].year = tyr;
}
}
if (fp != stdin) fclose (fp);
for (i = 0; i < idx; i++) /* output all data */
printf ("%4d %-6s %-10s %d\n", cars[i].id, cars[i].color,
cars[i].manf, cars[i].year);
putchar ('\n');
for (i = 0; i < idx; i++) { /* find unique colors */
if (!nc) { colors[nc++] = cars[i].color; continue; }
for (j = 0; j < nc; j++)
if (!strcmp( colors[j], cars[i].color)) goto cdup;
colors[nc++] = cars[i].color;
cdup:;
}
for (i = 0; i < idx; i++) { /* find unique manufacturers */
if (!nm) { manfs[nm++] = cars[i].manf; continue; }
for (j = 0; j < nm; j++)
if (*manfs[j] == *cars[i].manf) goto mdup;
manfs[nm++] = cars[i].manf;
mdup:;
}
/* output unique colors & unique manufacturers */
for (i = 0; i < nc; i++) printf ("%s\n", colors[i]);
putchar ('\n');
for (i = 0; i < nm; i++) printf ("%s\n", manfs[i]);
putchar ('\n');
return 0;
}
注意:如果您没有所有制造商的唯一首字母,则在测试颜色时需要完整的strcmp,而不仅仅是比较第一个字符。
示例输入
$ cat dat/cars.txt
4132 RED ALFA-ROMEO 2005
5230 BLUE FIAT 2004
4321 WHITE NISSAN 2000
5233 BLUE BMW 2001
7300 YELLOW CITROEN 1999
1232 BLUE PEUGEOT 1990
9102 RED VW 1995
1998 YELLOW ALFA-ROMEO 2004
5333 WHITE VW 1999
6434 BLUE NISSAN 2000
8823 BLACK MERCEDES 2003
4556 BLACK SEAT 1997
1554 RED MERCEDES 2001
6903 YELLOW NISSAN 2000
7093 BLACK FIAT 1978
1023 WHITE VW 1998
3422 BLUE SEAT 2005
3555 RED BMW 2004
6770 YELLOW SEAT 2002
使用/输出示例
$ ./bin/cars <dat/cars.txt
4132 RED ALFA-ROMEO 2005
5230 BLUE FIAT 2004
4321 WHITE NISSAN 2000
5233 BLUE BMW 2001
7300 YELLOW CITROEN 1999
1232 BLUE PEUGEOT 1990
9102 RED VW 1995
1998 YELLOW ALFA-ROMEO 2004
5333 WHITE VW 1999
6434 BLUE NISSAN 2000
8823 BLACK MERCEDES 2003
4556 BLACK SEAT 1997
1554 RED MERCEDES 2001
6903 YELLOW NISSAN 2000
7093 BLACK FIAT 1978
1023 WHITE VW 1998
3422 BLUE SEAT 2005
3555 RED BMW 2004
6770 YELLOW SEAT 2002
RED
BLUE
WHITE
YELLOW
BLACK
ALFA-ROMEO
FIAT
NISSAN
BMW
CITROEN
PEUGEOT
VW
MERCEDES
SEAT
注意:这只是为了让您入门。您仍然必须使用数据,但是您的任务的其余部分需要,但这里有一种方法可以将其以可管理的形式获取。如果您有任何问题,请告诉我。
简化版打印不重复颜色和制造商
我想到了您遇到的困难以及知道您需要多少细节的基本问题源于不知道您最终将如何使用您的数据。最初,您需要一种方法来识别数据文件中的独特颜色和制造商。第一个代码将所有数据分成独特的颜色和制造商集合,但由您来实现您需要完成的工作。但是,如果您只需要输出由唯一制造商提供的具有唯一颜色的汽车列表,那么您根本不需要存储结构数组,您只需打印具有唯一颜色/制造商的那些车辆,直到达到重复项。这可以通过以下简化方式完成:
#include <stdio.h>
#include <string.h>
/* constants for max name, chars & structs */
enum { MAXN = 16, MAXC = 64 };
int main (int argc, char **argv) {
char colors[MAXN][MAXN] = {{0}}, manfs[MAXN][MAXN] = {{0}};
char buf[MAXC] = "";
size_t i, nc = 0, nm = 0;
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;
}
while (fgets (buf, MAXC, fp)) { /* read each line */
int tid, tyr; /* temp variables */
char tcol[MAXC] = "", tman[MAXC] = "";
/* separate into temp variables, validate, copy to struct */
if (sscanf (buf, " %d %s %s %d%*c", &tid, tcol, tman, &tyr) == 4) {
if (!nc) /* 1st color - add it */
strcpy (colors[nc++], tcol);
else {
for (i = 0; i < nc; i++) /* compare against stored colors */
if (!strcmp (colors[i], tcol)) /* duplicate */
goto dupe; /* skip it */
strcpy (colors[nc++], tcol); /* add it */
}
if (!nm) /* do the same for manufacturers */
strcpy (manfs[nm++], tman);
else {
for (i = 0; i < nm; i++)
if (!strcmp (manfs[i], tman))
goto dupe;
strcpy (manfs[nm++], tman);
} /* if not a duplicate, print the vehicle */
printf ("%4d %-6s %-10s %d\n", tid, tcol, tman, tyr);
dupe:;
}
}
if (fp != stdin) fclose (fp);
return 0;
}
使用/输出示例
$ ./bin/cars2 <dat/cars.txt
4132 RED ALFA-ROMEO 2005
5230 BLUE FIAT 2004
4321 WHITE NISSAN 2000
7300 YELLOW CITROEN 1999
8823 BLACK MERCEDES 2003
看看做了什么。读取每一行并分离值。如果颜色或制造商数组为空,则添加第一个颜色/制造商。对于所有其他人,当前颜色或制造商将与之前的所有颜色或制造商进行比较,如果重复,则跳过该车的打印。如果您还有其他问题,请告诉我。