harunB10
harunB10

Reputation: 5207

How to parse table from txt file in C variables?

I have a text file in this format:

#Name                #Company             #ID
Name1                Brand1               1234
Name2                Brand2               5678

And a struct:

struct MyStruct{
  char name[TEXT_LEN];
  char company[TEXT_LEN];
  char ID[TEXT_LEN];
};
typedef struct MyStruct Data_t;

What I want... is to load the data from text file in appropriate variables. It should ignore first line because those are headers...

This is what I've been trying so far but without success:

int loadDataFromFile(Data_t *items, long len, char *inputFile)
{
  FILE *fp;

  if ((fp = fopen(inputFile, "r")))
  {
    for (long i = 0; i < len; i++)
    {
      /*fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);*/
     //this is commented part was not working part... More about this in EDIT
     fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);
     printf("Name: %s", items[i].name); // For first item it prints:
                                        // Name: #Name

    }
  }

  return 0;
}

What is wrong here?

EDIT

I've replaced the code but now it reads first line as well. Is there a way to ignore header of file (first line)?

Upvotes: 0

Views: 166

Answers (3)

user3629249
user3629249

Reputation: 16540

the following proposed code:

  1. cleanly compiles
  2. performs the desired functionality
  3. properly discards the first line of the input file (the column headers)
  4. properly checks for errors
  5. properly checks that the data array is not overflowed
  6. assures the fields in the data array are not overflowed when calling sscanf()
  7. properly assures the input file can be read

and now, the proposed code:

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

#define TEXT_LEN 21

struct MyStruct
{
    char name[TEXT_LEN];
    char company[TEXT_LEN];
    char ID[TEXT_LEN];
};
typedef struct MyStruct Data_t;


long loadDataFromFile( Data_t *items, long len, char *inputFile )
{
    FILE *fp = fopen(inputFile, "r");
    if( ! fp )
    {
        perror( "fopen to read file failed" );
        exit( EXIT_FAILURE );
    }

    // read/discard first line:
    char buffer[1024];
    if( ! fgets( buffer, sizeof( buffer ), fp ) )   // column header line
    {
        perror( "fgets failed to read column headers from input file" );
        exit( EXIT_FAILURE );
    }

    long i = 0;
    while( i < len && fgets( buffer, sizeof( buffer ), fp ) )
    {   
        if( sscanf(buffer, "%20s %20s %20s", items[i].name, items[i].company, items[i].ID) != 3 )
        {
            break;
        }

        printf("Name: %s", items[i].name); 
        i++;
    }

    return i;
}

Upvotes: 1

srilakshmikanthanp
srilakshmikanthanp

Reputation: 2399

Try This,

#include <stdio.h>

#define TEXT_LEN 100

typedef struct 
{

  char name[TEXT_LEN];
  char company[TEXT_LEN];
  char ID[TEXT_LEN];

}Data_t;

int loadDataFromFile(Data_t *items, long len, char *inputFile)  // change len as unsigned
{
  FILE *fp;
  char ch;
  long i;

  if ( ( fp = fopen(inputFile, "r") ) )
  {

    while( ( ch = getc(fp) != '\n') && ch!=EOF );   //To ignore first line
    printf("Reading...\n");

    for (i = 0; i < len && (fscanf(fp, "%s %s %s", items[i].name, items[i].company, items[i].ID) == 3); i++)
    {
        printf("\n#Name: %s #Company: %s #ID: %s", items[i].name, items[i].company, items[i].ID);
    }

  }
  else
  {
      printf("File Error");
      return 0;
  }


  return i;
}

int main()
{
    Data_t data[2];
    int n;

    if(n=loadDataFromFile(data,2,"Txt"))   //2 is number of line
    {
        printf("\n\nReaded !\n");

        for(int i=0;i<n;i++)
            printf("\n#Name: %s #Company: %s #ID: %s",data[i].name,data[i].company,data[i].ID);

    }

    return 0;
}

Txt:

#Name                #Company             #ID
Name1                Brand1               1234
Name2                Brand2               5678

Output:

Reading...

#Name: Name1 #Company: Brand1 #ID: 1234
#Name: Name2 #Company: Brand2 #ID: 5678

Readed !

#Name: Name1 #Company: Brand1 #ID: 1234
#Name: Name2 #Company: Brand2 #ID: 5678
[Done] exited with code=0 in 1.227 seconds

Upvotes: 1

Massaynus
Massaynus

Reputation: 452

you coult try changin

fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);

to

fscanf(fp, "%s\t%s\t%s\n", items[i].name, items[i].company, items[i].ID);

and also iterating on the file lines could be done better by using something like this

while (!EOF) {/*Code*/}

Upvotes: 0

Related Questions