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

标签 c

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

文件看起来像这样:

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 

我想做这个。 示例:

Locations[i]={"BERLIN","BERLIN","BUCHAREST","NEW_YORK"."BERLIN","BUCHAREST"}
TOYS[j]={"CAR","CAR","JACKET","DOLL","ROBOT","BALL"}
NUMBER[k]={1,1,2,7,5,4}
LETTER[l]={'U','R','D','U','L','L'}

到目前为止我的代码(MAX_STRING_LENGTH 定义为 30):

int i;
char *p,**a,delim[]=" ";
a=malloc(100 * sizeof(char));
for(i = 0; i < 100; i++)
{
    a[i]=calloc(MAX_STRING_LENGTH,sizeof(char));
}
while(!feof(stdin))
{
    fgets(*a,500,stdin);
    p=strtok(*a,delim);
}

最佳答案

strtok是正确的功能,但是您使用它是错误的。

man strtok

The strtok() function breaks a string into a sequence of zero or more nonempty tokens. On the first call to strtok(), the string to be parsed should be specified in str. In each subsequent call that should parse the same string, str must be 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(<data type>)malloc/calloc/realloc电话。很容易忽略 *和做 错误。更好:

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

// or

int *mayarray = calloc(size, sizeof *myarray);

使用 sizeof *var更好,因为它总是会返回正确的尺寸。

最后一件事:

while(!feof(stdin))

参见 Why is “while ( !feof (file) )” always wrong?

更好

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

编辑

这里有一个使用 strtok 的示例实现.我的实现使用 MAP 的数组秒。看看我构造/破坏 MAP 的方式对象以及内存是如何分配的。显然,这可以用更少的代码和更少的代码来完成 strdup s,但我认为这更准确地展示了如何使用这些功能。您可以将此代码用作您的基础或仅将其用作基本想法。

#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
---

关于c - 如何在c中按行或列拆分文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48157653/

相关文章:

c - c 中用户定义的通用快速排序

c - C 中的结构/链表/指针/字符串

c - GCC 8 for ARM 在 LTO 模式下正在删除中断处理程序和弱函数 - 如何防止它?

C Gameboy 独立函数和主文件

ios - 使用 ARC 将 NSArray 转换为 C 数组

c - 如何处理与 Telnet 服务器的 Telnet session

c - 为什么我可以将负数导入为 int,而不是 long int 或其他更大的数据类型?

c - 有效地将一个字符串插入另一个字符串

将索引从自定义字母表转换为序列

c - C 中的 get_symbol 函数