将制表符分隔的文件读取到C中的结构

将制表符分隔的文件读取到C中的结构,c,file,input,struct,tab-delimited-text,C,File,Input,Struct,Tab Delimited Text,我有一个带有制表符分隔数据的文件。我想把每一行读成一个结构。我有一个将数据读取到char缓冲区的代码。但是我想把数据加载到一个结构中 这是我的样本数据 empname1\t001\t35\tcity1 empname2\t002\t35\tcity2 我的结构定义 struct employee { char *empname; char *empid; int age; char *addr; }; 我的示例程序将数据读取到chararraybuffer char buff

我有一个带有制表符分隔数据的文件。我想把每一行读成一个结构。我有一个将数据读取到char缓冲区的代码。但是我想把数据加载到一个结构中

这是我的样本数据

empname1\t001\t35\tcity1

empname2\t002\t35\tcity2

我的结构定义

struct employee
{
  char *empname;
  char *empid;
  int age;
  char *addr;

};
我的示例程序将数据读取到
char
array
buffer

char buffer[BUF_SIZE];      /* Character buffer */
    input_fd = open (fSource, O_RDONLY);
    if (input_fd == -1) {
       perror ("open");
        return 2;
    }
                    
    while((ret_in = read (input_fd, &buffer, BUF_SIZE)) > 0){
                    
         // Do Some Process 
    }

这里我想将内容加载到结构变量,而不是字符缓冲区。我怎样才能做到这一点呢?

嗯,一个可能的解决办法是

  • 使用从文件中读取完整的行

  • 根据所需的分隔符[
    选项卡
    在您的情况下]使用标记化输入缓冲区

  • 将内存()分配给结构的指针变量

  • 将标记化输入复制到成员变量中

  • 注: 1.
    fgets()
    读取并存储尾部的
    \n
    。 2.请仔细检查如何使用strtok()。输入字符串应该是可变的。 3.在使用指针之前将内存分配给指针。在我看来,使用静态分配的数组作为
    struct employee
    成员变量。

    您可以使用fscanf功能。以流形式打开一个文件,然后使用fscanf从该文件获取输入

    int fscanf(FILE *stream, const char *format, ...);
    FILE *fp=fopen(fsource,"r+");
    struct employee detail;
    fscanf(fp,"%s %s %d %s",detail.empname,detail.empid,&detail.age,detail.addr);
    
    确保为变量分配内存


    或者您可以使用
    strok
    功能。那时候你必须使用sscanf功能。

    我想这可能就是你想要的

    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    #include <sys/stat.h>
    
    struct employee
    {
    char *empname;
    char *empid;
    int age;
    char *addr;
    
    };
    
    int readEmploee(char *line, struct employee *employee)
    {
        char *token;
        char *saveptr;
        char *endptr;
    
        if ((employee == NULL) || (line == NULL))
            return 0;
    
        token = strtok_r(line, "\t", &saveptr);
        if (token == NULL)
            return 0;
        employee->empname = strdup(token);
    
        token = strtok_r(NULL, "\t", &saveptr);
        if (token == NULL)
            return 0;
        employee->empid = strdup(token);
    
        token = strtok_r(NULL, "\t", &saveptr);
        if (token == NULL)
            return 0;
        employee->age = strtol(token, &endptr, 10);
        if (*endptr != '\0')
            return 0;
    
        token = strtok_r(NULL, "\t", &saveptr);
        if (token == NULL)
            return 0;
        employee->addr = strdup(token);
    
        return 1;
    }
    
    char *mygetline(int fd)
    {
        char  *line;
        size_t length;
        size_t count;
        char   character;
    
        line = malloc(128);
        if (line == NULL)
            return NULL;
        length = 0;
        count  = 1;
        do
        {
            if (read(fd, &character, 1) != 1) /* end of file probably reached */
            {
                free(line);
                return NULL;
            }
            else if (character != '\n')
            {
                if (length > 128 * count)
                {
                    char *temp;
                    temp = realloc(line, 128 * count);
                    if (temp == NULL)
                    {
                        free(line);
                        return NULL;
                    }
                    line   = temp;
                    count += 1;
                }
                line[length++] = character;
            }
        } while (character != '\n');
        line[length] = 0;
    
        return line;
    }
    
    struct employee *readFile(const char *const fSource, size_t *count)
    {
        struct employee *employees;
        int              employeeCount;
        int              input_fd;
        char            *line;
    
        if ((count == NULL) || (fSource == NULL))
            return NULL;
    
        *count        = 0;
        employees     = NULL;
        employeeCount = 0;
        input_fd      = open (fSource, O_RDONLY);
        if (input_fd == -1)
        {
            perror ("open");
            return NULL;
        }
    
        while ((line = mygetline(input_fd)) != NULL)
        {
            struct employee employee;
            if (readEmploee(line, &employee) != 0)
            {
                struct employee *temp;
    
                temp = realloc(employees, (1 + employeeCount) * sizeof(struct employee));
                if (temp != NULL)
                    employees = temp;
                employees[employeeCount++] = employee;
            }
            free(line);
        }
        *count = employeeCount;
    
        return employees;
    }
    
    int
    main()
    {
        size_t           count;
        size_t           index;
        struct employee *employees;
    
        employees = readFile("somesamplefile.txt", &count);
        if (employees == NULL)
            return 1;
        for (index = 0 ; index < count ; index++)
        {
            struct employee current;
    
            current = employees[index];
    
            fprintf(stderr, "%s, %s, %d, %s\n", current.empname, current.empid, current.age, current.addr);
            if (current.empname != NULL)
                free(current.empname);
            if (current.empid != NULL)
                free(current.empid);
            if (current.addr != NULL)
                free(current.addr);
        }
        free(employees);
        return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    结构雇员
    {
    字符*empname;
    char*empid;
    智力年龄;
    char*addr;
    };
    int reademployee(字符*行,结构雇员*雇员)
    {
    字符*令牌;
    char*saveptr;
    char*endptr;
    if((employee==NULL)| |(line==NULL))
    返回0;
    令牌=strtok_r(第“\t”行和saveptr);
    if(标记==NULL)
    返回0;
    employee->empname=strdup(令牌);
    令牌=strtok_r(NULL、\t、&saveptr);
    if(标记==NULL)
    返回0;
    employee->empid=strdup(令牌);
    令牌=strtok_r(NULL、\t、&saveptr);
    if(标记==NULL)
    返回0;
    员工->年龄=strtol(令牌和endptr,10);
    如果(*endptr!='\0')
    返回0;
    令牌=strtok_r(NULL、\t、&saveptr);
    if(标记==NULL)
    返回0;
    员工->地址=strdup(令牌);
    返回1;
    }
    字符*mygetline(int-fd)
    {
    字符*行;
    尺寸与长度;
    大小/数量;
    字符;
    直线=malloc(128);
    如果(行==NULL)
    返回NULL;
    长度=0;
    计数=1;
    做
    {
    如果(读取(fd,&字符,1)!=1)/*可能已到达文件结尾*/
    {
    自由线;
    返回NULL;
    }
    else if(字符!='\n')
    {
    如果(长度>128*计数)
    {
    字符*温度;
    temp=realloc(行,128*计数);
    if(temp==NULL)
    {
    自由线;
    返回NULL;
    }
    线路=温度;
    计数+=1;
    }
    行[长度++]=字符;
    }
    }while(字符!='\n');
    行[长度]=0;
    回流线;
    }
    结构employee*读取文件(常量字符*常量源,大小*计数)
    {
    结构雇员*雇员;
    国际雇员人数;
    int-input_-fd;
    字符*行;
    if((count==NULL)| |(fSource==NULL))
    返回NULL;
    *计数=0;
    employees=NULL;
    雇员人数=0;
    input_fd=打开(仅限fSource、O_rdu);
    如果(输入_fd==-1)
    {
    佩罗(“公开”);
    返回NULL;
    }
    while((line=mygetline(input_fd))!=NULL)
    {
    结构员工;
    如果(读员工(行和员工)!=0)
    {
    结构雇员*临时雇员;
    temp=realloc(员工,(1+员工人数)*sizeof(结构员工));
    如果(温度!=NULL)
    雇员=临时工;
    员工[employeeCount++]=员工;
    }
    自由线;
    }
    *计数=雇员计数;
    返回员工;
    }
    int
    main()
    {
    大小/数量;
    尺寸指数;
    结构雇员*雇员;
    employees=readFile(“somesamplefile.txt”、&count);
    if(employees==NULL)
    返回1;
    对于(索引=0;索引<计数;索引++)
    {
    结构员工当前;
    当前=员工[索引];
    fprintf(stderr,“%s,%s,%d,%s\n”,current.empname,current.empid,current.age,current.addr);
    if(current.empname!=NULL)
    自由(当前.empname);
    如果(current.empid!=NULL)
    自由(当前的empid);
    如果(current.addr!=NULL)
    自由(当前地址);
    }
    免费(员工);
    返回0;
    }
    
    您可以使用
    fscanf
    读取文件中的每一行,使用
    strtok
    标记读取的行。
    因为您的结构成员是指针,所以适当地分配内存

    下面的最小代码正是您想要的

    #define SIZE 50 
    FILE *fp = NULL;                                                            
    int i = 0;                                                                  
    struct employee var = {NULL, NULL, 0, NULL};                                
    char line[SIZE] = {0}, *ptr = NULL;   
    
    /* 1. Open file for Reading */                                                 
    if (NULL == (fp = fopen("file.txt","r")))                                   
    {                                                                           
        perror("Error while opening the file.\n");                              
        exit(EXIT_FAILURE);                                                     
    }
    


    工作演示:

    这里需要注意的几点:

  • 只要您的结构定义(和成员顺序)保持不变(请参见值的操作
    i
    ),这就可以保证工作正常
  • strtok(行“\\”)
    ,第二个参数只是转义(第一个
    \
    )实际的
    \
    字符

  • OP的澄清:

    在您的结构定义中,第三个成员是
    int
    ,但是您试图将
    t35
    读入其中(这是一个字符串)。
    因此
    var.age=atoi(ptr)将为您提供
    0

    您可以更改结构定义,将第三个成员设置为
    char*
    ,并像其他成员一样分配内存

    或更改文件内容,确保
    /* 2. Allocate Memory */                                                       
    var.empname = malloc(SIZE);                                                 
    var.empid = malloc(SIZE);                                                   
    var.addr = malloc(SIZE); 
    
    /* 3. Read each line from the file */   
    while (EOF != fscanf(fp, "%s", line))                                       
    {                                                                           
        /* 4. Tokenise the read line, using "\" delimiter*/                     
        ptr = strtok(line, "\\");                                                                                   
        var.empname = ptr;                                                      
    
        while (NULL != (ptr = strtok(NULL, "\\")))                              
        {                                                                       
            i++;                                                                
    
            /* 5. Store the tokens as per structure members , where (i==0) is first member and so on.. */
            if(i == 1)                                                          
                var.empid = ptr;                                                
            else if(i == 2)                                                     
                var.age = atoi(ptr);                                            
            else if (i == 3)                                                    
                var.addr = ptr;                                                 
        }                                                                       
    
        i = 0;        /* Reset value of i */                                                          
        printf("After Reading: Name:[%s] Id:[%s] Age:[%d] Addr:[%s]\n", var.empname, var.empid, var.age, var.addr);
    }