如何在c中按行或列拆分文件

如何在c中按行或列拆分文件,c,C,我试图将文件中的一行分割成由一个空格分隔的不同部分,但它不起作用。。。所以我的问题是:我如何将我的行分割成不同的部分,并对文件的每一行进行分割,然后将这些部分放入动态分配的向量/矩阵中?或者也可以按列。告诉我你认为合适的 该文件如下所示: BERLIN CAR 1 U BERLIN CAR 1 R BUCHAREST JACKET 2 D NEW_YORK DOLL 7 U BERLIN ROBOT 5 L BUCHAREST BALL 4 L 我想这样做。 例如: 到

我试图将文件中的一行分割成由一个空格分隔的不同部分,但它不起作用。。。所以我的问题是:我如何将我的行分割成不同的部分,并对文件的每一行进行分割,然后将这些部分放入动态分配的向量/矩阵中?或者也可以按列。告诉我你认为合适的

该文件如下所示:

BERLIN CAR 1 U        
BERLIN CAR 1 R 
BUCHAREST JACKET 2 D
NEW_YORK DOLL 7 U 
BERLIN ROBOT 5 L 
BUCHAREST BALL 4 L 
我想这样做。 例如:

到目前为止我的代码(最大字符串长度定义为30):

inti;
字符*p,**a,delim[]=”;
a=malloc(100*sizeof(char));
对于(i=0;i<100;i++)
{
a[i]=calloc(最大字符串长度,sizeof(char));
}
而(!feof(stdin))
{
fgets(*a,500,标准DIN);
p=strtok(*a,delim);
}

strtok
是正确的函数,但您使用的是错误的

曼斯特克

strtok()
函数将字符串分解为零个或多个非空令牌序列。 在第一次调用
strtok()
时,应指定要分析的字符串 在
str
中。在应该解析相同字符串的每个后续调用中,
str
必须为
NULL

我把引文中最重要的部分加粗了

还要记住,如果需要源代码,strtok会修改源代码 之后,你必须复印一份

// assuming that line is either a char[] or char*

char *token = strtok(line, " ");
if(token == NULL)
{
    // error detection
}

while(token = strtok(NULL, " "))
{
    // do the work
}
另外,我建议不要在中使用
sizeof()
malloc
/
calloc
/
realloc
调用。很容易忽略一个
*
,而使 错误。更好:

int *myarray = malloc(size * sizeof *myarray);

// or

int *mayarray = calloc(size, sizeof *myarray);
使用
sizeof*var
更好,因为它总是返回正确的大小

最后一件事:

while(!feof(stdin))

更好

char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
    // do the work here
}

编辑

这里有一个使用
strtok
的示例实现。我的实现使用
MAP
s的数组。看看我构造/销毁
MAP
对象的方式,以及内存是如何分配的。显然,这可以用更少的代码和更少的strdup来实现,但我认为这更准确地说明了如何使用这些函数。您可以将此代码用作基础,也可以将其用作基本想法

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

typedef struct{
    char *destination;
    char *type_present;
    int no_available_presents;
    char *direction;
} MAP;

MAP *create_map(const char *dest, const char *type, int present, const char *dir);
void free_map(MAP *map);
void print_map(MAP *map);


MAP *create_map(const char *dest, const char *type, int present, const char *dir)
{
    MAP *map = calloc(1, sizeof *map);
    if(map == NULL)
        return NULL;

    int errors = 0;

    if(!(map->destination = strdup(dest)))
        errors++;

    if(!(map->type_present = strdup(type)))
        errors++;

    if(!(map->direction = strdup(dir)))
        errors++;

    map->no_available_presents = present;

    if(!errors)
        return map;

    free_map(map);
    return NULL;
}

void free_map(MAP *map)
{
    if(map == NULL)
        return;

    free(map->destination);
    free(map->type_present);
    free(map->direction);
    free(map);
}

void print_map(MAP *map)
{
    if(map == NULL)
    {
        puts("(null)");
        return;
    }

    printf("destination: %s\n", map->destination);
    printf("type:        %s\n", map->type_present);
    printf("present:     %d\n", map->no_available_presents);
    printf("direction:   %s\n", map->direction);
}

int main(char argc, char **argv)
{
    FILE *fp;
    if(argc != 1 && argc != 2)
    {
        fprintf(stderr, "usage: %s [database]\n", argv[0]);
        return 1;
    }

    if(argc == 1)
        fp = stdin;
    else
        fp = fopen(argv[1], "r");

    if(fp == NULL)
    {
        fprintf(stderr, "Could not open '%s': %s\n", argv[1], strerror(errno)); 
        return 1;
    }

    MAP **maps = NULL;
    size_t map_len = 0;

    char line[1024];
    const char *delim = " \r\n";

    while(fgets(line, sizeof line, fp))
    {
        int pres;
        char *dest = NULL, *type = NULL, *dir = NULL, *token;

        token = strtok(line, delim);
        dest = strdup(token);

        token = strtok(NULL, delim);
        type = strdup(token);

        token = strtok(NULL, delim);
        pres = atoi(token);

        token = strtok(NULL, delim);
        dir = strdup(token);

        if(dest == NULL || type == NULL || dir == NULL)
        {
            // ignore line
            free(dest);free(type);free(dir);
            continue;
        }

        MAP *new_map = create_map(dest, type, pres, dir);

        if(new_map == NULL)
        {
            // ignore line
            free(dest);free(type);free(dir);
            continue;
        }

        MAP **tmp_map = realloc(maps, (map_len + 1) * sizeof *tmp_map);

        if(tmp_map == NULL)
        {
            // ignore line
            free_map(new_map);
            free(dest);free(type);free(dir);
            continue;
        }

        maps = tmp_map;
        maps[map_len++] = new_map;
        free(dest);free(type);free(dir);
    }

    for(int i = 0; i < map_len; ++i)
    {
        print_map(maps[i]);
        puts("---");
        free_map(maps[i]);
    }

    free(maps);


    if(fp != stdin)
        fclose(fp);

    return 0;
}

while(!feof(stdin)){fgets(*a,500,stdin);
:所以最后一行被标记了两次@Jean-Françoisfare将链接放到著名的why is
while(!feof())
总是错误的。我认为
a=malloc(100*sizeof(char));
的可能重复应该是
a=malloc(100*sizeof(char*));
@BenjaminJ.-第一个分配应该是指向每一行的指针,因此它可能是
a=malloc(100*sizeof(char*));; 59440irst标记。读取函数
fgets
保留输入字符串中的任何换行符。在
strtok
的上下文中,它将通过在定界符字符串中包含换行符来去除该标记,例如
strtok(..,“\n\r”)
@WeatherVane这是个好建议,我从来没有想过要这么做。我通常在做其他事情之前先把
\n
去掉。
char buffer[1024];
while(fgets(buffer, sizeof buffer, stdin))
{
    // do the work here
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

typedef struct{
    char *destination;
    char *type_present;
    int no_available_presents;
    char *direction;
} MAP;

MAP *create_map(const char *dest, const char *type, int present, const char *dir);
void free_map(MAP *map);
void print_map(MAP *map);


MAP *create_map(const char *dest, const char *type, int present, const char *dir)
{
    MAP *map = calloc(1, sizeof *map);
    if(map == NULL)
        return NULL;

    int errors = 0;

    if(!(map->destination = strdup(dest)))
        errors++;

    if(!(map->type_present = strdup(type)))
        errors++;

    if(!(map->direction = strdup(dir)))
        errors++;

    map->no_available_presents = present;

    if(!errors)
        return map;

    free_map(map);
    return NULL;
}

void free_map(MAP *map)
{
    if(map == NULL)
        return;

    free(map->destination);
    free(map->type_present);
    free(map->direction);
    free(map);
}

void print_map(MAP *map)
{
    if(map == NULL)
    {
        puts("(null)");
        return;
    }

    printf("destination: %s\n", map->destination);
    printf("type:        %s\n", map->type_present);
    printf("present:     %d\n", map->no_available_presents);
    printf("direction:   %s\n", map->direction);
}

int main(char argc, char **argv)
{
    FILE *fp;
    if(argc != 1 && argc != 2)
    {
        fprintf(stderr, "usage: %s [database]\n", argv[0]);
        return 1;
    }

    if(argc == 1)
        fp = stdin;
    else
        fp = fopen(argv[1], "r");

    if(fp == NULL)
    {
        fprintf(stderr, "Could not open '%s': %s\n", argv[1], strerror(errno)); 
        return 1;
    }

    MAP **maps = NULL;
    size_t map_len = 0;

    char line[1024];
    const char *delim = " \r\n";

    while(fgets(line, sizeof line, fp))
    {
        int pres;
        char *dest = NULL, *type = NULL, *dir = NULL, *token;

        token = strtok(line, delim);
        dest = strdup(token);

        token = strtok(NULL, delim);
        type = strdup(token);

        token = strtok(NULL, delim);
        pres = atoi(token);

        token = strtok(NULL, delim);
        dir = strdup(token);

        if(dest == NULL || type == NULL || dir == NULL)
        {
            // ignore line
            free(dest);free(type);free(dir);
            continue;
        }

        MAP *new_map = create_map(dest, type, pres, dir);

        if(new_map == NULL)
        {
            // ignore line
            free(dest);free(type);free(dir);
            continue;
        }

        MAP **tmp_map = realloc(maps, (map_len + 1) * sizeof *tmp_map);

        if(tmp_map == NULL)
        {
            // ignore line
            free_map(new_map);
            free(dest);free(type);free(dir);
            continue;
        }

        maps = tmp_map;
        maps[map_len++] = new_map;
        free(dest);free(type);free(dir);
    }

    for(int i = 0; i < map_len; ++i)
    {
        print_map(maps[i]);
        puts("---");
        free_map(maps[i]);
    }

    free(maps);


    if(fp != stdin)
        fclose(fp);

    return 0;
}
destination: BERLIN
type:        CAR
present:     1
direction:   U
---
destination: BERLIN
type:        CAR
present:     1
direction:   R
---
destination: BUCHAREST
type:        JACKET
present:     2
direction:   D
---
destination: NEW_YORK
type:        DOLL
present:     7
direction:   U
---
destination: BERLIN
type:        ROBOT
present:     5
direction:   L
---
destination: BUCHAREST
type:        BALL
present:     4
direction:   L
---