Read a tab delimited file in a structure in C

I have a tab delimited data file. I want to read each line in a Structure. I have some code to read data into a char buffer. But I want to load data into a structure.

This is my sample data.

empname1 \ t001 \ t35 \ tcity1

empname2 \ T002 \ t35 \ tcity2

Defining my structure.

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

};

      

My example program to read data into an array char

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 
    }

      

Here I want to load content into a structure variable instead of a character buffer. How can I achieve this?

+3


source to share


4 answers


Well, a possible solution might be



Note: 1. fgets()

reads and saves the final \n

. 2. Please study carefully how to use strtok()

. The input string must be mutable. 3. Allocate memory with pointers before using them. IMO, use a statically allocated array as member variables struct employee

.

+7


source


You can use the fscanf function. Open the file as a stream and then use fscanf to get input from the file.

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);

      



Make sure to allocate memory for variables.

Or you can use a function strtok

. This time you should use the sscanf function.

+2


source


You can use fscanf

to read each line from a file strtok

to tokenize the read line.
Since your structure members are pointers, allocate memory appropriately.

The following minimal code does exactly what you want.

#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);                                                     
}

      


/* 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);
}                                                                           

      

Working demo: http://ideone.com/Kp9mzN

A bit about what here:

  • This is guaranteed to work as long as your structure definition (and member order) remains the same (see value manipulation i

    ).
  • strtok(line, "\\");

    ... The second argument just escapes the (first \

    ) actual character \

    .

Clarification from OP:

In your structure definition, the third member is int

, however you are trying to read t35

in it (which is a string).
Therefore it var.age = atoi(ptr);

will give you 0

,

You can change the definition of a structure by making the third element the same char *

and allocating memory like the other members.

Or change the content of the file, making sure it is present as the third value int

.

+2


source


I think this might be what you are looking for

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

      

+1


source







All Articles