【问题标题】:Printing part of a .txt file [closed]打印 .txt 文件的一部分 [关闭]
【发布时间】:2016-05-29 20:26:04
【问题描述】:

再次您好,如果这是重复的,请提前道歉,但我很绝望,我只需要问一下!

我正在为一个学校项目编写一个 c 程序,我快完成了,但我卡住了。 我有一个 txt 文件,如图所示: cars.txt

此时我需要做的是打印列出的颜色,但每种不同的颜色只能打印一次。 汽车制造商也是如此,但那是以后的事了。

我完全没有想法...任何帮助将不胜感激...

【问题讨论】:

  • 将所有值读取到结构数组中,然后为颜色和制造商创建单独的指针数组,这些指针数组指向结构数组中每个元素的唯一出现并打印它们。
  • 我明白你在说什么,但我不知道如何创建指针数组......如果你能提供更多帮助,我将不胜感激...... .. @David C. Rankin
  • 我会在一分钟内给你一个简短的回顾。
  • 你会是我的救星!!!
  • @DavidC.Rankin 请不要忘记我 :(

标签: c string file


【解决方案1】:

好的,从评论继续,正如评论中所述,对于任何数据处理问题,您需要做的第一件事是将所有数据读入一个允许您根据需要使用它的表单.在这里,您有不同类型的数据,它们都构成一个单元(在这种情况下是汽车)。每当您必须将不同类型的数据作为一个单元处理时,您都应该考虑 struct.这里的结构 car 是有意义的:

typedef struct {    /* struct for cars */
    int id;
    char color[MAXN];
    char manf[MAXN];
    int year;
} car;

您现在可以将数据文件中的每一行读入一个数组或struct car,并为您的其余代码提供所有数据。

当您有 数据时,您应该考虑 面向行 输入,例如fgetsgetline。虽然您可以在此处使用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

看看做了什么。读取每一行并分离值。如果颜色或制造商数组为空,则添加第一个颜色/制造商。对于所有其他人,当前颜色或制造商将与之前的所有颜色或制造商进行比较,如果重复,则跳过该车的打印。如果您还有其他问题,请告诉我。

【讨论】:

  • 非常感谢您为此付出的努力,但恐怕我在这以下几个级别......我几乎无法理解其中的一半。我确实使用了一个结构,尽管其中的所有数组都是 char 类型。我尝试使用 strtok() 获取 txt 中每一行的颜色部分,它可以很好地以更有条理的方式打印文件,但由于某种原因,有一个带有颜色的字符串数组是一个问题......
  • 然后使用我使用的结构数组,我尝试了相同的操作,并使用 2 个 for 循环尝试仅打印以前未打印过的颜色。使用一些调试 printf s,我可以看到字符串数组正确填充,但由于某种原因,它会在 for 循环中打印随机符号....
  • 哦,不好意思,struct的数组你看懂了吗?如果是这样,你就完成了困难的部分。指针数组只会填充前 X 个元素,其中 X 是唯一颜色/制造商的数量。指针数组就是指针的集合(例如 colors[0], colors[1], etc.. 而不是 p1, p2, p3, ... 在每种情况下,它们都指向结构数组中颜色或制造商的第一次出现。如果您查看 @ 的地址987654338@(黑色),您会看到它指向与cars[10].color(第一个黑色)相同的地址。
  • 您可以将结构数组与所有char [] 成员一起使用,将数字视为数字似乎更自然。如果您查看sscanf 调用,那与strtok 所做的相同。 sscanf 方法更直接一些。无论如何,目标是获取结构数组中的值。您可以以任何您选择的方式找到独特的颜色/manf,我只是遍历结构数组并选择每个的第一次出现并跳过其余的。 if (!nc).. 只是选择第一种颜色(此时不能有任何欺骗)。
  • 好吧,尽管你的代码对我来说有点高级(而且我的老师会非常怀疑)你最后 2 个 cmets 让我朝着正确的方向前进。再次感谢您的所有努力!
【解决方案2】:

该程序读取格式如您所示的文件,并删除重复的颜色。该技术与删除其他重复项相同。我用这样的文件进行测试

4132 RED ALFA ROMERO 2005
1234 BLUE FIAT BLAHOGA 2032
4132 RED ALFA ROMERO 2005
1234 ORANGE FIAT BLAHOGA 2032
4132 RED ALFA ROMERO 2005
1234 BLACK FIAT BLAHOGA 2032
1234 ORANGE FIAT BLAHOGA 2032
1234 ORANGE FIAT BLAHOGA 2032

程序:

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

void rmdup(char *resentence) {
    char *temp1 = malloc(100);
    char *temp = NULL;

    *temp1 = 0;
    temp = strtok(resentence, " ");

    if (temp != NULL) {// && strstr(temp1, temp) == NULL)
        strcpy(temp1, temp);
        while ((temp = strtok(NULL, " ")) != NULL) {
            if (strstr(temp1, temp) == NULL) {
                strcat(temp1, " ");
                strcat(temp1, temp);
            }
        }
    }
    strcpy(resentence, temp1);
    puts(resentence);
    free(temp1);
}

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

    ssize_t read;
    char *line = NULL;
    size_t len = 0;
    FILE *fp;

    fp = fopen("file.txt", "r");

    char str[80];
    strcpy(str, "");
    while ((read = getline(&line, &len, fp)) != -1) {
        char * date2 = strtok(line, " ");
        date2 = strtok(NULL, " ");
        strcat(str, strdup(date2));
        strcat(str, " ");
    }
    fclose(fp);

    rmdup(str);
    printf("after: %s", str);

    exit(0);
}

输出

after: RED BLUE ORANGE BLACK

你看到的输出只有独特的颜色。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    相关资源
    最近更新 更多