简体   繁体   English

解析 C 中的制表符分隔文本文件

[英]Parsing a tab delimited text file in C

so, i saw an older post that showed how to do this, but for some reason it seems it no longer works, my input file consists of a header row, and then 15 rows of input, each with 5 columns, first 2 are strings, the last 3 are ints, i have a struct to store them, and im trying to write the contents into an array of these structs所以,我看到一篇较旧的帖子显示了如何执行此操作,但由于某种原因,它似乎不再有效,我的输入文件由 header 行组成,然后是 15 行输入,每行有 5 列,前 2 行是字符串,最后3个是整数,我有一个结构来存储它们,我试图将内容写入这些结构的数组

FName LName Credits Transactions Modifer
John Doe    83000   2   1
Jane Doe    64000   5   3

I tried我试过了

    struct customer cust = { NULL,NULL,0,0,0};
    char line[SIZE] = { 0 }, * ptr = NULL;
    cust.fName = malloc(15);
    cust.lName = malloc(15);
    printf("%d\n", &fp);
    if (NULL == (fp = fopen("../customers.txt", "r")))
    {
        perror("Error while opening the file.\n");
        exit(EXIT_FAILURE);
    }
    while (EOF != fscanf(fp, "%s", line))
    {
        ptr = strtok(line, "\\");
        cust.fName = ptr;
        printf("%s", ptr);
        while (EOF != (ptr = strtok(NULL, "\\")))
        {
            i++;
            printf("%s",ptr);
            if (i == 1)
                cust.lName = ptr;
            else if (i == 2)
                cust.miles = atoi(ptr);
            else if (i == 3)
                cust.years = atoi(ptr);
            else if (i == 4)
                cust.sequence = atoi(ptr);
        }

        i = 0;
        printf("After Reading: fName:[%s] lName:[%s] miles:[%d] years:[%d]\n", cust.fName, cust.lName, cust.miles, cust.years);
    }

For some reason, the printf within the inner while loop only prints "(null)" , and errors out when i==2 with the error出于某种原因,内部 while 循环中的printf仅打印"(null)" ,并且当i==2出现错误时出错

File: minkernel\crts\ucrt\inc\corecrt_internal_strtox.h
Line: 1772

Expression: _p != nullptr

I dont have any idea what that error message means, so i dont know what im doing wrong我不知道该错误消息是什么意思,所以我不知道我做错了什么

Also, Craig, do you mind giving an example, im pretty new to using C and am unfamiliar with fgets另外,克雷格,你介意举个例子吗,我对使用 C 很陌生,我不熟悉 fgets

Okay.好的。 Because your code was a bit far off, I had to refactor it heavily.因为你的代码有点远,我不得不大量重构它。

Your code was only handling a single customer record.您的代码只处理一个客户记录。 What you need to do is a separate struct instance for each line (ie customer).您需要做的是为每一行(即客户)创建一个单独的struct实例。 So, we want to use realloc to enlarge a dynamic array of our struct customer .因此,我们想使用realloc来扩大我们的struct customer的动态数组。

And, you have allocate memory [on the heap] for each string in a record (ie first and last names).而且,您已经为记录中的每个字符串(即名字和姓氏)分配了 memory [在堆上]。 So, we have to use strdup所以,我们必须使用strdup

Anyway, here's the code:无论如何,这是代码:

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

struct customer {
    char *fName;
    char *lName;
    int miles;
    int years;
    int sequence;
};

int
main(void)
{
    FILE *fp;
    char buf[1000];
    char *cp;
    char *bp;
    struct customer *list = NULL;
    int custcnt = 0;
    struct customer *cust;
    const char *delim = "\t\n";
    int field;

    fp = fopen("customers.txt","r");
    if (fp == NULL) {
        perror("error opening file");
        exit(1);
    }

    while (1) {
        cp = fgets(buf,sizeof(buf),fp);
        if (cp == NULL)
            break;

        // increase size of customer list/array by one
        list = realloc(list,sizeof(*list) * (custcnt + 1));
        if (list == NULL) {
            perror("malloc");
            exit(1);
        }

        // point to place for next customer
        cust = &list[custcnt];

        // advance customer count
        ++custcnt;

        // preclear the new record in case of a line that is malformed (i.e.
        // missing some data)
        memset(cust,0,sizeof(*cust));

        // loop through and store all customer record fields
        bp = buf;
        for (field = 0;  field < 5;  ++field) {
            cp = strtok(bp,delim);
            if (cp == NULL)
                break;
            bp = NULL;

            switch (field) {
            case 0:
                cust->fName = strdup(cp);
                break;

            case 1:
                cust->lName = strdup(cp);
                break;

            case 2:
                cust->miles = atoi(cp);
                break;

            case 3:
                cust->years = atoi(cp);
                break;

            case 4:
                cust->sequence = atoi(cp);
                break;
            }
        }

        printf("After Reading: fName:[%s] lName:[%s] miles:[%d] years:[%d]\n",
            cust->fName, cust->lName, cust->miles, cust->years);
    }

    fclose(fp);

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM