打印.txt文件的一部分

时间:2016-05-29 20:26:04

标签: c string file

再次问好,如果这是重复的话,请提前抱歉,但我绝望了,我只想问!

我正在为一个学校项目用c编写一个程序,我差不多完成但是我被卡住了。 我有一个这个图像中显示的txt文件: cars.txt

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

我完全没有想法......我们将非常感谢任何帮助......

2 个答案:

答案 0 :(得分:0)

此程序读取与您显示的格式相同的文件,并删除颜色的副本。删除其他重复项的技术相同。我用这样的文件测试

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

您会看到输出只是唯一的颜色。

答案 1 :(得分:0)

好的,继续发表评论,正如评论中所述,您需要对数据处理问题做的第一件事就是将所有数据读入一个允许您根据需要使用它的表单中。在这里,您可以使用不同类型的数据组成一个单元(在这种情况下为汽车)。每当你必须作为一个单元处理不同类型的数据时,你应该考虑结构。结构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

注意:这只是为了让您入门。您仍然必须使用数据,但是您的其他任务需要,但这是一种以可管理的形式获取它的方法。如果您有任何问题,请告诉我。

简化版打印非重复色彩&amp;制造商

我想到了你遇到的困难以及了解你需要多少细节的基本问题源于不知道你最终如何使用你的数据。最初,您需要一种方法来识别数据文件中的独特颜色和制造商。第一个代码将所有数据分成独特的颜色和制造商集合,但由您自行完成所需的工作。但是,如果您只需要由独特制造商输出具有独特颜色的汽车列表,那么您根本不需要存储一系列结构,只需打印具有独特颜色/制造商的车辆,直到达到重复。这可以通过以下简化方式完成:

#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

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